faye-redis-ng 1.0.5 → 1.0.6
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 +4 -4
- data/CHANGELOG.md +27 -1
- data/README.md +52 -11
- data/lib/faye/redis/version.rb +1 -1
- data/lib/faye/redis.rb +48 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f87f5800dede3c5720fc5ab77944c3322f735cd808c1b02edd218fc6d97bca8b
|
|
4
|
+
data.tar.gz: 13d579f33d6620ab7ecdc3567b45dd7c4a58264ed0115b25ddc39454662b2e0c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fbd69bad2590d4e55b141941952c95e316c3d8dd2a1e37f4ebbe3129ffe00b48957e8ba86c02732ef67aad97200c47b27dc6c663c5c41640cbaa0dd6787e8514
|
|
7
|
+
data.tar.gz: 8c08572629040c40e130f03c0881e864f02a1dbfb89b5db9c0509c255d4cf986a9f38bf5267c4834216dcae0ca26ef6c115742b42c4f61095c9e4cb14264824a
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.0.6] - 2025-10-30
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **Automatic Garbage Collection**: Implemented automatic GC timer that runs periodically to clean up expired clients and orphaned data
|
|
14
|
+
- New `gc_interval` configuration option (default: 60 seconds)
|
|
15
|
+
- Automatically starts when EventMachine is running
|
|
16
|
+
- Can be disabled by setting `gc_interval` to 0 or false
|
|
17
|
+
- Lazy initialization ensures timer starts even if engine is created before EventMachine starts
|
|
18
|
+
- Timer is properly stopped on disconnect to prevent resource leaks
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
- **Improved User Experience**: No longer requires manual setup of periodic cleanup
|
|
22
|
+
- Memory leak prevention is now automatic by default
|
|
23
|
+
- Matches behavior of original faye-redis-ruby project
|
|
24
|
+
- Users can still manually call `cleanup_expired` if needed
|
|
25
|
+
- Custom GC schedules possible by disabling automatic GC
|
|
26
|
+
|
|
27
|
+
### Technical Details
|
|
28
|
+
The automatic GC timer:
|
|
29
|
+
- Runs `cleanup_expired` every 60 seconds by default
|
|
30
|
+
- Only starts when EventMachine reactor is running
|
|
31
|
+
- Supports lazy initialization for engines created outside EM context
|
|
32
|
+
- Properly handles cleanup on disconnect
|
|
33
|
+
- Can be customized or disabled via `gc_interval` option
|
|
34
|
+
|
|
10
35
|
## [1.0.5] - 2025-10-30
|
|
11
36
|
|
|
12
37
|
### Fixed
|
|
@@ -126,7 +151,8 @@ For 100 subscribers receiving one message:
|
|
|
126
151
|
### Security
|
|
127
152
|
- Client and message IDs now use `SecureRandom.uuid` instead of predictable time-based generation
|
|
128
153
|
|
|
129
|
-
[Unreleased]: https://github.com/7a6163/faye-redis-ng/compare/v1.0.
|
|
154
|
+
[Unreleased]: https://github.com/7a6163/faye-redis-ng/compare/v1.0.6...HEAD
|
|
155
|
+
[1.0.6]: https://github.com/7a6163/faye-redis-ng/compare/v1.0.5...v1.0.6
|
|
130
156
|
[1.0.5]: https://github.com/7a6163/faye-redis-ng/compare/v1.0.4...v1.0.5
|
|
131
157
|
[1.0.4]: https://github.com/7a6163/faye-redis-ng/compare/v1.0.3...v1.0.4
|
|
132
158
|
[1.0.3]: https://github.com/7a6163/faye-redis-ng/compare/v1.0.2...v1.0.3
|
data/README.md
CHANGED
|
@@ -81,6 +81,9 @@ bayeux = Faye::RackAdapter.new(app, {
|
|
|
81
81
|
client_timeout: 60, # Client session timeout (seconds)
|
|
82
82
|
message_ttl: 3600, # Message TTL (seconds)
|
|
83
83
|
|
|
84
|
+
# Garbage collection
|
|
85
|
+
gc_interval: 60, # Automatic GC interval (seconds), set to 0 or false to disable
|
|
86
|
+
|
|
84
87
|
# Logging
|
|
85
88
|
log_level: :info, # Log level (:silent, :info, :debug)
|
|
86
89
|
|
|
@@ -236,11 +239,45 @@ The CI/CD pipeline will automatically:
|
|
|
236
239
|
|
|
237
240
|
## Memory Management
|
|
238
241
|
|
|
239
|
-
###
|
|
242
|
+
### Automatic Garbage Collection
|
|
243
|
+
|
|
244
|
+
**New in v1.0.6**: faye-redis-ng now includes automatic garbage collection that runs every 60 seconds by default. This automatically cleans up expired clients and orphaned subscription keys, preventing memory leaks without any manual intervention.
|
|
245
|
+
|
|
246
|
+
```ruby
|
|
247
|
+
bayeux = Faye::RackAdapter.new(app, {
|
|
248
|
+
mount: '/faye',
|
|
249
|
+
timeout: 25,
|
|
250
|
+
engine: {
|
|
251
|
+
type: Faye::Redis,
|
|
252
|
+
host: 'localhost',
|
|
253
|
+
port: 6379,
|
|
254
|
+
gc_interval: 60 # Run GC every 60 seconds (default)
|
|
255
|
+
}
|
|
256
|
+
})
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
To customize the GC interval or disable it:
|
|
240
260
|
|
|
241
|
-
|
|
261
|
+
```ruby
|
|
262
|
+
engine: {
|
|
263
|
+
type: Faye::Redis,
|
|
264
|
+
host: 'localhost',
|
|
265
|
+
port: 6379,
|
|
266
|
+
gc_interval: 300 # Run GC every 5 minutes
|
|
267
|
+
}
|
|
242
268
|
|
|
243
|
-
|
|
269
|
+
# Or disable automatic GC
|
|
270
|
+
engine: {
|
|
271
|
+
type: Faye::Redis,
|
|
272
|
+
host: 'localhost',
|
|
273
|
+
port: 6379,
|
|
274
|
+
gc_interval: 0 # Disabled - you'll need to call cleanup_expired manually
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Manual Cleanup
|
|
279
|
+
|
|
280
|
+
If you've disabled automatic GC, you can manually clean up expired clients:
|
|
244
281
|
|
|
245
282
|
```ruby
|
|
246
283
|
# Get the engine instance
|
|
@@ -252,9 +289,9 @@ engine.cleanup_expired do |expired_count|
|
|
|
252
289
|
end
|
|
253
290
|
```
|
|
254
291
|
|
|
255
|
-
####
|
|
292
|
+
#### Custom GC Schedule (Optional)
|
|
256
293
|
|
|
257
|
-
|
|
294
|
+
If you need more control, you can disable automatic GC and implement your own schedule:
|
|
258
295
|
|
|
259
296
|
```ruby
|
|
260
297
|
require 'eventmachine'
|
|
@@ -268,11 +305,12 @@ bayeux = Faye::RackAdapter.new(app, {
|
|
|
268
305
|
type: Faye::Redis,
|
|
269
306
|
host: 'localhost',
|
|
270
307
|
port: 6379,
|
|
271
|
-
namespace: 'my-app'
|
|
308
|
+
namespace: 'my-app',
|
|
309
|
+
gc_interval: 0 # Disable automatic GC
|
|
272
310
|
}
|
|
273
311
|
})
|
|
274
312
|
|
|
275
|
-
#
|
|
313
|
+
# Custom cleanup schedule - every 5 minutes
|
|
276
314
|
EM.add_periodic_timer(300) do
|
|
277
315
|
bayeux.get_engine.cleanup_expired do |count|
|
|
278
316
|
puts "[#{Time.now}] Cleaned up #{count} expired clients" if count > 0
|
|
@@ -330,12 +368,15 @@ The `cleanup_expired` method removes:
|
|
|
330
368
|
|
|
331
369
|
### Memory Leak Prevention
|
|
332
370
|
|
|
333
|
-
|
|
371
|
+
**v1.0.6+**: Automatic garbage collection is now enabled by default, preventing memory leaks from orphaned keys without any configuration needed.
|
|
372
|
+
|
|
373
|
+
Without GC, abnormal client disconnections (crashes, network failures, etc.) can cause orphaned keys to accumulate:
|
|
334
374
|
|
|
335
|
-
- **Before
|
|
336
|
-
- **
|
|
375
|
+
- **Before v1.0.5**: 10,000 orphaned clients × 5 channels = 50,000+ keys = 100-500 MB leaked
|
|
376
|
+
- **v1.0.5**: Manual cleanup required via `cleanup_expired` method
|
|
377
|
+
- **v1.0.6+**: Automatic GC runs every 60 seconds by default - no manual intervention needed
|
|
337
378
|
|
|
338
|
-
|
|
379
|
+
The automatic GC ensures memory usage remains stable even with frequent client disconnections.
|
|
339
380
|
|
|
340
381
|
## Troubleshooting
|
|
341
382
|
|
data/lib/faye/redis/version.rb
CHANGED
data/lib/faye/redis.rb
CHANGED
|
@@ -25,7 +25,8 @@ module Faye
|
|
|
25
25
|
retry_delay: 1,
|
|
26
26
|
client_timeout: 60,
|
|
27
27
|
message_ttl: 3600,
|
|
28
|
-
namespace: 'faye'
|
|
28
|
+
namespace: 'faye',
|
|
29
|
+
gc_interval: 60 # Automatic garbage collection interval (seconds), set to 0 or false to disable
|
|
29
30
|
}.freeze
|
|
30
31
|
|
|
31
32
|
attr_reader :server, :options, :connection, :client_registry,
|
|
@@ -50,10 +51,16 @@ module Faye
|
|
|
50
51
|
|
|
51
52
|
# Set up message routing
|
|
52
53
|
setup_message_routing
|
|
54
|
+
|
|
55
|
+
# Start automatic garbage collection timer
|
|
56
|
+
start_gc_timer
|
|
53
57
|
end
|
|
54
58
|
|
|
55
59
|
# Create a new client
|
|
56
60
|
def create_client(&callback)
|
|
61
|
+
# Ensure GC timer is started (lazy initialization)
|
|
62
|
+
ensure_gc_timer_started
|
|
63
|
+
|
|
57
64
|
client_id = generate_client_id
|
|
58
65
|
@client_registry.create(client_id) do |success|
|
|
59
66
|
if success
|
|
@@ -136,6 +143,9 @@ module Faye
|
|
|
136
143
|
|
|
137
144
|
# Disconnect the engine
|
|
138
145
|
def disconnect
|
|
146
|
+
# Stop GC timer if running
|
|
147
|
+
stop_gc_timer
|
|
148
|
+
|
|
139
149
|
@pubsub_coordinator.disconnect
|
|
140
150
|
@connection.disconnect
|
|
141
151
|
end
|
|
@@ -254,5 +264,42 @@ module Faye
|
|
|
254
264
|
def log_error(message)
|
|
255
265
|
@logger.error(message)
|
|
256
266
|
end
|
|
267
|
+
|
|
268
|
+
# Start automatic garbage collection timer
|
|
269
|
+
def start_gc_timer
|
|
270
|
+
gc_interval = @options[:gc_interval]
|
|
271
|
+
|
|
272
|
+
# Skip if GC is disabled (0, false, or nil)
|
|
273
|
+
return if !gc_interval || gc_interval == 0
|
|
274
|
+
|
|
275
|
+
# Only start timer if EventMachine is running
|
|
276
|
+
return unless EventMachine.reactor_running?
|
|
277
|
+
|
|
278
|
+
@logger.info("Starting automatic GC timer with interval: #{gc_interval} seconds")
|
|
279
|
+
|
|
280
|
+
@gc_timer = EventMachine.add_periodic_timer(gc_interval) do
|
|
281
|
+
@logger.debug("Running automatic garbage collection")
|
|
282
|
+
cleanup_expired do |count|
|
|
283
|
+
@logger.debug("GC completed: #{count} expired clients cleaned") if count > 0
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# Ensure GC timer is started (called lazily on first operation)
|
|
289
|
+
def ensure_gc_timer_started
|
|
290
|
+
return if @gc_timer # Already started
|
|
291
|
+
return if !@options[:gc_interval] || @options[:gc_interval] == 0 # Disabled
|
|
292
|
+
|
|
293
|
+
start_gc_timer
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
# Stop automatic garbage collection timer
|
|
297
|
+
def stop_gc_timer
|
|
298
|
+
if @gc_timer
|
|
299
|
+
EventMachine.cancel_timer(@gc_timer)
|
|
300
|
+
@gc_timer = nil
|
|
301
|
+
@logger.info("Stopped automatic GC timer")
|
|
302
|
+
end
|
|
303
|
+
end
|
|
257
304
|
end
|
|
258
305
|
end
|