github.com/KYVENetwork/cometbft/v38@v38.0.3/state/txindex/indexer_service.go (about) 1 package txindex 2 3 import ( 4 "context" 5 6 "github.com/KYVENetwork/cometbft/v38/libs/service" 7 "github.com/KYVENetwork/cometbft/v38/state/indexer" 8 "github.com/KYVENetwork/cometbft/v38/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 terminateOnError bool 26 } 27 28 // NewIndexerService returns a new service instance. 29 func NewIndexerService( 30 txIdxr TxIndexer, 31 blockIdxr indexer.BlockIndexer, 32 eventBus *types.EventBus, 33 terminateOnError bool, 34 ) *IndexerService { 35 36 is := &IndexerService{txIdxr: txIdxr, blockIdxr: blockIdxr, eventBus: eventBus, terminateOnError: terminateOnError} 37 is.BaseService = *service.NewBaseService(nil, "IndexerService", is) 38 return is 39 } 40 41 // OnStart implements service.Service by subscribing for all transactions 42 // and indexing them by events. 43 func (is *IndexerService) OnStart() error { 44 // Use SubscribeUnbuffered here to ensure both subscriptions does not get 45 // canceled due to not pulling messages fast enough. Cause this might 46 // sometimes happen when there are no other subscribers. 47 blockSub, err := is.eventBus.SubscribeUnbuffered( 48 context.Background(), 49 subscriber, 50 types.EventQueryNewBlockEvents) 51 if err != nil { 52 return err 53 } 54 55 txsSub, err := is.eventBus.SubscribeUnbuffered(context.Background(), subscriber, types.EventQueryTx) 56 if err != nil { 57 return err 58 } 59 60 go func() { 61 for { 62 select { 63 case <-blockSub.Canceled(): 64 return 65 case msg := <-blockSub.Out(): 66 eventNewBlockEvents := msg.Data().(types.EventDataNewBlockEvents) 67 height := eventNewBlockEvents.Height 68 numTxs := eventNewBlockEvents.NumTxs 69 70 batch := NewBatch(numTxs) 71 72 for i := int64(0); i < numTxs; i++ { 73 msg2 := <-txsSub.Out() 74 txResult := msg2.Data().(types.EventDataTx).TxResult 75 76 if err = batch.Add(&txResult); err != nil { 77 is.Logger.Error( 78 "failed to add tx to batch", 79 "height", height, 80 "index", txResult.Index, 81 "err", err, 82 ) 83 84 if is.terminateOnError { 85 if err := is.Stop(); err != nil { 86 is.Logger.Error("failed to stop", "err", err) 87 } 88 return 89 } 90 } 91 } 92 93 if err := is.blockIdxr.Index(eventNewBlockEvents); err != nil { 94 is.Logger.Error("failed to index block", "height", height, "err", err) 95 if is.terminateOnError { 96 if err := is.Stop(); err != nil { 97 is.Logger.Error("failed to stop", "err", err) 98 } 99 return 100 } 101 } else { 102 is.Logger.Info("indexed block events", "height", height) 103 } 104 105 if err = is.txIdxr.AddBatch(batch); err != nil { 106 is.Logger.Error("failed to index block txs", "height", height, "err", err) 107 if is.terminateOnError { 108 if err := is.Stop(); err != nil { 109 is.Logger.Error("failed to stop", "err", err) 110 } 111 return 112 } 113 } else { 114 is.Logger.Debug("indexed transactions", "height", height, "num_txs", numTxs) 115 } 116 } 117 } 118 }() 119 return nil 120 } 121 122 // OnStop implements service.Service by unsubscribing from all transactions. 123 func (is *IndexerService) OnStop() { 124 if is.eventBus.IsRunning() { 125 _ = is.eventBus.UnsubscribeAll(context.Background(), subscriber) 126 } 127 }