mirror of
https://github.com/redis/go-redis.git
synced 2025-07-20 22:42:59 +03:00
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.
83 lines
2.3 KiB
Go
83 lines
2.3 KiB
Go
package pushprocessor
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
)
|
|
|
|
// Registry manages push notification handlers.
|
|
type Registry struct {
|
|
mu sync.RWMutex
|
|
handlers map[string]Handler
|
|
protected map[string]bool
|
|
}
|
|
|
|
// NewRegistry creates a new push notification registry.
|
|
func NewRegistry() *Registry {
|
|
return &Registry{
|
|
handlers: make(map[string]Handler),
|
|
protected: make(map[string]bool),
|
|
}
|
|
}
|
|
|
|
// RegisterHandler registers a handler for a specific 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.
|
|
func (r *Registry) RegisterHandler(pushNotificationName string, handler Handler, protected bool) error {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
|
|
if _, exists := r.handlers[pushNotificationName]; exists {
|
|
return fmt.Errorf("handler already registered for push notification: %s", pushNotificationName)
|
|
}
|
|
|
|
r.handlers[pushNotificationName] = handler
|
|
r.protected[pushNotificationName] = protected
|
|
return nil
|
|
}
|
|
|
|
// UnregisterHandler removes a handler for a specific push notification name.
|
|
// Returns an error if the handler is protected or doesn't exist.
|
|
func (r *Registry) UnregisterHandler(pushNotificationName string) error {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
|
|
_, exists := r.handlers[pushNotificationName]
|
|
if !exists {
|
|
return fmt.Errorf("no handler registered for push notification: %s", pushNotificationName)
|
|
}
|
|
|
|
if r.protected[pushNotificationName] {
|
|
return fmt.Errorf("cannot unregister protected handler for push notification: %s", pushNotificationName)
|
|
}
|
|
|
|
delete(r.handlers, pushNotificationName)
|
|
delete(r.protected, pushNotificationName)
|
|
return nil
|
|
}
|
|
|
|
// GetHandler returns the handler for a specific push notification name.
|
|
// Returns nil if no handler is registered for the given name.
|
|
func (r *Registry) GetHandler(pushNotificationName string) Handler {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
|
|
handler, exists := r.handlers[pushNotificationName]
|
|
if !exists {
|
|
return nil
|
|
}
|
|
return handler
|
|
}
|
|
|
|
// GetRegisteredPushNotificationNames returns a list of all registered push notification names.
|
|
func (r *Registry) GetRegisteredPushNotificationNames() []string {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
|
|
names := make([]string, 0, len(r.handlers))
|
|
for name := range r.handlers {
|
|
names = append(names, name)
|
|
}
|
|
return names
|
|
}
|