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