github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/bft/state/eventstore/store_service.go (about)

     1  package eventstore
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/gnolang/gno/tm2/pkg/bft/types"
     8  	"github.com/gnolang/gno/tm2/pkg/events"
     9  	"github.com/gnolang/gno/tm2/pkg/service"
    10  )
    11  
    12  // Service connects the event bus and event store together in order
    13  // to store events coming from event bus
    14  type Service struct {
    15  	service.BaseService
    16  
    17  	cancelFn context.CancelFunc
    18  
    19  	txEventStore TxEventStore
    20  	evsw         events.EventSwitch
    21  }
    22  
    23  // NewEventStoreService returns a new service instance
    24  func NewEventStoreService(idr TxEventStore, evsw events.EventSwitch) *Service {
    25  	is := &Service{txEventStore: idr, evsw: evsw}
    26  	is.BaseService = *service.NewBaseService(nil, "EventStoreService", is)
    27  
    28  	return is
    29  }
    30  
    31  func (is *Service) OnStart() error {
    32  	// Create a context for the intermediary monitor service
    33  	ctx, cancelFn := context.WithCancel(context.Background())
    34  	is.cancelFn = cancelFn
    35  
    36  	// Start the event store
    37  	if err := is.txEventStore.Start(); err != nil {
    38  		return fmt.Errorf("unable to start transaction event store, %w", err)
    39  	}
    40  
    41  	// Start the intermediary monitor service
    42  	go is.monitorTxEvents(ctx)
    43  
    44  	return nil
    45  }
    46  
    47  func (is *Service) OnStop() {
    48  	// Close off any routines
    49  	is.cancelFn()
    50  
    51  	// Attempt to gracefully stop the event store
    52  	if err := is.txEventStore.Stop(); err != nil {
    53  		is.Logger.Error(
    54  			fmt.Sprintf("unable to gracefully stop event store, %v", err),
    55  		)
    56  	}
    57  }
    58  
    59  // monitorTxEvents acts as an intermediary feed service for the supplied
    60  // event store. It relays transaction events that come from the event stream
    61  func (is *Service) monitorTxEvents(ctx context.Context) {
    62  	// Create a subscription for transaction events
    63  	subCh := events.SubscribeToEvent(is.evsw, "tx-event-store", types.EventTx{})
    64  
    65  	for {
    66  		select {
    67  		case <-ctx.Done():
    68  			return
    69  		case evRaw := <-subCh:
    70  			// Cast the event
    71  			ev, ok := evRaw.(types.EventTx)
    72  			if !ok {
    73  				is.Logger.Error("invalid transaction result type cast")
    74  
    75  				continue
    76  			}
    77  
    78  			// Alert the actual tx event store
    79  			if err := is.txEventStore.Append(ev.Result); err != nil {
    80  				is.Logger.Error("unable to store transaction", "err", err)
    81  			}
    82  		}
    83  	}
    84  }