1
0
mirror of https://github.com/redis/go-redis.git synced 2025-07-20 22:42:59 +03:00
Commit Graph

133 Commits

Author SHA1 Message Date
5972b4c23f refactor: move all push notification logic to root package and remove adapters
Consolidate all push notification handling logic in the root package to eliminate
adapters and simplify the architecture. This provides direct access to concrete
types without any intermediate layers or type conversions.

Key Changes:

1. Moved Core Types to Root Package:
   - Moved Registry, Processor, VoidProcessor to push_notifications.go
   - Moved all push notification constants to root package
   - Removed internal/pushnotif package dependencies
   - Direct implementation without internal abstractions

2. Eliminated All Adapters:
   - Removed handlerAdapter that bridged internal and public interfaces
   - Removed voidProcessorAdapter for void processor functionality
   - Removed convertInternalToPublicContext conversion functions
   - Direct usage of concrete types throughout

3. Simplified Architecture:
   - PushNotificationHandlerContext directly implemented in root package
   - PushNotificationHandler directly implemented in root package
   - Registry, Processor, VoidProcessor directly in root package
   - No intermediate layers or type conversions needed

4. Direct Type Usage:
   - GetClusterClient() returns *ClusterClient directly
   - GetSentinelClient() returns *SentinelClient directly
   - GetRegularClient() returns *Client directly
   - GetPubSub() returns *PubSub directly
   - No interface casting or type assertions required

5. Updated All Integration Points:
   - Updated redis.go to use direct types
   - Updated pubsub.go to use direct types
   - Updated sentinel.go to use direct types
   - Removed all internal/pushnotif imports
   - Simplified context creation and usage

6. Core Implementation in Root Package:
   ```go
   // Direct implementation - no adapters needed
   type Registry struct {
       handlers  map[string]PushNotificationHandler
       protected map[string]bool
   }

   type Processor struct {
       registry *Registry
   }

   type VoidProcessor struct{}
   ```

7. Handler Context with Concrete Types:
   ```go
   type PushNotificationHandlerContext interface {
       GetClusterClient() *ClusterClient    // Direct concrete type
       GetSentinelClient() *SentinelClient  // Direct concrete type
       GetRegularClient() *Client           // Direct concrete type
       GetPubSub() *PubSub                  // Direct concrete type
   }
   ```

8. Comprehensive Test Suite:
   - Added push_notifications_test.go with full test coverage
   - Tests for Registry, Processor, VoidProcessor
   - Tests for HandlerContext with concrete type access
   - Tests for all push notification constants
   - Validates all functionality works correctly

9. Benefits:
   - Eliminated complex adapter pattern
   - Removed unnecessary type conversions
   - Simplified codebase with direct type usage
   - Better performance without adapter overhead
   - Cleaner architecture with single source of truth
   - Enhanced developer experience with direct access

10. Architecture Simplification:
    Before: Client -> Adapter -> Internal -> Adapter -> Handler
    After:  Client -> Handler (direct)

    No more:
    - handlerAdapter bridging interfaces
    - voidProcessorAdapter for void functionality
    - convertInternalToPublicContext conversions
    - Complex type mapping between layers

This refactoring provides a much cleaner, simpler architecture where all
push notification logic lives in the root package with direct access to
concrete Redis client types, eliminating unnecessary complexity while
maintaining full functionality and type safety.
2025-07-04 21:13:47 +03:00
d530d45b9b feat: implement strongly typed HandlerContext with concrete types in main package
Move push notification handler and context interfaces to main package to enable
strongly typed getters using concrete Redis client types instead of interfaces.
This provides much better type safety and usability for push notification handlers.

Key Changes:

1. Main Package Implementation:
   - Moved PushNotificationHandlerContext to push_notifications.go
   - Moved PushNotificationHandler to push_notifications.go
   - Implemented concrete types for all getters
   - GetClusterClient() returns *ClusterClient
   - GetSentinelClient() returns *SentinelClient
   - GetRegularClient() returns *Client
   - GetPubSub() returns *PubSub

2. Concrete Type Benefits:
   - No need for interface definitions or type assertions
   - Direct access to concrete client methods and properties
   - Compile-time type checking with actual client types
   - IntelliSense support for all client-specific methods
   - No runtime panics from incorrect type casting

3. Handler Interface with Concrete Types:
   ```go
   type PushNotificationHandlerContext interface {
       GetClusterClient() *ClusterClient
       GetSentinelClient() *SentinelClient
       GetRegularClient() *Client
       GetPubSub() *PubSub
       GetConn() *pool.Conn
       IsBlocking() bool
   }
   ```

4. Adapter Pattern Implementation:
   - Created handlerAdapter to bridge internal and public interfaces
   - Created voidProcessorAdapter for void processor functionality
   - Seamless conversion between internal and public contexts
   - Maintains compatibility with existing internal architecture

5. Context Conversion Functions:
   - convertInternalToPublicContext() for seamless conversion
   - Proper context bridging between internal and public APIs
   - Maintains all context information during conversion
   - Consistent behavior across all client types

6. Updated All Integration Points:
   - Updated redis.go to use public context conversion
   - Updated pubsub.go to use public context conversion
   - Updated sentinel.go to use void processor adapter
   - Maintained backward compatibility with existing code

7. Handler Usage Example:
   ```go
   func (h *MyHandler) HandlePushNotification(
       ctx context.Context,
       handlerCtx PushNotificationHandlerContext,
       notification []interface{},
   ) bool {
       // Direct access to concrete types - no casting needed!
       if clusterClient := handlerCtx.GetClusterClient(); clusterClient != nil {
           // Full access to ClusterClient methods
           nodes := clusterClient.ClusterNodes(ctx)
           // ... cluster-specific logic
       }

       if regularClient := handlerCtx.GetRegularClient(); regularClient != nil {
           // Full access to Client methods
           info := regularClient.Info(ctx)
           // ... regular client logic
       }

       return true
   }
   ```

8. Type Safety Improvements:
   - No interface{} fields in public API
   - Concrete return types for all getters
   - Compile-time verification of client type usage
   - Clear API with explicit client type access
   - Enhanced developer experience with full type information

Benefits:
- Strongly typed access to concrete Redis client types
- No type assertions or interface casting required
- Full IntelliSense support for client-specific methods
- Compile-time type checking prevents runtime errors
- Clean public API with concrete types
- Seamless integration with existing internal architecture
- Enhanced developer experience and productivity

This implementation provides handlers with direct access to concrete Redis
client types while maintaining the flexibility and context information needed
for sophisticated push notification handling, particularly important for
hitless upgrades and cluster management operations.
2025-07-04 20:04:03 +03:00
1606de8b73 feat: implement strongly typed HandlerContext interface
Convert HandlerContext from struct to interface with strongly typed getters
for different client types. This provides better type safety and a cleaner
API for push notification handlers while maintaining flexibility.

Key Changes:

1. HandlerContext Interface Design:
   - Converted HandlerContext from struct to interface
   - Added strongly typed getters for different client types
   - GetClusterClient() returns ClusterClientInterface
   - GetSentinelClient() returns SentinelClientInterface
   - GetFailoverClient() returns FailoverClientInterface
   - GetRegularClient() returns RegularClientInterface
   - GetPubSub() returns PubSubInterface

2. Client Type Interfaces:
   - Defined ClusterClientInterface for cluster client access
   - Defined SentinelClientInterface for sentinel client access
   - Defined FailoverClientInterface for failover client access
   - Defined RegularClientInterface for regular client access
   - Defined PubSubInterface for pub/sub access
   - Each interface provides String() method for basic operations

3. Concrete Implementation:
   - Created handlerContext struct implementing HandlerContext interface
   - Added NewHandlerContext constructor function
   - Implemented type-safe getters with interface casting
   - Returns nil for incorrect client types (type safety)

4. Updated All Usage:
   - Updated Handler interface to use HandlerContext interface
   - Updated ProcessorInterface to use HandlerContext interface
   - Updated all processor implementations (Processor, VoidProcessor)
   - Updated all handler context creation sites
   - Updated test handlers and test context creation

5. Helper Methods:
   - Updated pushNotificationHandlerContext() in baseClient
   - Updated pushNotificationHandlerContext() in PubSub
   - Consistent context creation across all client types
   - Proper parameter passing for different connection types

6. Type Safety Benefits:
   - Handlers can safely cast to specific client types
   - Compile-time checking for client type access
   - Clear API for accessing different client capabilities
   - No runtime panics from incorrect type assertions

7. API Usage Example:
   ```go
   func (h *MyHandler) HandlePushNotification(
       ctx context.Context,
       handlerCtx HandlerContext,
       notification []interface{},
   ) bool {
       // Strongly typed access
       if clusterClient := handlerCtx.GetClusterClient(); clusterClient != nil {
           // Handle cluster-specific logic
       }
       if sentinelClient := handlerCtx.GetSentinelClient(); sentinelClient != nil {
           // Handle sentinel-specific logic
       }
       return true
   }
   ```

8. Backward Compatibility:
   - Interface maintains same functionality as original struct
   - All existing handler patterns continue to work
   - No breaking changes to handler implementations
   - Smooth migration path for existing code

Benefits:
- Strong type safety for client access in handlers
- Clear API with explicit client type getters
- Compile-time checking prevents runtime errors
- Flexible interface allows future extensions
- Better separation of concerns between client types
- Enhanced developer experience with IntelliSense support

This enhancement provides handlers with strongly typed access to different
Redis client types while maintaining the flexibility and context information
needed for sophisticated push notification handling, particularly important
for hitless upgrades and cluster management operations.
2025-07-04 19:53:19 +03:00
47dd490a8a feat: enhance push notification handlers with context information 2025-07-04 18:16:15 +03:00
9a7a5c853b fix: add nil reader check in ProcessPendingNotifications to prevent panic
- 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.
2025-06-27 15:05:16 +03:00
be9b6dd6a0 refactor: remove unnecessary enabled field and IsEnabled/SetEnabled methods
- 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
2025-06-27 01:36:38 +03:00
fdfcf94300 feat: add VoidPushNotificationProcessor for disabled push notifications
- 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
2025-06-27 01:36:35 +03:00
b02eed63b2 feat: add general push notification system
- 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.
2025-06-27 01:36:08 +03:00
bb8d508481 fix: PubSub isn't concurrency-safe (#3360) 2025-04-29 09:39:26 +03:00
0cfcd1a61d update pubsub.go (#3329) 2025-04-03 16:10:31 +03:00
26e0c49acf Update pubsub.go (#3042)
Change context.Background() to ctx
2024-07-05 10:27:44 +08:00
6960bcc08d chore: fix some comments (#2967)
Signed-off-by: kindknow <iturf@sina.com>
Co-authored-by: Monkey <golang@88.com>
2024-04-14 01:15:23 +08:00
e053f7eaf3 update PubSub.Channel documentation (#2761)
Co-authored-by: ofekshenawa <104765379+ofekshenawa@users.noreply.github.com>
2023-10-30 14:35:02 +02:00
97b491aace chore: update import path 2023-01-23 08:48:54 +02:00
331e40dc6c fix: reset pubsub state when unsubscribing from all channels 2022-10-14 15:15:06 +03:00
58f7149e38 feat: add ContextTimeoutEnabled to respect context timeouts and deadlines 2022-10-11 10:22:42 +03:00
baa48a4415 feat(pubsub): support sharded pub/sub 2022-08-04 00:05:22 +08:00
a18fad5bd3 chore: v9 2022-06-04 17:42:06 +03:00
c98c5f0eeb fix: update ChannelWithSubscriptions to accept options 2022-06-04 16:20:10 +03:00
98bb99ddc2 Fix Redis Cluster issue during roll outs of new nodes with same addr (#1914)
* fix: recycle connections in some Redis Cluster scenarios

This issue was surfaced in a Cloud Provider solution that used for
rolling out new nodes using the same address (hostname) of the nodes
that will be replaced in a Redis Cluster, while the former ones once
depromoted as Slaves would continue in service during some mintues
for redirecting traffic.

The solution basically identifies when the connection could be stale
since a MOVED response will be returned using the same address (hostname)
that is being used by the connection. At that moment we consider the
connection as no longer usable forcing to recycle the connection.
2021-10-04 13:10:42 +03:00
b94bde306e Fix/pubsub ping mutex (#1878)
* Fix PubSub.Ping to hold the lock

* Fix PubSub.Ping to hold the lock

* add write cmd data-race test

Signed-off-by: monkey92t <golang@88.com>

Co-authored-by: monkey92t <golang@88.com>
2021-09-03 17:57:34 +08:00
37f5a2b1cd Update changelog 2021-05-26 15:12:25 +03:00
8e8510431d Improve pubsub (#1764)
* Improve pubsub

Signed-off-by: monkey92t <golang@88.com>

* Extract code to channel struct and tweak API

* Move chanSendTimeout to channel

* Cleanup health check

* Add WithChannelSendTimeout and tweak comments

* clear notes

Signed-off-by: monkey92t <golang@88.com>

Co-authored-by: Vladimir Mihailenco <vladimir.webdev@gmail.com>
2021-05-26 11:25:18 +08:00
a2410beb43 upgrade golangci-lint to v1.39.0
Signed-off-by: monkey <golang@88.com>
2021-04-08 14:44:31 +08:00
02a9c81ef1 Fix golangci-lint check 2021-03-23 11:02:29 +02:00
76f1e50d50 Do not use retry backoff in PubSub 2020-09-17 12:54:48 +03:00
8a25ceadae Merge pull request #1448 from rueian/pubsub-message-payload-slice
Support string array in pubsub message payload
2020-09-08 18:02:19 +03:00
c357d18624 Faster renew the subscription 2020-09-05 10:56:09 +03:00
f5f73f8033 Support string array in pubsub message payload 2020-08-21 17:29:37 +08:00
8a3f304b25 Log with context to associate all log by traceID (#1413)
* Log with context to associate all log by traceID
2020-07-18 09:04:36 +03:00
4440575966 Merge branch 'v8' 2020-05-21 10:16:44 +03:00
eecd319ee3 Fix nil type assertion 2020-05-21 09:11:00 +03:00
3dcb844106 Bump major version 2020-05-19 08:52:38 +03:00
f5593121e0 Add ctx as first arg 2020-05-19 08:52:38 +03:00
7247939b32 Fix "redis: discarding bad PubSub connection" stuck state (#1162)
* Reset healthy on reconnect
2019-09-30 11:24:53 +03:00
7779accbea Use semantic import versioning 2019-08-08 14:29:44 +03:00
4e9cea8876 Add proper SingleConnPool implementation 2019-08-03 17:31:28 +03:00
f3ce3362a0 Add golangci-lint 2019-07-25 14:36:50 +03:00
11ef80b162 Change PubSub.Channel 2019-07-09 10:25:27 +03:00
3bdf64784a Cleanup 2019-06-17 12:32:40 +03:00
5460bc10f2 Use Context.Deadline to set net.Conn deadline 2019-06-08 15:02:51 +03:00
af59960088 Typo error in comments 2019-04-08 20:06:31 +08:00
b6fdeca648 Add PubSub.ChannelSize 2019-03-12 12:48:32 +02:00
21913a8304 pubsub: drop a message when the channel is full 2019-03-12 12:40:08 +02:00
daf101bd79 Fix nil ping error 2018-10-09 10:52:30 +03:00
6a768df38b . 2018-10-01 11:38:21 +03:00
0197108027 Use bufio.Writer 2018-08-17 14:14:02 +03:00
5146fb0c57 Cleanup buffers manipulation 2018-08-15 11:53:15 +03:00
7c26d1ceb6 Pass cn.Rd where possible 2018-08-15 09:38:58 +03:00
e3b56f7641 pubsub: fix ping logic 2018-08-07 16:48:32 +03:00