Implement push notification processing in baseClient._getConn() to ensure
that all cluster topology changes are handled immediately before connections
are used for commands. This is critical for hitless upgrades and real-time
cluster state awareness.
Key Enhancements:
1. Enhanced Connection Retrieval (_getConn):
- Process push notifications for both existing and new connections
- Added processPushNotifications() call before returning connections
- Ensures immediate handling of cluster topology changes
- Proper error handling with connection removal on processing failures
2. Push Notification Processing Method:
- Added processPushNotifications() method to baseClient
- Only processes notifications for RESP3 connections with processors
- Uses WithReader() to safely access connection reader
- Integrates with existing push notification infrastructure
3. Connection Flow Enhancement:
- Existing connections: Health check → Push notification processing → Return
- New connections: Initialization → Push notification processing → Return
- Failed processing results in connection removal and error return
- Seamless integration with existing connection management
4. RESP3 Protocol Integration:
- Protocol version check (only process for RESP3)
- Push processor availability check
- Graceful handling when processors are not available
- Consistent behavior with existing push notification system
5. Error Handling and Recovery:
- Remove connections if push notification processing fails
- Return errors to trigger connection retry mechanisms
- Maintain connection pool health and reliability
- Prevent returning connections with unprocessed notifications
Implementation Details:
- processPushNotifications() checks protocol and processor availability
- Uses cn.WithReader() to safely access the connection reader
- Calls pushProcessor.ProcessPendingNotifications() for actual processing
- Applied to both pooled connections and newly initialized connections
- Consistent error handling across all connection retrieval paths
Flow Enhancement:
1. Connection requested via _getConn()
2. Connection retrieved from pool (existing or new)
3. Connection initialization (if new)
4. Push notification processing (NEW)
5. Connection returned to caller
6. Commands executed with up-to-date cluster state
Benefits:
- Immediate cluster topology awareness before command execution
- Enhanced hitless upgrade reliability with real-time notifications
- Reduced command failures during cluster topology changes
- Consistent push notification handling across all connection types
- Better integration with Redis cluster operations
This ensures that Redis cluster topology changes (MOVING, MIGRATING,
MIGRATED, FAILING_OVER, FAILED_OVER) are always processed before
connections are used, providing the foundation for reliable hitless
upgrades and seamless cluster operations.
- Add GetHandler() method to PushNotificationProcessorInterface for better encapsulation
- Add GetPushNotificationHandler() convenience method to Client and SentinelClient
- Remove HasHandlers() check from ProcessPendingNotifications to ensure notifications are always consumed
- Use PushNotificationProcessorInterface in internal pool package for proper abstraction
- Maintain GetRegistry() for backward compatibility and testing
- Update pubsub to use GetHandler() instead of GetRegistry() for cleaner code
Benefits:
- Better API encapsulation - no need to expose entire registry
- Cleaner interface - direct access to specific handlers
- Always consume push notifications from reader regardless of handler presence
- Proper abstraction in internal pool package
- Backward compatibility maintained
- Consistent behavior across all processor types
- Add nil check in newConn to create VoidPushNotificationProcessor when needed
- Fix tests to use Protocol 2 for disabled push notification scenarios
- Prevent nil pointer dereference in transaction and connection contexts
- Ensure consistent behavior across all connection creation paths
The panic was occurring because newConn could create connections with nil
pushProcessor when options didn't have a processor set. Now we always
ensure a processor exists (real or void) to maintain the 'never nil' guarantee.
- Remove enabled field from PushNotificationProcessor struct
- Remove IsEnabled() and SetEnabled() methods from processor interface
- Remove enabled parameter from NewPushNotificationProcessor()
- Update all interfaces in pool package to remove IsEnabled requirement
- Simplify processor logic - if processor exists, it works
- VoidPushNotificationProcessor handles disabled case by discarding notifications
- Update all tests to use simplified interface without enable/disable logic
Benefits:
- Simpler, cleaner interface with less complexity
- No unnecessary state management for enabled/disabled
- VoidPushNotificationProcessor pattern handles disabled case elegantly
- Reduced cognitive overhead - processors just work when set
- Eliminates redundant enabled checks throughout codebase
- More predictable behavior - set processor = it works
- Add VoidPushNotificationProcessor that reads and discards push notifications
- Create PushNotificationProcessorInterface for consistent behavior
- Always provide a processor (real or void) instead of nil
- VoidPushNotificationProcessor properly cleans RESP3 push notifications from buffer
- Remove all nil checks throughout codebase for cleaner, safer code
- Update tests to expect VoidPushNotificationProcessor when disabled
Benefits:
- Eliminates nil pointer risks throughout the codebase
- Follows null object pattern for safer operation
- Properly handles RESP3 push notifications even when disabled
- Consistent interface regardless of push notification settings
- Cleaner code without defensive nil checks everywhere
- Add protected flag to RegisterHandler methods across all types
- Protected handlers cannot be unregistered, UnregisterHandler returns error
- Rename 'command' parameter to 'pushNotificationName' for clarity
- Update PushNotificationInfo.Command field to Name field
- Add comprehensive test for protected handler functionality
- Update all existing tests to use new protected parameter (false by default)
- Improve error messages to use 'push notification' terminology
Benefits:
- Critical handlers can be protected from accidental unregistration
- Clearer naming reflects that these are notification names, not commands
- Better error handling with informative error messages
- Backward compatible (existing handlers work with protected=false)
- Remove RegisterPushNotificationHandlerFunc methods from all types
- Remove PushNotificationHandlerFunc type adapter
- Keep only RegisterPushNotificationHandler method for cleaner interface
- Remove unnecessary push notification constants (keep only Redis Cluster ones)
- Update all tests to use simplified interface with direct handler implementations
Benefits:
- Cleaner, simpler API with single registration method
- Reduced code complexity and maintenance burden
- Focus on essential Redis Cluster push notifications only
- Users implement PushNotificationHandler interface directly
- No functional changes, just interface simplification
- Remove unused Timestamp and Source fields from PushNotificationInfo
- Add pushProcessor to newConn function to ensure Conn instances have push notifications
- Add push notification methods to Conn type for consistency
- Ensure cloned clients and Conn instances preserve push notification functionality
This fixes issues where:
1. PushNotificationInfo had unused fields causing confusion
2. Conn instances created via client.Conn() lacked push notification support
3. All client types now consistently support push notifications
- Add PushNotificationProcessor field to pool.Conn for connection-level processing
- Modify connection pool Put() and isHealthyConn() to handle push notifications
- Process pending push notifications before discarding connections
- Pass push notification processor to connections during creation
- Update connection pool options to include push notification processor
- Add comprehensive test for connection health check integration
This prevents connections with buffered push notification data from being
incorrectly discarded by the connection health check, ensuring push
notifications are properly processed and connections are reused.
- Remove all global push notification handler functionality
- Simplify registry to support only single handler per notification type
- Enable push notifications by default for RESP3 connections
- Update comprehensive test suite to remove global handler tests
- Update demo to show multiple specific handlers instead of global handlers
- Always respect custom processors regardless of PushNotifications flag
Push notifications are now automatically enabled for RESP3 and each
notification type has a single dedicated handler for predictable behavior.
- Change PushNotificationRegistry to allow only one handler per command
- RegisterHandler methods now return error if handler already exists
- Update UnregisterHandler to remove handler by command only
- Update all client methods to return errors for duplicate registrations
- Update comprehensive test suite to verify single handler behavior
- Add specific test for duplicate handler error scenarios
This prevents handler conflicts and ensures predictable notification
routing with clear error handling for registration conflicts.
- Add PushNotificationRegistry for managing notification handlers
- Add PushNotificationProcessor for processing RESP3 push notifications
- Add client methods for registering push notification handlers
- Add PubSub integration for handling generic push notifications
- Add comprehensive test suite with 100% coverage
- Add push notification demo example
This system allows handling any arbitrary RESP3 push notification
with registered handlers, not just specific notification types.
* wip
* update documentation
* add streamingcredentialsprovider in options
* fix: put back option in pool creation
* add package level comment
* Initial re authentication implementation
Introduces the StreamingCredentialsProvider as the CredentialsProvider
with the highest priority.
TODO: needs to be tested
* Change function type name
Change CancelProviderFunc to UnsubscribeFunc
* add tests
* fix race in tests
* fix example tests
* wip, hooks refactor
* fix build
* update README.md
* update wordlist
* update README.md
* refactor(auth): early returns in cred listener
* fix(doctest): simulate some delay
* feat(conn): add close hook on conn
* fix(tests): simulate start/stop in mock credentials provider
* fix(auth): don't double close the conn
* docs(README): mark streaming credentials provider as experimental
* fix(auth): streamline auth err proccess
* fix(auth): check err on close conn
* chore(entraid): use the repo under redis org
* chore: set the default value for the `options.protocol` in the `init()` of `options`
Signed-off-by: fukua95 <fukua95@gmail.com>
* add a test
Signed-off-by: fukua95 <fukua95@gmail.com>
---------
Signed-off-by: fukua95 <fukua95@gmail.com>
* fix: handle network error on SETINFO
This fix addresses potential out of order responses as described in `CVE-2025-29923`
* fix: deprecate DisableIndentity and introduce DisableIdentity
Both options will work before V10. In v10 DisableIndentity will be dropped. The preferred flag to use is `DisableIdentity`.
* add helpers to set library name and library info without risk of panic if we try to set both
* refactor code to use helpers
* add example
* refactor tests
* fix testable example
* simplify example
* rename exampl
* fix ring.go
* update example
---------
Co-authored-by: ofekshenawa <104765379+ofekshenawa@users.noreply.github.com>
* Update CLIENT-SETINFO to support suffixes
* Update CLIENT-SETINFO
* fix acl log test
* add setinfo option to cluster
* change to DisableIndentity
* change to DisableIndentity