Add ScopedPresence to fix memory leaks with room-scoped presence subs… #855
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Room-scoped presence subscriptions auto-unsubscribe when room is disposed
This PR addresses the memory leak issue described in #843 where room-scoped presence subscriptions are not automatically cleaned up when a room is disposed. This particularly affects Redis Presence in multi-process setups, causing memory usage to grow over time.
Implementation
The solution implements the approach suggested in #843 by creating a ScopedPresence class that:
Wraps the global presence instance
Tracks all subscriptions made through it
Provides a dispose() method to clean up all subscriptions when a room is disposed
Changes include:
New ScopedPresence class that implements the Presence interface
Modified MatchMaker to create a ScopedPresence instance for each room
Modified Room to dispose the ScopedPresence instance when the room is disposed
Added export for ScopedPresence in the package index
How it fixes the issue
When a room is disposed, all presence subscriptions created by that room are automatically unsubscribed, preventing memory leaks. This is achieved by:
Each room gets its own ScopedPresence instance that wraps the global presence
All subscriptions made through the room's presence are tracked
When the room is disposed, all tracked subscriptions are automatically unsubscribed
Testing
The implementation has been tested with:
Manual testing with both LocalPresence and RedisPresence
Verification that subscriptions are properly cleaned up when rooms are disposed
Simulation of the exact scenario described in the issue:
Backward compatibility
This implementation maintains backward compatibility:
Existing code that uses this.presence will continue to work without changes
The ScopedPresence class delegates all methods to the global presence instance
No changes to the public API
Related issues
Fixes #843
Related to #842