mirror of
https://github.com/redis/go-redis.git
synced 2025-07-29 17:41:15 +03:00
feat: add GetHandler method and improve push notification API encapsulation
- 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
This commit is contained in:
@ -96,17 +96,23 @@ func (r *PushNotificationRegistry) GetRegisteredPushNotificationNames() []string
|
|||||||
return names
|
return names
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasHandlers returns true if there are any handlers registered.
|
// GetHandler returns the handler for a specific push notification name.
|
||||||
func (r *PushNotificationRegistry) HasHandlers() bool {
|
// Returns nil if no handler is registered for the given name.
|
||||||
|
func (r *PushNotificationRegistry) GetHandler(pushNotificationName string) PushNotificationHandler {
|
||||||
r.mu.RLock()
|
r.mu.RLock()
|
||||||
defer r.mu.RUnlock()
|
defer r.mu.RUnlock()
|
||||||
|
|
||||||
return len(r.handlers) > 0
|
handler, exists := r.handlers[pushNotificationName]
|
||||||
|
if !exists {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return handler
|
||||||
}
|
}
|
||||||
|
|
||||||
// PushNotificationProcessorInterface defines the interface for push notification processors.
|
// PushNotificationProcessorInterface defines the interface for push notification processors.
|
||||||
type PushNotificationProcessorInterface interface {
|
type PushNotificationProcessorInterface interface {
|
||||||
GetRegistry() *PushNotificationRegistry
|
GetHandler(pushNotificationName string) PushNotificationHandler
|
||||||
|
GetRegistry() *PushNotificationRegistry // For backward compatibility and testing
|
||||||
ProcessPendingNotifications(ctx context.Context, rd *proto.Reader) error
|
ProcessPendingNotifications(ctx context.Context, rd *proto.Reader) error
|
||||||
RegisterHandler(pushNotificationName string, handler PushNotificationHandler, protected bool) error
|
RegisterHandler(pushNotificationName string, handler PushNotificationHandler, protected bool) error
|
||||||
}
|
}
|
||||||
@ -123,16 +129,20 @@ func NewPushNotificationProcessor() *PushNotificationProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRegistry returns the push notification registry.
|
// GetHandler returns the handler for a specific push notification name.
|
||||||
|
// Returns nil if no handler is registered for the given name.
|
||||||
|
func (p *PushNotificationProcessor) GetHandler(pushNotificationName string) PushNotificationHandler {
|
||||||
|
return p.registry.GetHandler(pushNotificationName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRegistry returns the push notification registry for internal use.
|
||||||
|
// This method is primarily for testing and internal operations.
|
||||||
func (p *PushNotificationProcessor) GetRegistry() *PushNotificationRegistry {
|
func (p *PushNotificationProcessor) GetRegistry() *PushNotificationRegistry {
|
||||||
return p.registry
|
return p.registry
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcessPendingNotifications checks for and processes any pending push notifications.
|
// ProcessPendingNotifications checks for and processes any pending push notifications.
|
||||||
func (p *PushNotificationProcessor) ProcessPendingNotifications(ctx context.Context, rd *proto.Reader) error {
|
func (p *PushNotificationProcessor) ProcessPendingNotifications(ctx context.Context, rd *proto.Reader) error {
|
||||||
if !p.registry.HasHandlers() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if there are any buffered bytes that might contain push notifications
|
// Check if there are any buffered bytes that might contain push notifications
|
||||||
if rd.Buffered() == 0 {
|
if rd.Buffered() == 0 {
|
||||||
@ -233,6 +243,11 @@ func NewVoidPushNotificationProcessor() *VoidPushNotificationProcessor {
|
|||||||
return &VoidPushNotificationProcessor{}
|
return &VoidPushNotificationProcessor{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetHandler returns nil for void processor since it doesn't maintain handlers.
|
||||||
|
func (v *VoidPushNotificationProcessor) GetHandler(pushNotificationName string) PushNotificationHandler {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetRegistry returns nil for void processor since it doesn't maintain handlers.
|
// GetRegistry returns nil for void processor since it doesn't maintain handlers.
|
||||||
func (v *VoidPushNotificationProcessor) GetRegistry() *PushNotificationRegistry {
|
func (v *VoidPushNotificationProcessor) GetRegistry() *PushNotificationRegistry {
|
||||||
return nil
|
return nil
|
||||||
|
@ -28,9 +28,7 @@ func TestPushNotificationRegistry(t *testing.T) {
|
|||||||
registry := redis.NewPushNotificationRegistry()
|
registry := redis.NewPushNotificationRegistry()
|
||||||
|
|
||||||
// Test initial state
|
// Test initial state
|
||||||
if registry.HasHandlers() {
|
// Registry starts empty (no need to check HasHandlers anymore)
|
||||||
t.Error("Registry should not have handlers initially")
|
|
||||||
}
|
|
||||||
|
|
||||||
commands := registry.GetRegisteredPushNotificationNames()
|
commands := registry.GetRegisteredPushNotificationNames()
|
||||||
if len(commands) != 0 {
|
if len(commands) != 0 {
|
||||||
@ -49,10 +47,7 @@ func TestPushNotificationRegistry(t *testing.T) {
|
|||||||
t.Fatalf("Failed to register handler: %v", err)
|
t.Fatalf("Failed to register handler: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !registry.HasHandlers() {
|
// Verify handler was registered by checking registered names
|
||||||
t.Error("Registry should have handlers after registration")
|
|
||||||
}
|
|
||||||
|
|
||||||
commands = registry.GetRegisteredPushNotificationNames()
|
commands = registry.GetRegisteredPushNotificationNames()
|
||||||
if len(commands) != 1 || commands[0] != "TEST_COMMAND" {
|
if len(commands) != 1 || commands[0] != "TEST_COMMAND" {
|
||||||
t.Errorf("Expected ['TEST_COMMAND'], got %v", commands)
|
t.Errorf("Expected ['TEST_COMMAND'], got %v", commands)
|
||||||
@ -803,7 +798,6 @@ func TestPushNotificationRegistryConcurrency(t *testing.T) {
|
|||||||
registry.HandleNotification(context.Background(), notification)
|
registry.HandleNotification(context.Background(), notification)
|
||||||
|
|
||||||
// Check registry state
|
// Check registry state
|
||||||
registry.HasHandlers()
|
|
||||||
registry.GetRegisteredPushNotificationNames()
|
registry.GetRegisteredPushNotificationNames()
|
||||||
}
|
}
|
||||||
}(i)
|
}(i)
|
||||||
@ -815,10 +809,6 @@ func TestPushNotificationRegistryConcurrency(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify registry is still functional
|
// Verify registry is still functional
|
||||||
if !registry.HasHandlers() {
|
|
||||||
t.Error("Registry should have handlers after concurrent operations")
|
|
||||||
}
|
|
||||||
|
|
||||||
commands := registry.GetRegisteredPushNotificationNames()
|
commands := registry.GetRegisteredPushNotificationNames()
|
||||||
if len(commands) == 0 {
|
if len(commands) == 0 {
|
||||||
t.Error("Registry should have registered commands after concurrent operations")
|
t.Error("Registry should have registered commands after concurrent operations")
|
||||||
|
6
redis.go
6
redis.go
@ -837,6 +837,12 @@ func (c *Client) GetPushNotificationProcessor() PushNotificationProcessorInterfa
|
|||||||
return c.pushProcessor
|
return c.pushProcessor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPushNotificationHandler returns the handler for a specific push notification name.
|
||||||
|
// Returns nil if no handler is registered for the given name.
|
||||||
|
func (c *Client) GetPushNotificationHandler(pushNotificationName string) PushNotificationHandler {
|
||||||
|
return c.pushProcessor.GetHandler(pushNotificationName)
|
||||||
|
}
|
||||||
|
|
||||||
type PoolStats pool.Stats
|
type PoolStats pool.Stats
|
||||||
|
|
||||||
// PoolStats returns connection pool stats.
|
// PoolStats returns connection pool stats.
|
||||||
|
@ -522,6 +522,12 @@ func (c *SentinelClient) GetPushNotificationProcessor() PushNotificationProcesso
|
|||||||
return c.pushProcessor
|
return c.pushProcessor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPushNotificationHandler returns the handler for a specific push notification name.
|
||||||
|
// Returns nil if no handler is registered for the given name.
|
||||||
|
func (c *SentinelClient) GetPushNotificationHandler(pushNotificationName string) PushNotificationHandler {
|
||||||
|
return c.pushProcessor.GetHandler(pushNotificationName)
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterPushNotificationHandler registers a handler for a specific push notification name.
|
// RegisterPushNotificationHandler registers a handler for a specific push notification name.
|
||||||
// Returns an error if a handler is already registered for this push notification name.
|
// Returns an error if a handler is already registered for this push notification name.
|
||||||
// If protected is true, the handler cannot be unregistered.
|
// If protected is true, the handler cannot be unregistered.
|
||||||
|
Reference in New Issue
Block a user