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