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