github.com/evdatsion/aphelion-dpos-bft@v0.32.1/types/event_bus.go (about)

     1  package types
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/evdatsion/aphelion-dpos-bft/abci/types"
     8  	cmn "github.com/evdatsion/aphelion-dpos-bft/libs/common"
     9  	"github.com/evdatsion/aphelion-dpos-bft/libs/log"
    10  	tmpubsub "github.com/evdatsion/aphelion-dpos-bft/libs/pubsub"
    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  	cmn.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 = *cmn.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(ctx context.Context, subscriber string, query tmpubsub.Query, outCapacity ...int) (Subscription, error) {
    74  	return b.pubsub.Subscribe(ctx, subscriber, query, outCapacity...)
    75  }
    76  
    77  // This method can be used for a local consensus explorer and synchronous
    78  // testing. Do not use for for public facing / untrusted subscriptions!
    79  func (b *EventBus) SubscribeUnbuffered(ctx context.Context, subscriber string, query tmpubsub.Query) (Subscription, error) {
    80  	return b.pubsub.SubscribeUnbuffered(ctx, subscriber, query)
    81  }
    82  
    83  func (b *EventBus) Unsubscribe(ctx context.Context, subscriber string, query tmpubsub.Query) error {
    84  	return b.pubsub.Unsubscribe(ctx, subscriber, query)
    85  }
    86  
    87  func (b *EventBus) UnsubscribeAll(ctx context.Context, subscriber string) error {
    88  	return b.pubsub.UnsubscribeAll(ctx, subscriber)
    89  }
    90  
    91  func (b *EventBus) Publish(eventType string, eventData TMEventData) error {
    92  	// no explicit deadline for publishing events
    93  	ctx := context.Background()
    94  	return b.pubsub.PublishWithEvents(ctx, eventData, map[string][]string{EventTypeKey: {eventType}})
    95  }
    96  
    97  // validateAndStringifyEvents takes a slice of event objects and creates a
    98  // map of stringified events where each key is composed of the event
    99  // type and each of the event's attributes keys in the form of
   100  // "{event.Type}.{attribute.Key}" and the value is each attribute's value.
   101  func (b *EventBus) validateAndStringifyEvents(events []types.Event, logger log.Logger) map[string][]string {
   102  	result := make(map[string][]string)
   103  	for _, event := range events {
   104  		if len(event.Type) == 0 {
   105  			logger.Debug("Got an event with an empty type (skipping)", "event", event)
   106  			continue
   107  		}
   108  
   109  		for _, attr := range event.Attributes {
   110  			if len(attr.Key) == 0 {
   111  				logger.Debug("Got an event attribute with an empty key(skipping)", "event", event)
   112  				continue
   113  			}
   114  
   115  			compositeTag := fmt.Sprintf("%s.%s", event.Type, string(attr.Key))
   116  			result[compositeTag] = append(result[compositeTag], string(attr.Value))
   117  		}
   118  	}
   119  
   120  	return result
   121  }
   122  
   123  func (b *EventBus) PublishEventNewBlock(data EventDataNewBlock) error {
   124  	// no explicit deadline for publishing events
   125  	ctx := context.Background()
   126  
   127  	resultEvents := append(data.ResultBeginBlock.Events, data.ResultEndBlock.Events...)
   128  	events := b.validateAndStringifyEvents(resultEvents, b.Logger.With("block", data.Block.StringShort()))
   129  
   130  	// add predefined new block event
   131  	events[EventTypeKey] = append(events[EventTypeKey], EventNewBlock)
   132  
   133  	return b.pubsub.PublishWithEvents(ctx, data, events)
   134  }
   135  
   136  func (b *EventBus) PublishEventNewBlockHeader(data EventDataNewBlockHeader) error {
   137  	// no explicit deadline for publishing events
   138  	ctx := context.Background()
   139  
   140  	resultTags := append(data.ResultBeginBlock.Events, data.ResultEndBlock.Events...)
   141  	// TODO: Create StringShort method for Header and use it in logger.
   142  	events := b.validateAndStringifyEvents(resultTags, b.Logger.With("header", data.Header))
   143  
   144  	// add predefined new block header event
   145  	events[EventTypeKey] = append(events[EventTypeKey], EventNewBlockHeader)
   146  
   147  	return b.pubsub.PublishWithEvents(ctx, data, events)
   148  }
   149  
   150  func (b *EventBus) PublishEventVote(data EventDataVote) error {
   151  	return b.Publish(EventVote, data)
   152  }
   153  
   154  func (b *EventBus) PublishEventValidBlock(data EventDataRoundState) error {
   155  	return b.Publish(EventValidBlock, data)
   156  }
   157  
   158  // PublishEventTx publishes tx event with tags from Result. Note it will add
   159  // predefined tags (EventTypeKey, TxHashKey). Existing tags with the same names
   160  // will be overwritten.
   161  func (b *EventBus) PublishEventTx(data EventDataTx) error {
   162  	// no explicit deadline for publishing events
   163  	ctx := context.Background()
   164  
   165  	events := b.validateAndStringifyEvents(data.Result.Events, b.Logger.With("tx", data.Tx))
   166  
   167  	// add predefined tags
   168  	events[EventTypeKey] = append(events[EventTypeKey], EventTx)
   169  	events[TxHashKey] = append(events[TxHashKey], fmt.Sprintf("%X", data.Tx.Hash()))
   170  	events[TxHeightKey] = append(events[TxHeightKey], fmt.Sprintf("%d", data.Height))
   171  
   172  	return b.pubsub.PublishWithEvents(ctx, data, events)
   173  }
   174  
   175  func (b *EventBus) PublishEventNewRoundStep(data EventDataRoundState) error {
   176  	return b.Publish(EventNewRoundStep, data)
   177  }
   178  
   179  func (b *EventBus) PublishEventTimeoutPropose(data EventDataRoundState) error {
   180  	return b.Publish(EventTimeoutPropose, data)
   181  }
   182  
   183  func (b *EventBus) PublishEventTimeoutWait(data EventDataRoundState) error {
   184  	return b.Publish(EventTimeoutWait, data)
   185  }
   186  
   187  func (b *EventBus) PublishEventNewRound(data EventDataNewRound) error {
   188  	return b.Publish(EventNewRound, data)
   189  }
   190  
   191  func (b *EventBus) PublishEventCompleteProposal(data EventDataCompleteProposal) error {
   192  	return b.Publish(EventCompleteProposal, data)
   193  }
   194  
   195  func (b *EventBus) PublishEventPolka(data EventDataRoundState) error {
   196  	return b.Publish(EventPolka, data)
   197  }
   198  
   199  func (b *EventBus) PublishEventUnlock(data EventDataRoundState) error {
   200  	return b.Publish(EventUnlock, data)
   201  }
   202  
   203  func (b *EventBus) PublishEventRelock(data EventDataRoundState) error {
   204  	return b.Publish(EventRelock, data)
   205  }
   206  
   207  func (b *EventBus) PublishEventLock(data EventDataRoundState) error {
   208  	return b.Publish(EventLock, data)
   209  }
   210  
   211  func (b *EventBus) PublishEventValidatorSetUpdates(data EventDataValidatorSetUpdates) error {
   212  	return b.Publish(EventValidatorSetUpdates, data)
   213  }
   214  
   215  //-----------------------------------------------------------------------------
   216  type NopEventBus struct{}
   217  
   218  func (NopEventBus) Subscribe(ctx context.Context, subscriber string, query tmpubsub.Query, out chan<- interface{}) error {
   219  	return nil
   220  }
   221  
   222  func (NopEventBus) Unsubscribe(ctx context.Context, subscriber string, query tmpubsub.Query) error {
   223  	return nil
   224  }
   225  
   226  func (NopEventBus) UnsubscribeAll(ctx context.Context, subscriber string) error {
   227  	return nil
   228  }
   229  
   230  func (NopEventBus) PublishEventNewBlock(data EventDataNewBlock) error {
   231  	return nil
   232  }
   233  
   234  func (NopEventBus) PublishEventNewBlockHeader(data EventDataNewBlockHeader) error {
   235  	return nil
   236  }
   237  
   238  func (NopEventBus) PublishEventVote(data EventDataVote) error {
   239  	return nil
   240  }
   241  
   242  func (NopEventBus) PublishEventTx(data EventDataTx) error {
   243  	return nil
   244  }
   245  
   246  func (NopEventBus) PublishEventNewRoundStep(data EventDataRoundState) error {
   247  	return nil
   248  }
   249  
   250  func (NopEventBus) PublishEventTimeoutPropose(data EventDataRoundState) error {
   251  	return nil
   252  }
   253  
   254  func (NopEventBus) PublishEventTimeoutWait(data EventDataRoundState) error {
   255  	return nil
   256  }
   257  
   258  func (NopEventBus) PublishEventNewRound(data EventDataRoundState) error {
   259  	return nil
   260  }
   261  
   262  func (NopEventBus) PublishEventCompleteProposal(data EventDataRoundState) error {
   263  	return nil
   264  }
   265  
   266  func (NopEventBus) PublishEventPolka(data EventDataRoundState) error {
   267  	return nil
   268  }
   269  
   270  func (NopEventBus) PublishEventUnlock(data EventDataRoundState) error {
   271  	return nil
   272  }
   273  
   274  func (NopEventBus) PublishEventRelock(data EventDataRoundState) error {
   275  	return nil
   276  }
   277  
   278  func (NopEventBus) PublishEventLock(data EventDataRoundState) error {
   279  	return nil
   280  }
   281  
   282  func (NopEventBus) PublishEventValidatorSetUpdates(data EventDataValidatorSetUpdates) error {
   283  	return nil
   284  }