faye-redis-ng 1.0.4 → 1.0.5
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 +38 -1
 - data/README.md +103 -0
 - data/lib/faye/redis/version.rb +1 -1
 - data/lib/faye/redis.rb +70 -0
 - metadata +2 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 02a75e3e557cd2916224537b1d688333c2661e1006a836ca92afde12f59c04bb
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 33a2a61187282c3801de1ac648f4d55fa0ad2a46d5ef1c1f964f1e5db5df7ed7
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 79f1cdaeb24197a454fbcf9ffa2a2a0678ebe2e09c0ab82a694e9e6b643fba4a43fa14d836c1cb3eeca91c9f4091d63faec489d60c7237e8652b42679c8a811f
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: d96e691b5bb66c86c64852474b4bbb9cb1797420adfed71210f64c27f0e695b5489dec71c18d6636daa3ecdcea6e6a1580f90cba850f140e1c7ebc5734d615b8
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    | 
         @@ -7,6 +7,42 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 
     | 
|
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
            ## [Unreleased]
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
      
 10 
     | 
    
         
            +
            ## [1.0.5] - 2025-10-30
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            ### Fixed
         
     | 
| 
      
 13 
     | 
    
         
            +
            - **Memory Leak**: Fixed critical memory leak where subscription keys were never cleaned up after client disconnection
         
     | 
| 
      
 14 
     | 
    
         
            +
              - Orphaned `subscriptions:{client_id}` keys remained permanently in Redis
         
     | 
| 
      
 15 
     | 
    
         
            +
              - Orphaned `subscription:{client_id}:{channel}` hash keys accumulated over time
         
     | 
| 
      
 16 
     | 
    
         
            +
              - Orphaned client IDs remained in `channels:{channel}` sets
         
     | 
| 
      
 17 
     | 
    
         
            +
              - Message queues for disconnected clients were not cleaned up
         
     | 
| 
      
 18 
     | 
    
         
            +
              - Could result in hundreds of MB memory leak in production environments
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            ### Added
         
     | 
| 
      
 21 
     | 
    
         
            +
            - **`cleanup_expired` Method**: New public method to clean up expired clients and orphaned data
         
     | 
| 
      
 22 
     | 
    
         
            +
              - Automatically detects and removes orphaned subscription keys
         
     | 
| 
      
 23 
     | 
    
         
            +
              - Cleans up message queues for disconnected clients
         
     | 
| 
      
 24 
     | 
    
         
            +
              - Removes stale client IDs from channel subscriber lists
         
     | 
| 
      
 25 
     | 
    
         
            +
              - Uses Redis SCAN to avoid blocking operations
         
     | 
| 
      
 26 
     | 
    
         
            +
              - Batch deletion using pipelining for efficiency
         
     | 
| 
      
 27 
     | 
    
         
            +
              - Can be called manually or scheduled as periodic task
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            ### Changed
         
     | 
| 
      
 30 
     | 
    
         
            +
            - **Improved Cleanup Strategy**: Enhanced cleanup process now handles orphaned data
         
     | 
| 
      
 31 
     | 
    
         
            +
              - `cleanup_expired` now cleans both expired clients AND orphaned subscriptions
         
     | 
| 
      
 32 
     | 
    
         
            +
              - Works even when no expired clients are found
         
     | 
| 
      
 33 
     | 
    
         
            +
              - Prevents memory leaks from abnormal client disconnections
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            ### Technical Details
         
     | 
| 
      
 36 
     | 
    
         
            +
            Memory leak scenario (before fix):
         
     | 
| 
      
 37 
     | 
    
         
            +
            - 10,000 abnormally disconnected clients × 5 channels each = 50,000+ orphaned keys
         
     | 
| 
      
 38 
     | 
    
         
            +
            - Estimated memory waste: 100-500 MB
         
     | 
| 
      
 39 
     | 
    
         
            +
            - Keys remained permanently without TTL
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            After fix:
         
     | 
| 
      
 42 
     | 
    
         
            +
            - All orphaned keys cleaned up automatically
         
     | 
| 
      
 43 
     | 
    
         
            +
            - Memory usage remains stable
         
     | 
| 
      
 44 
     | 
    
         
            +
            - Production environments can schedule periodic cleanup
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
       10 
46 
     | 
    
         
             
            ## [1.0.4] - 2025-10-15
         
     | 
| 
       11 
47 
     | 
    
         | 
| 
       12 
48 
     | 
    
         
             
            ### Performance
         
     | 
| 
         @@ -90,7 +126,8 @@ For 100 subscribers receiving one message: 
     | 
|
| 
       90 
126 
     | 
    
         
             
            ### Security
         
     | 
| 
       91 
127 
     | 
    
         
             
            - Client and message IDs now use `SecureRandom.uuid` instead of predictable time-based generation
         
     | 
| 
       92 
128 
     | 
    
         | 
| 
       93 
     | 
    
         
            -
            [Unreleased]: https://github.com/7a6163/faye-redis-ng/compare/v1.0. 
     | 
| 
      
 129 
     | 
    
         
            +
            [Unreleased]: https://github.com/7a6163/faye-redis-ng/compare/v1.0.5...HEAD
         
     | 
| 
      
 130 
     | 
    
         
            +
            [1.0.5]: https://github.com/7a6163/faye-redis-ng/compare/v1.0.4...v1.0.5
         
     | 
| 
       94 
131 
     | 
    
         
             
            [1.0.4]: https://github.com/7a6163/faye-redis-ng/compare/v1.0.3...v1.0.4
         
     | 
| 
       95 
132 
     | 
    
         
             
            [1.0.3]: https://github.com/7a6163/faye-redis-ng/compare/v1.0.2...v1.0.3
         
     | 
| 
       96 
133 
     | 
    
         
             
            [1.0.2]: https://github.com/7a6163/faye-redis-ng/compare/v1.0.1...v1.0.2
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -234,6 +234,109 @@ The CI/CD pipeline will automatically: 
     | 
|
| 
       234 
234 
     | 
    
         
             
            - Add `RUBYGEMS_API_KEY` to GitHub repository secrets
         
     | 
| 
       235 
235 
     | 
    
         
             
            - The tag must start with 'v' (e.g., v0.1.0, v1.2.3)
         
     | 
| 
       236 
236 
     | 
    
         | 
| 
      
 237 
     | 
    
         
            +
            ## Memory Management
         
     | 
| 
      
 238 
     | 
    
         
            +
             
     | 
| 
      
 239 
     | 
    
         
            +
            ### Cleaning Up Expired Clients
         
     | 
| 
      
 240 
     | 
    
         
            +
             
     | 
| 
      
 241 
     | 
    
         
            +
            To prevent memory leaks from orphaned subscription keys, you should periodically clean up expired clients:
         
     | 
| 
      
 242 
     | 
    
         
            +
             
     | 
| 
      
 243 
     | 
    
         
            +
            #### Manual Cleanup
         
     | 
| 
      
 244 
     | 
    
         
            +
             
     | 
| 
      
 245 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 246 
     | 
    
         
            +
            # Get the engine instance
         
     | 
| 
      
 247 
     | 
    
         
            +
            engine = bayeux.get_engine
         
     | 
| 
      
 248 
     | 
    
         
            +
             
     | 
| 
      
 249 
     | 
    
         
            +
            # Clean up expired clients and orphaned data
         
     | 
| 
      
 250 
     | 
    
         
            +
            engine.cleanup_expired do |expired_count|
         
     | 
| 
      
 251 
     | 
    
         
            +
              puts "Cleaned up #{expired_count} expired clients"
         
     | 
| 
      
 252 
     | 
    
         
            +
            end
         
     | 
| 
      
 253 
     | 
    
         
            +
            ```
         
     | 
| 
      
 254 
     | 
    
         
            +
             
     | 
| 
      
 255 
     | 
    
         
            +
            #### Automatic Periodic Cleanup (Recommended)
         
     | 
| 
      
 256 
     | 
    
         
            +
             
     | 
| 
      
 257 
     | 
    
         
            +
            Add this to your Faye server setup:
         
     | 
| 
      
 258 
     | 
    
         
            +
             
     | 
| 
      
 259 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 260 
     | 
    
         
            +
            require 'eventmachine'
         
     | 
| 
      
 261 
     | 
    
         
            +
            require 'faye'
         
     | 
| 
      
 262 
     | 
    
         
            +
            require 'faye-redis-ng'
         
     | 
| 
      
 263 
     | 
    
         
            +
             
     | 
| 
      
 264 
     | 
    
         
            +
            bayeux = Faye::RackAdapter.new(app, {
         
     | 
| 
      
 265 
     | 
    
         
            +
              mount: '/faye',
         
     | 
| 
      
 266 
     | 
    
         
            +
              timeout: 25,
         
     | 
| 
      
 267 
     | 
    
         
            +
              engine: {
         
     | 
| 
      
 268 
     | 
    
         
            +
                type: Faye::Redis,
         
     | 
| 
      
 269 
     | 
    
         
            +
                host: 'localhost',
         
     | 
| 
      
 270 
     | 
    
         
            +
                port: 6379,
         
     | 
| 
      
 271 
     | 
    
         
            +
                namespace: 'my-app'
         
     | 
| 
      
 272 
     | 
    
         
            +
              }
         
     | 
| 
      
 273 
     | 
    
         
            +
            })
         
     | 
| 
      
 274 
     | 
    
         
            +
             
     | 
| 
      
 275 
     | 
    
         
            +
            # Schedule automatic cleanup every 5 minutes
         
     | 
| 
      
 276 
     | 
    
         
            +
            EM.add_periodic_timer(300) do
         
     | 
| 
      
 277 
     | 
    
         
            +
              bayeux.get_engine.cleanup_expired do |count|
         
     | 
| 
      
 278 
     | 
    
         
            +
                puts "[#{Time.now}] Cleaned up #{count} expired clients" if count > 0
         
     | 
| 
      
 279 
     | 
    
         
            +
              end
         
     | 
| 
      
 280 
     | 
    
         
            +
            end
         
     | 
| 
      
 281 
     | 
    
         
            +
             
     | 
| 
      
 282 
     | 
    
         
            +
            run bayeux
         
     | 
| 
      
 283 
     | 
    
         
            +
            ```
         
     | 
| 
      
 284 
     | 
    
         
            +
             
     | 
| 
      
 285 
     | 
    
         
            +
            #### Using Rake Task
         
     | 
| 
      
 286 
     | 
    
         
            +
             
     | 
| 
      
 287 
     | 
    
         
            +
            Create a Rake task for manual or scheduled cleanup:
         
     | 
| 
      
 288 
     | 
    
         
            +
             
     | 
| 
      
 289 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 290 
     | 
    
         
            +
            # lib/tasks/faye_cleanup.rake
         
     | 
| 
      
 291 
     | 
    
         
            +
            namespace :faye do
         
     | 
| 
      
 292 
     | 
    
         
            +
              desc "Clean up expired Faye clients and orphaned subscriptions"
         
     | 
| 
      
 293 
     | 
    
         
            +
              task cleanup: :environment do
         
     | 
| 
      
 294 
     | 
    
         
            +
                require 'eventmachine'
         
     | 
| 
      
 295 
     | 
    
         
            +
             
     | 
| 
      
 296 
     | 
    
         
            +
                EM.run do
         
     | 
| 
      
 297 
     | 
    
         
            +
                  engine = Faye::Redis.new(
         
     | 
| 
      
 298 
     | 
    
         
            +
                    nil,
         
     | 
| 
      
 299 
     | 
    
         
            +
                    host: ENV['REDIS_HOST'] || 'localhost',
         
     | 
| 
      
 300 
     | 
    
         
            +
                    port: ENV['REDIS_PORT']&.to_i || 6379,
         
     | 
| 
      
 301 
     | 
    
         
            +
                    namespace: 'my-app'
         
     | 
| 
      
 302 
     | 
    
         
            +
                  )
         
     | 
| 
      
 303 
     | 
    
         
            +
             
     | 
| 
      
 304 
     | 
    
         
            +
                  engine.cleanup_expired do |count|
         
     | 
| 
      
 305 
     | 
    
         
            +
                    puts "✅ Cleaned up #{count} expired clients"
         
     | 
| 
      
 306 
     | 
    
         
            +
                    engine.disconnect
         
     | 
| 
      
 307 
     | 
    
         
            +
                    EM.stop
         
     | 
| 
      
 308 
     | 
    
         
            +
                  end
         
     | 
| 
      
 309 
     | 
    
         
            +
                end
         
     | 
| 
      
 310 
     | 
    
         
            +
              end
         
     | 
| 
      
 311 
     | 
    
         
            +
            end
         
     | 
| 
      
 312 
     | 
    
         
            +
            ```
         
     | 
| 
      
 313 
     | 
    
         
            +
             
     | 
| 
      
 314 
     | 
    
         
            +
            Then schedule it with cron:
         
     | 
| 
      
 315 
     | 
    
         
            +
             
     | 
| 
      
 316 
     | 
    
         
            +
            ```bash
         
     | 
| 
      
 317 
     | 
    
         
            +
            # Run cleanup every hour
         
     | 
| 
      
 318 
     | 
    
         
            +
            0 * * * * cd /path/to/app && bundle exec rake faye:cleanup
         
     | 
| 
      
 319 
     | 
    
         
            +
            ```
         
     | 
| 
      
 320 
     | 
    
         
            +
             
     | 
| 
      
 321 
     | 
    
         
            +
            ### What Gets Cleaned Up
         
     | 
| 
      
 322 
     | 
    
         
            +
             
     | 
| 
      
 323 
     | 
    
         
            +
            The `cleanup_expired` method removes:
         
     | 
| 
      
 324 
     | 
    
         
            +
             
     | 
| 
      
 325 
     | 
    
         
            +
            1. **Expired client keys** (`clients:{client_id}`)
         
     | 
| 
      
 326 
     | 
    
         
            +
            2. **Orphaned subscription lists** (`subscriptions:{client_id}`)
         
     | 
| 
      
 327 
     | 
    
         
            +
            3. **Orphaned subscription metadata** (`subscription:{client_id}:{channel}`)
         
     | 
| 
      
 328 
     | 
    
         
            +
            4. **Stale client IDs from channel subscribers** (`channels:{channel}`)
         
     | 
| 
      
 329 
     | 
    
         
            +
            5. **Orphaned message queues** (`messages:{client_id}`)
         
     | 
| 
      
 330 
     | 
    
         
            +
             
     | 
| 
      
 331 
     | 
    
         
            +
            ### Memory Leak Prevention
         
     | 
| 
      
 332 
     | 
    
         
            +
             
     | 
| 
      
 333 
     | 
    
         
            +
            Without periodic cleanup, abnormal client disconnections (crashes, network failures, etc.) can cause orphaned keys to accumulate:
         
     | 
| 
      
 334 
     | 
    
         
            +
             
     | 
| 
      
 335 
     | 
    
         
            +
            - **Before fix**: 10,000 orphaned clients × 5 channels = 50,000+ keys = 100-500 MB leaked
         
     | 
| 
      
 336 
     | 
    
         
            +
            - **After fix**: All orphaned keys are cleaned up automatically
         
     | 
| 
      
 337 
     | 
    
         
            +
             
     | 
| 
      
 338 
     | 
    
         
            +
            **Recommendation**: Schedule cleanup every 5-10 minutes in production environments.
         
     | 
| 
      
 339 
     | 
    
         
            +
             
     | 
| 
       237 
340 
     | 
    
         
             
            ## Troubleshooting
         
     | 
| 
       238 
341 
     | 
    
         | 
| 
       239 
342 
     | 
    
         
             
            ### Connection Issues
         
     | 
    
        data/lib/faye/redis/version.rb
    CHANGED
    
    
    
        data/lib/faye/redis.rb
    CHANGED
    
    | 
         @@ -1,4 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'securerandom'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'set'
         
     | 
| 
       2 
3 
     | 
    
         
             
            require_relative 'redis/version'
         
     | 
| 
       3 
4 
     | 
    
         
             
            require_relative 'redis/logger'
         
     | 
| 
       4 
5 
     | 
    
         
             
            require_relative 'redis/connection'
         
     | 
| 
         @@ -139,6 +140,19 @@ module Faye 
     | 
|
| 
       139 
140 
     | 
    
         
             
                  @connection.disconnect
         
     | 
| 
       140 
141 
     | 
    
         
             
                end
         
     | 
| 
       141 
142 
     | 
    
         | 
| 
      
 143 
     | 
    
         
            +
                # Clean up expired clients and their associated data
         
     | 
| 
      
 144 
     | 
    
         
            +
                def cleanup_expired(&callback)
         
     | 
| 
      
 145 
     | 
    
         
            +
                  @client_registry.cleanup_expired do |expired_count|
         
     | 
| 
      
 146 
     | 
    
         
            +
                    @logger.info("Cleaned up #{expired_count} expired clients") if expired_count > 0
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                    # Always clean up orphaned subscription keys (even if no expired clients)
         
     | 
| 
      
 149 
     | 
    
         
            +
                    # This handles cases where subscriptions were orphaned due to crashes
         
     | 
| 
      
 150 
     | 
    
         
            +
                    cleanup_orphaned_subscriptions do
         
     | 
| 
      
 151 
     | 
    
         
            +
                      callback.call(expired_count) if callback
         
     | 
| 
      
 152 
     | 
    
         
            +
                    end
         
     | 
| 
      
 153 
     | 
    
         
            +
                  end
         
     | 
| 
      
 154 
     | 
    
         
            +
                end
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
       142 
156 
     | 
    
         
             
                private
         
     | 
| 
       143 
157 
     | 
    
         | 
| 
       144 
158 
     | 
    
         
             
                def generate_client_id
         
     | 
| 
         @@ -171,6 +185,62 @@ module Faye 
     | 
|
| 
       171 
185 
     | 
    
         
             
                  end
         
     | 
| 
       172 
186 
     | 
    
         
             
                end
         
     | 
| 
       173 
187 
     | 
    
         | 
| 
      
 188 
     | 
    
         
            +
                def cleanup_orphaned_subscriptions(&callback)
         
     | 
| 
      
 189 
     | 
    
         
            +
                  # Get all active client IDs
         
     | 
| 
      
 190 
     | 
    
         
            +
                  @client_registry.all do |active_clients|
         
     | 
| 
      
 191 
     | 
    
         
            +
                    active_set = active_clients.to_set
         
     | 
| 
      
 192 
     | 
    
         
            +
                    namespace = @options[:namespace] || 'faye'
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
                    # Scan for subscription keys and clean up orphaned ones
         
     | 
| 
      
 195 
     | 
    
         
            +
                    @connection.with_redis do |redis|
         
     | 
| 
      
 196 
     | 
    
         
            +
                      cursor = "0"
         
     | 
| 
      
 197 
     | 
    
         
            +
                      orphaned_keys = []
         
     | 
| 
      
 198 
     | 
    
         
            +
             
     | 
| 
      
 199 
     | 
    
         
            +
                      loop do
         
     | 
| 
      
 200 
     | 
    
         
            +
                        cursor, keys = redis.scan(cursor, match: "#{namespace}:subscriptions:*", count: 100)
         
     | 
| 
      
 201 
     | 
    
         
            +
             
     | 
| 
      
 202 
     | 
    
         
            +
                        keys.each do |key|
         
     | 
| 
      
 203 
     | 
    
         
            +
                          # Extract client_id from key (format: namespace:subscriptions:client_id)
         
     | 
| 
      
 204 
     | 
    
         
            +
                          client_id = key.split(':').last
         
     | 
| 
      
 205 
     | 
    
         
            +
                          orphaned_keys << client_id unless active_set.include?(client_id)
         
     | 
| 
      
 206 
     | 
    
         
            +
                        end
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
                        break if cursor == "0"
         
     | 
| 
      
 209 
     | 
    
         
            +
                      end
         
     | 
| 
      
 210 
     | 
    
         
            +
             
     | 
| 
      
 211 
     | 
    
         
            +
                      # Clean up orphaned subscription data
         
     | 
| 
      
 212 
     | 
    
         
            +
                      if orphaned_keys.any?
         
     | 
| 
      
 213 
     | 
    
         
            +
                        @logger.info("Cleaning up #{orphaned_keys.size} orphaned subscription sets")
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
                        orphaned_keys.each do |client_id|
         
     | 
| 
      
 216 
     | 
    
         
            +
                          # Get channels for this orphaned client
         
     | 
| 
      
 217 
     | 
    
         
            +
                          channels = redis.smembers("#{namespace}:subscriptions:#{client_id}")
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
      
 219 
     | 
    
         
            +
                          # Remove in batch
         
     | 
| 
      
 220 
     | 
    
         
            +
                          redis.pipelined do |pipeline|
         
     | 
| 
      
 221 
     | 
    
         
            +
                            # Delete client's subscription list
         
     | 
| 
      
 222 
     | 
    
         
            +
                            pipeline.del("#{namespace}:subscriptions:#{client_id}")
         
     | 
| 
      
 223 
     | 
    
         
            +
             
     | 
| 
      
 224 
     | 
    
         
            +
                            # Delete each subscription metadata and remove from channel subscribers
         
     | 
| 
      
 225 
     | 
    
         
            +
                            channels.each do |channel|
         
     | 
| 
      
 226 
     | 
    
         
            +
                              pipeline.del("#{namespace}:subscription:#{client_id}:#{channel}")
         
     | 
| 
      
 227 
     | 
    
         
            +
                              pipeline.srem("#{namespace}:channels:#{channel}", client_id)
         
     | 
| 
      
 228 
     | 
    
         
            +
                            end
         
     | 
| 
      
 229 
     | 
    
         
            +
             
     | 
| 
      
 230 
     | 
    
         
            +
                            # Delete message queue if exists
         
     | 
| 
      
 231 
     | 
    
         
            +
                            pipeline.del("#{namespace}:messages:#{client_id}")
         
     | 
| 
      
 232 
     | 
    
         
            +
                          end
         
     | 
| 
      
 233 
     | 
    
         
            +
                        end
         
     | 
| 
      
 234 
     | 
    
         
            +
                      end
         
     | 
| 
      
 235 
     | 
    
         
            +
                    end
         
     | 
| 
      
 236 
     | 
    
         
            +
             
     | 
| 
      
 237 
     | 
    
         
            +
                    EventMachine.next_tick { callback.call } if callback
         
     | 
| 
      
 238 
     | 
    
         
            +
                  end
         
     | 
| 
      
 239 
     | 
    
         
            +
                rescue => e
         
     | 
| 
      
 240 
     | 
    
         
            +
                  log_error("Failed to cleanup orphaned subscriptions: #{e.message}")
         
     | 
| 
      
 241 
     | 
    
         
            +
                  EventMachine.next_tick { callback.call } if callback
         
     | 
| 
      
 242 
     | 
    
         
            +
                end
         
     | 
| 
      
 243 
     | 
    
         
            +
             
     | 
| 
       174 
244 
     | 
    
         
             
                def setup_message_routing
         
     | 
| 
       175 
245 
     | 
    
         
             
                  # Subscribe to message events from other servers
         
     | 
| 
       176 
246 
     | 
    
         
             
                  @pubsub_coordinator.on_message do |channel, message|
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: faye-redis-ng
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 1.0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 1.0.5
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Zac
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire:
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2025-10- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2025-10-30 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: redis
         
     |