56 lines
1.8 KiB
Go
56 lines
1.8 KiB
Go
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)
|
|
}
|