github.com/adoriasoft/tendermint@v0.34.0-dev1.0.20200722151356-96d84601a75a/types/event_bus.go (about) 1 package types 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/tendermint/tendermint/abci/types" 8 "github.com/tendermint/tendermint/libs/log" 9 tmpubsub "github.com/tendermint/tendermint/libs/pubsub" 10 "github.com/tendermint/tendermint/libs/service" 11 ) 12 13 const defaultCapacity = 0 14 15 type EventBusSubscriber interface { 16 Subscribe(ctx context.Context, subscriber string, query tmpubsub.Query, outCapacity ...int) (Subscription, error) 17 Unsubscribe(ctx context.Context, subscriber string, query tmpubsub.Query) error 18 UnsubscribeAll(ctx context.Context, subscriber string) error 19 20 NumClients() int 21 NumClientSubscriptions(clientID string) int 22 } 23 24 type Subscription interface { 25 Out() <-chan tmpubsub.Message 26 Cancelled() <-chan struct{} 27 Err() error 28 } 29 30 // EventBus is a common bus for all events going through the system. All calls 31 // are proxied to underlying pubsub server. All events must be published using 32 // EventBus to ensure correct data types. 33 type EventBus struct { 34 service.BaseService 35 pubsub *tmpubsub.Server 36 } 37 38 // NewEventBus returns a new event bus. 39 func NewEventBus() *EventBus { 40 return NewEventBusWithBufferCapacity(defaultCapacity) 41 } 42 43 // NewEventBusWithBufferCapacity returns a new event bus with the given buffer capacity. 44 func NewEventBusWithBufferCapacity(cap int) *EventBus { 45 // capacity could be exposed later if needed 46 pubsub := tmpubsub.NewServer(tmpubsub.BufferCapacity(cap)) 47 b := &EventBus{pubsub: pubsub} 48 b.BaseService = *service.NewBaseService(nil, "EventBus", b) 49 return b 50 } 51 52 func (b *EventBus) SetLogger(l log.Logger) { 53 b.BaseService.SetLogger(l) 54 b.pubsub.SetLogger(l.With("module", "pubsub")) 55 } 56 57 func (b *EventBus) OnStart() error { 58 return b.pubsub.Start() 59 } 60 61 func (b *EventBus) OnStop() { 62 b.pubsub.Stop() 63 } 64 65 func (b *EventBus) NumClients() int { 66 return b.pubsub.NumClients() 67 } 68 69 func (b *EventBus) NumClientSubscriptions(clientID string) int { 70 return b.pubsub.NumClientSubscriptions(clientID) 71 } 72 73 func (b *EventBus) Subscribe( 74 ctx context.Context, 75 subscriber string, 76 query tmpubsub.Query, 77 outCapacity ...int, 78 ) (Subscription, error) { 79 return b.pubsub.Subscribe(ctx, subscriber, query, outCapacity...) 80 } 81 82 // This method can be used for a local consensus explorer and synchronous 83 // testing. Do not use for for public facing / untrusted subscriptions! 84 func (b *EventBus) SubscribeUnbuffered( 85 ctx context.Context, 86 subscriber string, 87 query tmpubsub.Query, 88 ) (Subscription, error) { 89 return b.pubsub.SubscribeUnbuffered(ctx, subscriber, query) 90 } 91 92 func (b *EventBus) Unsubscribe(ctx context.Context, subscriber string, query tmpubsub.Query) error { 93 return b.pubsub.Unsubscribe(ctx, subscriber, query) 94 } 95 96 func (b *EventBus) UnsubscribeAll(ctx context.Context, subscriber string) error { 97 return b.pubsub.UnsubscribeAll(ctx, subscriber) 98 } 99 100 func (b *EventBus) Publish(eventType string, eventData TMEventData) error { 101 // no explicit deadline for publishing events 102 ctx := context.Background() 103 return b.pubsub.PublishWithEvents(ctx, eventData, map[string][]string{EventTypeKey: {eventType}}) 104 } 105 106 // validateAndStringifyEvents takes a slice of event objects and creates a 107 // map of stringified events where each key is composed of the event 108 // type and each of the event's attributes keys in the form of 109 // "{event.Type}.{attribute.Key}" and the value is each attribute's value. 110 func (b *EventBus) validateAndStringifyEvents(events []types.Event, logger log.Logger) map[string][]string { 111 result := make(map[string][]string) 112 for _, event := range events { 113 if len(event.Type) == 0 { 114 logger.Debug("Got an event with an empty type (skipping)", "event", event) 115 continue 116 } 117 118 for _, attr := range event.Attributes { 119 if len(attr.Key) == 0 { 120 logger.Debug("Got an event attribute with an empty key(skipping)", "event", event) 121 continue 122 } 123 124 compositeTag := fmt.Sprintf("%s.%s", event.Type, string(attr.Key)) 125 result[compositeTag] = append(result[compositeTag], string(attr.Value)) 126 } 127 } 128 129 return result 130 } 131 132 func (b *EventBus) PublishEventNewBlock(data EventDataNewBlock) error { 133 // no explicit deadline for publishing events 134 ctx := context.Background() 135 136 resultEvents := append(data.ResultBeginBlock.Events, data.ResultEndBlock.Events...) 137 events := b.validateAndStringifyEvents(resultEvents, b.Logger.With("block", data.Block.StringShort())) 138 139 // add predefined new block event 140 events[EventTypeKey] = append(events[EventTypeKey], EventNewBlock) 141 142 return b.pubsub.PublishWithEvents(ctx, data, events) 143 } 144 145 func (b *EventBus) PublishEventNewBlockHeader(data EventDataNewBlockHeader) error { 146 // no explicit deadline for publishing events 147 ctx := context.Background() 148 149 resultTags := append(data.ResultBeginBlock.Events, data.ResultEndBlock.Events...) 150 // TODO: Create StringShort method for Header and use it in logger. 151 events := b.validateAndStringifyEvents(resultTags, b.Logger.With("header", data.Header)) 152 153 // add predefined new block header event 154 events[EventTypeKey] = append(events[EventTypeKey], EventNewBlockHeader) 155 156 return b.pubsub.PublishWithEvents(ctx, data, events) 157 } 158 159 func (b *EventBus) PublishEventNewEvidence(evidence EventDataNewEvidence) error { 160 return b.Publish(EventNewEvidence, evidence) 161 } 162 163 func (b *EventBus) PublishEventVote(data EventDataVote) error { 164 return b.Publish(EventVote, data) 165 } 166 167 func (b *EventBus) PublishEventValidBlock(data EventDataRoundState) error { 168 return b.Publish(EventValidBlock, data) 169 } 170 171 // PublishEventTx publishes tx event with events from Result. Note it will add 172 // predefined keys (EventTypeKey, TxHashKey). Existing events with the same keys 173 // will be overwritten. 174 func (b *EventBus) PublishEventTx(data EventDataTx) error { 175 // no explicit deadline for publishing events 176 ctx := context.Background() 177 178 events := b.validateAndStringifyEvents(data.Result.Events, b.Logger.With("tx", data.Tx)) 179 180 // add predefined compositeKeys 181 events[EventTypeKey] = append(events[EventTypeKey], EventTx) 182 events[TxHashKey] = append(events[TxHashKey], fmt.Sprintf("%X", Tx(data.Tx).Hash())) 183 events[TxHeightKey] = append(events[TxHeightKey], fmt.Sprintf("%d", data.Height)) 184 185 return b.pubsub.PublishWithEvents(ctx, data, events) 186 } 187 188 func (b *EventBus) PublishEventNewRoundStep(data EventDataRoundState) error { 189 return b.Publish(EventNewRoundStep, data) 190 } 191 192 func (b *EventBus) PublishEventTimeoutPropose(data EventDataRoundState) error { 193 return b.Publish(EventTimeoutPropose, data) 194 } 195 196 func (b *EventBus) PublishEventTimeoutWait(data EventDataRoundState) error { 197 return b.Publish(EventTimeoutWait, data) 198 } 199 200 func (b *EventBus) PublishEventNewRound(data EventDataNewRound) error { 201 return b.Publish(EventNewRound, data) 202 } 203 204 func (b *EventBus) PublishEventCompleteProposal(data EventDataCompleteProposal) error { 205 return b.Publish(EventCompleteProposal, data) 206 } 207 208 func (b *EventBus) PublishEventPolka(data EventDataRoundState) error { 209 return b.Publish(EventPolka, data) 210 } 211 212 func (b *EventBus) PublishEventUnlock(data EventDataRoundState) error { 213 return b.Publish(EventUnlock, data) 214 } 215 216 func (b *EventBus) PublishEventRelock(data EventDataRoundState) error { 217 return b.Publish(EventRelock, data) 218 } 219 220 func (b *EventBus) PublishEventLock(data EventDataRoundState) error { 221 return b.Publish(EventLock, data) 222 } 223 224 func (b *EventBus) PublishEventValidatorSetUpdates(data EventDataValidatorSetUpdates) error { 225 return b.Publish(EventValidatorSetUpdates, data) 226 } 227 228 //----------------------------------------------------------------------------- 229 type NopEventBus struct{} 230 231 func (NopEventBus) Subscribe( 232 ctx context.Context, 233 subscriber string, 234 query tmpubsub.Query, 235 out chan<- interface{}, 236 ) error { 237 return nil 238 } 239 240 func (NopEventBus) Unsubscribe(ctx context.Context, subscriber string, query tmpubsub.Query) error { 241 return nil 242 } 243 244 func (NopEventBus) UnsubscribeAll(ctx context.Context, subscriber string) error { 245 return nil 246 } 247 248 func (NopEventBus) PublishEventNewBlock(data EventDataNewBlock) error { 249 return nil 250 } 251 252 func (NopEventBus) PublishEventNewBlockHeader(data EventDataNewBlockHeader) error { 253 return nil 254 } 255 256 func (NopEventBus) PublishEventNewEvidence(evidence EventDataNewEvidence) error { 257 return nil 258 } 259 260 func (NopEventBus) PublishEventVote(data EventDataVote) error { 261 return nil 262 } 263 264 func (NopEventBus) PublishEventTx(data EventDataTx) error { 265 return nil 266 } 267 268 func (NopEventBus) PublishEventNewRoundStep(data EventDataRoundState) error { 269 return nil 270 } 271 272 func (NopEventBus) PublishEventTimeoutPropose(data EventDataRoundState) error { 273 return nil 274 } 275 276 func (NopEventBus) PublishEventTimeoutWait(data EventDataRoundState) error { 277 return nil 278 } 279 280 func (NopEventBus) PublishEventNewRound(data EventDataRoundState) error { 281 return nil 282 } 283 284 func (NopEventBus) PublishEventCompleteProposal(data EventDataRoundState) error { 285 return nil 286 } 287 288 func (NopEventBus) PublishEventPolka(data EventDataRoundState) error { 289 return nil 290 } 291 292 func (NopEventBus) PublishEventUnlock(data EventDataRoundState) error { 293 return nil 294 } 295 296 func (NopEventBus) PublishEventRelock(data EventDataRoundState) error { 297 return nil 298 } 299 300 func (NopEventBus) PublishEventLock(data EventDataRoundState) error { 301 return nil 302 } 303 304 func (NopEventBus) PublishEventValidatorSetUpdates(data EventDataValidatorSetUpdates) error { 305 return nil 306 }