github.com/Team-Kujira/tendermint@v0.34.24-indexer/libs/pubsub/subscription.go (about) 1 package pubsub 2 3 import ( 4 "errors" 5 6 tmsync "github.com/tendermint/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("internal subscription event buffer is out of capacity") 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 canceled 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 canceled: 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.canceled 50 } 51 52 // Err returns nil if the channel returned 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 // 58 // After Err returns a non-nil error, successive calls to Err return the same 59 // error. 60 func (s *Subscription) Err() error { 61 s.mtx.RLock() 62 defer s.mtx.RUnlock() 63 return s.err 64 } 65 66 func (s *Subscription) cancel(err error) { 67 s.mtx.Lock() 68 s.err = err 69 s.mtx.Unlock() 70 close(s.canceled) 71 } 72 73 // Message glues data and events together. 74 type Message struct { 75 data interface{} 76 events map[string][]string 77 } 78 79 func NewMessage(data interface{}, events map[string][]string) Message { 80 return Message{data, events} 81 } 82 83 // Data returns an original data published. 84 func (msg Message) Data() interface{} { 85 return msg.data 86 } 87 88 // Events returns events, which matched the client's query. 89 func (msg Message) Events() map[string][]string { 90 return msg.events 91 }