faye-redis-ng 1.0.12 → 1.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 398f99e890ab9d57e91c5f42f93898488c2b1f475f0831d6079e06314a1d4923
4
- data.tar.gz: 7191ecc674147302d1ccce44a612ede961d53709059bd21eb69b28cefe527385
3
+ metadata.gz: 1b5fc029a910d92539d5500a92a851a1b3db0857a5769e6aa9338b8155126cfd
4
+ data.tar.gz: cbf1c670cfe442f7511466f278280db0f8543eee8adcddd9dc0e5ba9a0527667
5
5
  SHA512:
6
- metadata.gz: 3fe20898a79896711f0e003aaf9e6e44baa6b455130260bd6d24ce03424460c140d51a55da29fba63920490e6e04691318e244a48d608ac0f9c6ceeca443f4d7
7
- data.tar.gz: f3317d04d6423963b17dd05d6e24b5f37b9a416da06780c92f118a94e4e42b3116e444cdb0fa18e89e4ef173d524325bd1e2cc0c54bf7235e4733162df740262
6
+ metadata.gz: ae3fb5749855e269fae14583b830bb3d6c55dda8cd90dd28f0bc2fcd4a91c1ca34b89db0a3ac8d7db9343a337653524f84f8b9d7680c089c14e4d42d172ae5f6
7
+ data.tar.gz: 4355fe52a0d572f61640bc1bef644563f1df61d0e37549e8d35d76a64b58eafb0a255570f973453cda769f5e3a47b01715995fcb111eaa10bcf9a5292077e369
data/CHANGELOG.md CHANGED
@@ -7,6 +7,45 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.0.13] - 2025-11-01
11
+
12
+ ### Added - Ping-Based Subscription TTL Refresh
13
+ - **Subscription TTLs now refresh on every ping**: Keeps subscriptions alive as long as client is connected
14
+ - **New behavior**: Each client ping (every ~25s) now refreshes all subscription-related TTLs
15
+ - **Implementation**:
16
+ - Added `SubscriptionManager#refresh_client_subscriptions_ttl` method
17
+ - Modified `Redis#ping` to call subscription TTL refresh
18
+ - Uses pipelined Redis commands for efficient batch TTL updates
19
+ - **Impact**:
20
+ - ✅ Active clients: Subscriptions never expire while connected
21
+ - ✅ Inactive clients: Subscriptions expire 1 hour after last ping (as expected)
22
+ - ✅ Long-lived connections: Chat rooms, dashboards work indefinitely
23
+ - ✅ Prevents silent subscription expiration for active clients
24
+ - **Before**: Subscriptions expired after 1 hour even for active clients
25
+ - **After**: Subscriptions only expire 1 hour after client disconnects
26
+ - **Performance**: Minimal impact - uses single pipelined Redis call per ping
27
+
28
+ ### Design Decision - Message Queue TTL Not Refreshed
29
+ - **Message queue TTL remains fixed at 1 hour**: Does not refresh on ping
30
+ - **Rationale**:
31
+ - Active clients: Messages are immediately delivered, queue is usually empty
32
+ - Empty queues that expire are automatically recreated when needed
33
+ - Inactive clients: 1-hour TTL provides sufficient buffer for reconnection
34
+ - Memory efficiency: Prevents permanent empty queue keys for long-lived connections
35
+ - **Trade-offs**:
36
+ - ✅ Better memory efficiency: Empty queues expire after 1 hour
37
+ - ✅ No functional impact: Messages still delivered normally to active clients
38
+ - ✅ Automatic cleanup: Long-term disconnected clients don't accumulate messages indefinitely
39
+ - **Behavior**:
40
+ - Active client: Queue may expire, but recreates automatically on next message
41
+ - Disconnected < 1 hour: All messages preserved for reconnection
42
+ - Disconnected > 1 hour: Messages cleared to prevent unbounded growth
43
+
44
+ ### Notes
45
+ - Ping-based refresh ensures long-lived connections (chat, real-time dashboards) work correctly
46
+ - Message queue strategy balances reliability with memory efficiency
47
+ - The 1-hour TTL provides ample buffer (60 GC cycles) for cleanup after disconnect
48
+
10
49
  ## [1.0.12] - 2025-11-01
11
50
 
12
51
  ### Changed - Aligned Subscription TTL with Message TTL
@@ -32,11 +71,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
32
71
  - `{namespace}:patterns` (SET)
33
72
  - **Backward compatibility**: Users can still override with custom `subscription_ttl` option
34
73
 
74
+ ### Added - Ping-Based Subscription TTL Refresh
75
+ - **Subscription TTLs now refresh on every ping**: Keeps subscriptions alive as long as client is connected
76
+ - **New behavior**: Each client ping (every ~25s) now refreshes all subscription-related TTLs
77
+ - **Implementation**:
78
+ - Added `SubscriptionManager#refresh_client_subscriptions_ttl` method
79
+ - Modified `Redis#ping` to call subscription TTL refresh
80
+ - Uses pipelined Redis commands for efficient batch TTL updates
81
+ - **Impact**:
82
+ - ✅ Active clients: Subscriptions never expire while connected
83
+ - ✅ Inactive clients: Subscriptions expire 1 hour after last ping (as expected)
84
+ - ✅ Long-lived connections: Chat rooms, dashboards work indefinitely
85
+ - ✅ Prevents silent subscription expiration for active clients
86
+ - **Before**: Subscriptions expired after 1 hour even for active clients
87
+ - **After**: Subscriptions only expire 1 hour after client disconnects
88
+ - **Performance**: Minimal impact - uses single pipelined Redis call per ping
89
+
35
90
  ### Notes
36
91
  - This change ensures subscriptions don't expire before their associated messages
37
- - The 1-hour TTL provides ample buffer (60 GC cycles) for cleanup
92
+ - The 1-hour TTL provides ample buffer (60 GC cycles) for cleanup after disconnect
38
93
  - TTL-safe implementation (v1.0.10) ensures active subscriptions maintain their original TTL
39
94
  - Conservative approach: prioritizes message delivery over aggressive memory optimization
95
+ - Ping-based refresh ensures long-lived connections (chat, real-time dashboards) work correctly
40
96
 
41
97
  ## [1.0.11] - 2025-10-31
42
98
 
@@ -118,6 +118,35 @@ module Faye
118
118
  EventMachine.next_tick { callback.call(false) } if callback
119
119
  end
120
120
 
121
+ # Refresh TTL for all subscription keys related to a client
122
+ # Called during ping to keep subscriptions alive as long as client is connected
123
+ def refresh_client_subscriptions_ttl(client_id)
124
+ subscription_ttl = @options[:subscription_ttl] || 3600
125
+
126
+ @connection.with_redis do |redis|
127
+ # Get all channels this client is subscribed to
128
+ channels = redis.smembers(client_subscriptions_key(client_id))
129
+ return if channels.empty?
130
+
131
+ # Use pipeline to refresh all TTLs efficiently
132
+ redis.pipelined do |pipeline|
133
+ # Refresh client's subscriptions set
134
+ pipeline.expire(client_subscriptions_key(client_id), subscription_ttl)
135
+
136
+ # Refresh each subscription metadata and channel subscriber set
137
+ channels.each do |channel|
138
+ pipeline.expire(subscription_key(client_id, channel), subscription_ttl)
139
+ pipeline.expire(channel_subscribers_key(channel), subscription_ttl)
140
+ end
141
+
142
+ # Refresh patterns set if it exists
143
+ pipeline.expire(patterns_key, subscription_ttl)
144
+ end
145
+ end
146
+ rescue => e
147
+ log_error("Failed to refresh subscription TTL for client #{client_id}: #{e.message}")
148
+ end
149
+
121
150
  # Get all channels a client is subscribed to
122
151
  def get_client_subscriptions(client_id, &callback)
123
152
  channels = @connection.with_redis do |redis|
@@ -1,5 +1,5 @@
1
1
  module Faye
2
2
  class Redis
3
- VERSION = '1.0.12'
3
+ VERSION = '1.0.13'
4
4
  end
5
5
  end
data/lib/faye/redis.rb CHANGED
@@ -88,8 +88,10 @@ module Faye
88
88
  end
89
89
 
90
90
  # Ping a client to keep it alive
91
+ # Also refreshes subscription TTLs to keep them alive while client is connected
91
92
  def ping(client_id)
92
93
  @client_registry.ping(client_id)
94
+ @subscription_manager.refresh_client_subscriptions_ttl(client_id)
93
95
  end
94
96
 
95
97
  # Subscribe a client to a channel
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: faye-redis-ng
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.12
4
+ version: 1.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zac