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