package notify import "sync" // Subscriber represents a client subscribed to receive notifications. // Each subscriber has a unique ID and receives notifications through // a buffered channel. Subscribers are created via Notifier.Subscribe(). type Subscriber struct { // ID is the unique identifier for this subscriber. // This is automatically generated using cryptographic random bytes. ID Target // notifications is the buffered channel for receiving notifications. // The buffer size is determined by the Notifier's configuration. notifications chan Notification // notifier is a reference back to the parent Notifier. notifier *Notifier // unsubscribelock protects the unsubscribe operation. unsubscribelock *sync.Mutex // unsubscribed tracks whether this subscriber has been unsubscribed. unsubscribed bool } // Listen returns a receive-only channel for reading notifications. // Use this channel in a for-range loop to process notifications: // // for notification := range sub.Listen() { // // Process notification // fmt.Println(notification.Message) // } // // The channel will be closed when the subscriber unsubscribes or // when the notifier is closed. func (s *Subscriber) Listen() <-chan Notification { return s.notifications } // Unsubscribe removes this subscriber from the notifier and closes the notification channel. // It is safe to call Unsubscribe multiple times; subsequent calls are no-ops. // After unsubscribe, the channel returned by Listen() will be closed immediately. // Any goroutines reading from Listen() will detect the closure and can exit gracefully. func (s *Subscriber) Unsubscribe() { s.unsubscribelock.Lock() if s.unsubscribed { s.unsubscribelock.Unlock() return } s.unsubscribed = true s.unsubscribelock.Unlock() s.notifier.RemoveSubscriber(s) }