-
-
Notifications
You must be signed in to change notification settings - Fork 638
Closed
Description
Problem
The redisReceiver.ts module in the dummy app currently uses global module-level state that causes several issues:
Global State Issues
- Shared Redis Client - Single
sharedRedisClientconnection shared across ALL concurrent requests - Global pendingPromises Map - Promise tracking map shared across ALL listeners, regardless of requestId
- Global activeListeners Map - Listener cache that accumulates
undefinedentries (never cleaned up properly)
Memory Leak Risk
pendingPromisesandactiveListenersmaps only set entries toundefinedinstead of deleting them- Over time in long-running processes, these maps accumulate undefined entries
- Global state prevents proper garbage collection between requests
Request Isolation Issues
- Multiple concurrent requests share the same Redis client connection
pendingPromisesbeing global means different requestIds can interfere with each other's promise resolution- No proper isolation between independent stream listeners
Solution
Refactor to eliminate all global state by moving to request-scoped encapsulation:
Changes
-
Remove all module-level state variables:
sharedRedisClient❌isClientConnected❌activeListeners❌pendingPromises❌
-
Create private state per
listenToRequestData()call:- Each listener gets its own dedicated Redis client instance
- Each listener has its own isolated
pendingPromisesmap - Each listener manages its own connection lifecycle
-
Proper cleanup:
- Use
deleteinstead of setting toundefined - Always close Redis client in
close()method - Clear all Maps completely on cleanup
- Use
Benefits
✅ No memory leaks - All state properly cleaned up per request
✅ Request isolation - Each stream listener is completely independent
✅ Simpler code - No global state management complexity
✅ Better resource management - Each listener owns its connection lifecycle
✅ Same API - No breaking changes to consumers
Scope
Files modified:
/react_on_rails_pro/spec/dummy/client/app/utils/redisReceiver.ts- Internal refactoring only
No changes needed:
- Consumer components (
RedisReceiver.jsx,RSCPostsPageOverRedis.jsx) - E2E tests
- Backend Ruby controllers
Behavioral differences:
- Removed listener caching by requestId (each call creates fresh listener)
- Each listener has isolated state and own Redis connection
- External API and behavior unchanged
Metadata
Metadata
Assignees
Labels
No labels