github.com/noirx94/tendermintmp@v0.0.1/state/txindex/indexer_service.go (about)

     1  package txindex
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/tendermint/tendermint/libs/service"
     7  	"github.com/tendermint/tendermint/state/indexer"
     8  	"github.com/tendermint/tendermint/types"
     9  )
    10  
    11  // XXX/TODO: These types should be moved to the indexer package.
    12  
    13  const (
    14  	subscriber = "IndexerService"
    15  )
    16  
    17  // IndexerService connects event bus, transaction and block indexers together in
    18  // order to index transactions and blocks coming from the event bus.
    19  type IndexerService struct {
    20  	service.BaseService
    21  
    22  	txIdxr    TxIndexer
    23  	blockIdxr indexer.BlockIndexer
    24  	eventBus  *types.EventBus
    25  }
    26  
    27  // NewIndexerService returns a new service instance.
    28  func NewIndexerService(
    29  	txIdxr TxIndexer,
    30  	blockIdxr indexer.BlockIndexer,
    31  	eventBus *types.EventBus,
    32  ) *IndexerService {
    33  
    34  	is := &IndexerService{txIdxr: txIdxr, blockIdxr: blockIdxr, eventBus: eventBus}
    35  	is.BaseService = *service.NewBaseService(nil, "IndexerService", is)
    36  	return is
    37  }
    38  
    39  // OnStart implements service.Service by subscribing for all transactions
    40  // and indexing them by events.
    41  func (is *IndexerService) OnStart() error {
    42  	// Use SubscribeUnbuffered here to ensure both subscriptions does not get
    43  	// cancelled due to not pulling messages fast enough. Cause this might
    44  	// sometimes happen when there are no other subscribers.
    45  	blockHeadersSub, err := is.eventBus.SubscribeUnbuffered(
    46  		context.Background(),
    47  		subscriber,
    48  		types.EventQueryNewBlockHeader)
    49  	if err != nil {
    50  		return err
    51  	}
    52  
    53  	txsSub, err := is.eventBus.SubscribeUnbuffered(context.Background(), subscriber, types.EventQueryTx)
    54  	if err != nil {
    55  		return err
    56  	}
    57  
    58  	go func() {
    59  		for {
    60  			msg := <-blockHeadersSub.Out()
    61  			eventDataHeader := msg.Data().(types.EventDataNewBlockHeader)
    62  			height := eventDataHeader.Header.Height
    63  			batch := NewBatch(eventDataHeader.NumTxs)
    64  
    65  			for i := int64(0); i < eventDataHeader.NumTxs; i++ {
    66  				msg2 := <-txsSub.Out()
    67  				txResult := msg2.Data().(types.EventDataTx).TxResult
    68  
    69  				if err = batch.Add(&txResult); err != nil {
    70  					is.Logger.Error(
    71  						"failed to add tx to batch",
    72  						"height", height,
    73  						"index", txResult.Index,
    74  						"err", err,
    75  					)
    76  				}
    77  			}
    78  
    79  			if err := is.blockIdxr.Index(eventDataHeader); err != nil {
    80  				is.Logger.Error("failed to index block", "height", height, "err", err)
    81  			} else {
    82  				is.Logger.Info("indexed block", "height", height)
    83  			}
    84  
    85  			if err = is.txIdxr.AddBatch(batch); err != nil {
    86  				is.Logger.Error("failed to index block txs", "height", height, "err", err)
    87  			} else {
    88  				is.Logger.Debug("indexed block txs", "height", height, "num_txs", eventDataHeader.NumTxs)
    89  			}
    90  		}
    91  	}()
    92  	return nil
    93  }
    94  
    95  // OnStop implements service.Service by unsubscribing from all transactions.
    96  func (is *IndexerService) OnStop() {
    97  	if is.eventBus.IsRunning() {
    98  		_ = is.eventBus.UnsubscribeAll(context.Background(), subscriber)
    99  	}
   100  }