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  }