github.com/vipernet-xyz/tendermint-core@v0.32.0/libs/pubsub/subscription.go (about) 1 package pubsub 2 3 import ( 4 "errors" 5 "sync" 6 ) 7 8 var ( 9 // ErrUnsubscribed is returned by Err when a client unsubscribes. 10 ErrUnsubscribed = errors.New("client unsubscribed") 11 12 // ErrOutOfCapacity is returned by Err when a client is not pulling messages 13 // fast enough. Note the client's subscription will be terminated. 14 ErrOutOfCapacity = errors.New("client is not pulling messages fast enough") 15 ) 16 17 // A Subscription represents a client subscription for a particular query and 18 // consists of three things: 19 // 1) channel onto which messages and events are published 20 // 2) channel which is closed if a client is too slow or choose to unsubscribe 21 // 3) err indicating the reason for (2) 22 type Subscription struct { 23 out chan Message 24 25 cancelled chan struct{} 26 mtx sync.RWMutex 27 err error 28 } 29 30 // NewSubscription returns a new subscription with the given outCapacity. 31 func NewSubscription(outCapacity int) *Subscription { 32 return &Subscription{ 33 out: make(chan Message, outCapacity), 34 cancelled: make(chan struct{}), 35 } 36 } 37 38 // Out returns a channel onto which messages and events are published. 39 // Unsubscribe/UnsubscribeAll does not close the channel to avoid clients from 40 // receiving a nil message. 41 func (s *Subscription) Out() <-chan Message { 42 return s.out 43 } 44 45 // Cancelled returns a channel that's closed when the subscription is 46 // terminated and supposed to be used in a select statement. 47 func (s *Subscription) Cancelled() <-chan struct{} { 48 return s.cancelled 49 } 50 51 // Err returns nil if the channel returned by Cancelled is not yet closed. 52 // If the channel is closed, Err returns a non-nil error explaining why: 53 // - ErrUnsubscribed if the subscriber choose to unsubscribe, 54 // - ErrOutOfCapacity if the subscriber is not pulling messages fast enough 55 // and the channel returned by Out became full, 56 // After Err returns a non-nil error, successive calls to Err return the same 57 // error. 58 func (s *Subscription) Err() error { 59 s.mtx.RLock() 60 defer s.mtx.RUnlock() 61 return s.err 62 } 63 64 func (s *Subscription) cancel(err error) { 65 s.mtx.Lock() 66 s.err = err 67 s.mtx.Unlock() 68 close(s.cancelled) 69 } 70 71 // Message glues data and events together. 72 type Message struct { 73 data interface{} 74 events map[string][]string 75 } 76 77 func NewMessage(data interface{}, events map[string][]string) Message { 78 return Message{data, events} 79 } 80 81 // Data returns an original data published. 82 func (msg Message) Data() interface{} { 83 return msg.data 84 } 85 86 // Events returns events, which matched the client's query. 87 func (msg Message) Events() map[string][]string { 88 return msg.events 89 }