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  }