github.com/okex/exchain@v1.8.0/libs/tendermint/types/event_bus.go (about) 1 package types 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/okex/exchain/libs/tendermint/abci/types" 8 "github.com/okex/exchain/libs/tendermint/libs/log" 9 tmpubsub "github.com/okex/exchain/libs/tendermint/libs/pubsub" 10 "github.com/okex/exchain/libs/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) PublishEventVote(data EventDataVote) error { 160 return b.Publish(EventVote, data) 161 } 162 163 func (b *EventBus) PublishEventValidBlock(data EventDataRoundState) error { 164 return b.Publish(EventValidBlock, data) 165 } 166 167 // PublishEventTx publishes tx event with events from Result. Note it will add 168 // predefined keys (EventTypeKey, TxHashKey). Existing events with the same keys 169 // will be overwritten. 170 func (b *EventBus) PublishEventTx(data EventDataTx) error { 171 // no explicit deadline for publishing events 172 ctx := context.Background() 173 174 events := b.validateAndStringifyEvents(data.Result.Events, b.Logger.With("tx", data.Tx)) 175 176 // add predefined compositeKeys 177 events[EventTypeKey] = append(events[EventTypeKey], EventTx) 178 events[TxHashKey] = append(events[TxHashKey], fmt.Sprintf("%X", data.Tx.Hash(data.Height))) 179 events[TxHeightKey] = append(events[TxHeightKey], fmt.Sprintf("%d", data.Height)) 180 181 return b.pubsub.PublishWithEvents(ctx, data, events) 182 } 183 184 func (b *EventBus) PublishEventTxs(data EventDataTxs) error { 185 return b.Publish(EventTxs, data) 186 } 187 188 func (b *EventBus) PublishEventPendingTx(data EventDataTx) error { 189 ctx := context.Background() 190 191 events := make(map[string][]string) 192 // add predefined compositeKeys 193 events[EventTypeKey] = append(events[EventTypeKey], EventPendingTx) 194 return b.pubsub.PublishWithEvents(ctx, data, events) 195 } 196 197 func (b *EventBus) PublishEventRmPendingTx(data EventDataRmPendingTx) error { 198 ctx := context.Background() 199 200 events := make(map[string][]string) 201 events[EventTypeKey] = append(events[EventTypeKey], EventRmPendingTx) 202 return b.pubsub.PublishWithEvents(ctx, data, events) 203 } 204 205 func (b *EventBus) PublishEventLatestBlockTime(data EventDataBlockTime) error { 206 ctx := context.Background() 207 events := make(map[string][]string) 208 events[EventTypeKey] = append(events[EventTypeKey], EventBlockTime) 209 return b.pubsub.PublishWithEvents(ctx, data, events) 210 } 211 212 func (b *EventBus) PublishEventNewRoundStep(data EventDataRoundState) error { 213 return b.Publish(EventNewRoundStep, data) 214 } 215 216 func (b *EventBus) PublishEventTimeoutPropose(data EventDataRoundState) error { 217 return b.Publish(EventTimeoutPropose, data) 218 } 219 220 func (b *EventBus) PublishEventTimeoutWait(data EventDataRoundState) error { 221 return b.Publish(EventTimeoutWait, data) 222 } 223 224 func (b *EventBus) PublishEventNewRound(data EventDataNewRound) error { 225 return b.Publish(EventNewRound, data) 226 } 227 228 func (b *EventBus) PublishEventCompleteProposal(data EventDataCompleteProposal) error { 229 return b.Publish(EventCompleteProposal, data) 230 } 231 232 func (b *EventBus) PublishEventPolka(data EventDataRoundState) error { 233 return b.Publish(EventPolka, data) 234 } 235 236 func (b *EventBus) PublishEventUnlock(data EventDataRoundState) error { 237 return b.Publish(EventUnlock, data) 238 } 239 240 func (b *EventBus) PublishEventRelock(data EventDataRoundState) error { 241 return b.Publish(EventRelock, data) 242 } 243 244 func (b *EventBus) PublishEventLock(data EventDataRoundState) error { 245 return b.Publish(EventLock, data) 246 } 247 248 func (b *EventBus) PublishEventValidatorSetUpdates(data EventDataValidatorSetUpdates) error { 249 return b.Publish(EventValidatorSetUpdates, data) 250 } 251 252 //----------------------------------------------------------------------------- 253 type NopEventBus struct{} 254 255 func (NopEventBus) Subscribe( 256 ctx context.Context, 257 subscriber string, 258 query tmpubsub.Query, 259 out chan<- interface{}, 260 ) error { 261 return nil 262 } 263 264 func (NopEventBus) Unsubscribe(ctx context.Context, subscriber string, query tmpubsub.Query) error { 265 return nil 266 } 267 268 func (NopEventBus) UnsubscribeAll(ctx context.Context, subscriber string) error { 269 return nil 270 } 271 272 func (NopEventBus) PublishEventNewBlock(data EventDataNewBlock) error { 273 return nil 274 } 275 276 func (NopEventBus) PublishEventNewBlockHeader(data EventDataNewBlockHeader) error { 277 return nil 278 } 279 280 func (NopEventBus) PublishEventVote(data EventDataVote) error { 281 return nil 282 } 283 284 func (NopEventBus) PublishEventTx(data EventDataTx) error { 285 return nil 286 } 287 288 func (NopEventBus) PublishEventTxs(data EventDataTxs) error { 289 return nil 290 } 291 292 func (NopEventBus) PublishEventPendingTx(data EventDataTx) error { 293 return nil 294 } 295 296 func (NopEventBus) PublishEventRmPendingTx(EventDataRmPendingTx) error { 297 return nil 298 } 299 300 func (NopEventBus) PublishEventNewRoundStep(data EventDataRoundState) error { 301 return nil 302 } 303 304 func (NopEventBus) PublishEventTimeoutPropose(data EventDataRoundState) error { 305 return nil 306 } 307 308 func (NopEventBus) PublishEventTimeoutWait(data EventDataRoundState) error { 309 return nil 310 } 311 312 func (NopEventBus) PublishEventNewRound(data EventDataRoundState) error { 313 return nil 314 } 315 316 func (NopEventBus) PublishEventCompleteProposal(data EventDataRoundState) error { 317 return nil 318 } 319 320 func (NopEventBus) PublishEventPolka(data EventDataRoundState) error { 321 return nil 322 } 323 324 func (NopEventBus) PublishEventUnlock(data EventDataRoundState) error { 325 return nil 326 } 327 328 func (NopEventBus) PublishEventRelock(data EventDataRoundState) error { 329 return nil 330 } 331 332 func (NopEventBus) PublishEventLock(data EventDataRoundState) error { 333 return nil 334 } 335 336 func (NopEventBus) PublishEventValidatorSetUpdates(data EventDataValidatorSetUpdates) error { 337 return nil 338 } 339 340 func (NopEventBus) PublishEventLatestBlockTime(data EventDataBlockTime) error { 341 return nil 342 }