- Add nil check for proto.Reader parameter in both PushNotificationProcessor and VoidPushNotificationProcessor
- Prevent segmentation violation when ProcessPendingNotifications is called with nil reader
- Return early with nil error when reader is nil (graceful handling)
- Fix panic in TestProcessPendingNotificationsEdgeCases test
This addresses the runtime panic that occurred when rd.Buffered() was called on a nil reader,
ensuring robust error handling in edge cases where the reader might not be properly initialized.
- Remove GetRegistry() method from PushNotificationProcessorInterface
- Enforce use of GetHandler() method for cleaner API design
- Add GetRegistryForTesting() method for test access only
- Update all tests to use new testing helper methods
- Maintain clean separation between public API and internal implementation
Benefits:
- Better encapsulation - no direct registry access from public interface
- Cleaner API - forces use of GetHandler() for specific handler access
- Consistent interface design across all processor types
- Internal registry access only available for testing purposes
- Prevents misuse of registry in production code
- Add PushNotifications field to FailoverOptions struct
- Update clientOptions() to pass PushNotifications field to Options
- Change SentinelClient and FailoverClient initialization to use same logic as regular Client
- Both clients now support real push notification processors when enabled
- Both clients use void processors only when explicitly disabled
- Consistent behavior across all client types (Client, SentinelClient, FailoverClient)
Benefits:
- SentinelClient and FailoverClient can now fully utilize push notifications
- Consistent API across all client types
- Real processors when push notifications are enabled
- Void processors only when explicitly disabled
- Equal push notification capabilities for all Redis client types
- 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 push processor initialization to NewFailoverClient to prevent nil pointer dereference
- Use VoidPushNotificationProcessor for failover clients (typically don't need push notifications)
- Ensure consistent behavior across all client creation paths including failover scenarios
- Complete the coverage of all client types that inherit from baseClient
This fixes the final nil pointer dereference that was occurring in failover client
contexts where the pushProcessor field was nil, causing segmentation violations
during Redis operations in sentinel-managed failover scenarios.
- Copy pushProcessor from parent client to transaction in newTx()
- Ensure transactions inherit push notification processor from parent client
- Prevent nil pointer dereference in transaction contexts (Watch, Unwatch, etc.)
- Maintain consistent push notification behavior across all Redis operations
This fixes the panic that was occurring in transaction examples where the
transaction's baseClient had a nil pushProcessor field, causing segmentation
violations during transaction operations like Watch and Unwatch.
- Add push processor initialization to NewSentinelClient to prevent nil pointer dereference
- Add GetPushNotificationProcessor and RegisterPushNotificationHandler methods to SentinelClient
- Use VoidPushNotificationProcessor for Sentinel (typically doesn't need push notifications)
- Ensure consistent behavior across all client types that inherit from baseClient
This fixes the panic that was occurring in Sentinel contexts where the pushProcessor
field was nil, causing segmentation violations when processing commands.
- 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)
- Add sync.RWMutex to PushNotificationProcessor struct
- Protect enabled field access with read/write locks in IsEnabled() and SetEnabled()
- Use thread-safe IsEnabled() method in ProcessPendingNotifications()
- Fix concurrent access to enabled field that was causing data races
This resolves the race condition between goroutines calling IsEnabled() and
SetEnabled() concurrently, ensuring thread-safe access to the enabled field.
- 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
- Add 10 new unit tests covering all previously untested code paths
- Test connection pool integration with push notifications
- Test connection health check integration
- Test Conn type push notification methods
- Test cloned client push notification preservation
- Test PushNotificationInfo structure validation
- Test edge cases and error scenarios
- Test custom processor integration
- Test disabled push notification scenarios
Total coverage now includes:
- 20 existing push notification tests
- 10 new comprehensive coverage tests
- All new code paths from connection pool integration
- All Conn methods and cloning functionality
- Edge cases and error handling scenarios
- 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.
- At present, the `scan` command is dispatched to a random slot.
- As far as I can tell, the scanX family of commands are not cluster aware (e.g. don't redirect the client to the correct slot).
- You can see [here](869dc0bb66/src/main/java/redis/clients/jedis/ShardedCommandObjects.java (L101)), the Jedis client calling `processKey` on the match argument, and this is what this PR also does.
We've had this patch running in production, and it seems to work well for us.
For further thought:
- Continuing looking at other Redis clients (e.g. Jedis), they outright [reject as invalid](869dc0bb66/src/main/java/redis/clients/jedis/ShardedCommandObjects.java (L98)) any scan command that does not include a hash-tag. Presumably this has the advantage of users not being surprised when their scan produces no results when a random server is picked.
- Perhaps it would be sensible for go-redis to do the same also?
Co-authored-by: Nedyalko Dyakov <1547186+ndyakov@users.noreply.github.com>
* feat(redisotel): add WithCaller option
Allow the disabling the collection of the `code.function`, `code.filepath` and `code.lineno` tracing attributes.
When setting `WithCaller(false)` overall performance is increased as the "expensive" `runtime.Callers` and `runtime.(*Frames).Next` calls are no longer needed.
* chore(redisotel): improve docblock language
* chore(redisotel): rename `WithCaller` to `WithCallerEnabled`
---------
Co-authored-by: Nedyalko Dyakov <1547186+ndyakov@users.noreply.github.com>
* fix(txpipeline): keyless commands should take the slot of the keyed commands
* fix(txpipeline): extract only keyed cmds from all cmds
* chore(test): Add tests for keyless cmds and txpipeline
* fix(cmdSlot): Add preferred random slot
* fix(cmdSlot): Add shortlist of keyless cmds
* chore(test): Fix ring test
* fix(keylessCommands): Add list of keyless commands
Add list of keyless Commands based on the Commands output
for redis 8
* chore(txPipeline): refactor slottedCommands impl
* fix(osscluster): typo
* DOC-5078 added basic vector set examples
* DOC-5078 formatting and extra comments
* DOC-5078 fixed nondeterministic test
* wip(tests): run doctests for vector sets on redis 8 only
* DOC-5229 added probabilistic data type examples
---------
Co-authored-by: Nedyalko Dyakov <nedyalko.dyakov@gmail.com>
* fix(txpipeline): should return error on multi/exec on multiple slots
* fix(txpipeline): test normal tx pipeline behaviour
* chore(err): Extract crossslot err and add test
* fix(txpipeline): short curcuit the tx if there are no commands
* chore(tests): validate keys are in different slots
* feat: support vectorset
* fix: char encoding error
* use `any` instread of `interface{}`
* update vectorset API
Signed-off-by: fukua95 <fukua95@gmail.com>
* refact: MapStringFloat64Cmd -> VectorInfoSliceCmd
Signed-off-by: fukua95 <fukua95@gmail.com>
* update:
* the type of vector attribute: string -> VectorAttributeMarshaller
* Add a new API VRemAttr
* mark the APIs are experimental
Signed-off-by: fukua95 <fukua95@gmail.com>
* trigger CI again
Signed-off-by: fukua95 <fukua95@gmail.com>
* rename a API: VRemAttr -> VClearAttributes
Signed-off-by: fukua95 <fukua95@gmail.com>
* add test
Signed-off-by: fukua95 <fukua95@gmail.com>
* feat(vectorset): improve VSetAttr API and add comprehensive test suite
- Simplify VSetAttr to accept interface{} with automatic JSON marshalling
- Remove VectorAttributeMarshaller interface for simpler API
- Add comprehensive unit tests for all vectorset commands
---------
Signed-off-by: fukua95 <fukua95@gmail.com>
Co-authored-by: Nedyalko Dyakov <nedyalko.dyakov@gmail.com>
* feat: expose shard information in redis.Ring
- Add GetShards() method to retrieve a list of active shard clients.
- Add GetShardByKey(key string) method to get the shard client for a specific key.
- These methods enable users to manage Pub/Sub operations more effectively by accessing shard-specific clients.
* rename GetShardClients and GetShardClientForKey
---------
Co-authored-by: DengY11 <212294929@qq.com>
Co-authored-by: Nedyalko Dyakov <1547186+ndyakov@users.noreply.github.com>
* 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>
* xinfo-groups: support nil lag in XINFO GROUPS
* Add test
* docs: clarify XInfoGroup.Lag field behavior with Nil values
* docs: clarify XInfoGroup.Lag field behavior