github.com/evdatsion/aphelion-dpos-bft@v0.32.1/state/txindex/indexer_service.go (about)

     1  package txindex
     2  
     3  import (
     4  	"context"
     5  
     6  	cmn "github.com/evdatsion/aphelion-dpos-bft/libs/common"
     7  
     8  	"github.com/evdatsion/aphelion-dpos-bft/types"
     9  )
    10  
    11  const (
    12  	subscriber = "IndexerService"
    13  )
    14  
    15  // IndexerService connects event bus and transaction indexer together in order
    16  // to index transactions coming from event bus.
    17  type IndexerService struct {
    18  	cmn.BaseService
    19  
    20  	idr      TxIndexer
    21  	eventBus *types.EventBus
    22  }
    23  
    24  // NewIndexerService returns a new service instance.
    25  func NewIndexerService(idr TxIndexer, eventBus *types.EventBus) *IndexerService {
    26  	is := &IndexerService{idr: idr, eventBus: eventBus}
    27  	is.BaseService = *cmn.NewBaseService(nil, "IndexerService", is)
    28  	return is
    29  }
    30  
    31  // OnStart implements cmn.Service by subscribing for all transactions
    32  // and indexing them by tags.
    33  func (is *IndexerService) OnStart() error {
    34  	// Use SubscribeUnbuffered here to ensure both subscriptions does not get
    35  	// cancelled due to not pulling messages fast enough. Cause this might
    36  	// sometimes happen when there are no other subscribers.
    37  
    38  	blockHeadersSub, err := is.eventBus.SubscribeUnbuffered(context.Background(), subscriber, types.EventQueryNewBlockHeader)
    39  	if err != nil {
    40  		return err
    41  	}
    42  
    43  	txsSub, err := is.eventBus.SubscribeUnbuffered(context.Background(), subscriber, types.EventQueryTx)
    44  	if err != nil {
    45  		return err
    46  	}
    47  
    48  	go func() {
    49  		for {
    50  			msg := <-blockHeadersSub.Out()
    51  			header := msg.Data().(types.EventDataNewBlockHeader).Header
    52  			batch := NewBatch(header.NumTxs)
    53  			for i := int64(0); i < header.NumTxs; i++ {
    54  				msg2 := <-txsSub.Out()
    55  				txResult := msg2.Data().(types.EventDataTx).TxResult
    56  				if err = batch.Add(&txResult); err != nil {
    57  					is.Logger.Error("Can't add tx to batch",
    58  						"height", header.Height,
    59  						"index", txResult.Index,
    60  						"err", err)
    61  				}
    62  			}
    63  			if err = is.idr.AddBatch(batch); err != nil {
    64  				is.Logger.Error("Failed to index block", "height", header.Height, "err", err)
    65  			} else {
    66  				is.Logger.Info("Indexed block", "height", header.Height)
    67  			}
    68  		}
    69  	}()
    70  	return nil
    71  }
    72  
    73  // OnStop implements cmn.Service by unsubscribing from all transactions.
    74  func (is *IndexerService) OnStop() {
    75  	if is.eventBus.IsRunning() {
    76  		_ = is.eventBus.UnsubscribeAll(context.Background(), subscriber)
    77  	}
    78  }