github.com/arcology-network/consensus-engine@v1.9.0/state/txindex/indexer_service.go (about) 1 package txindex 2 3 import ( 4 "context" 5 6 "github.com/arcology-network/consensus-engine/libs/service" 7 8 "github.com/arcology-network/consensus-engine/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 service.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 = *service.NewBaseService(nil, "IndexerService", is) 28 return is 29 } 30 31 // OnStart implements service.Service by subscribing for all transactions 32 // and indexing them by events. 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( 39 context.Background(), 40 subscriber, 41 types.EventQueryNewBlockHeader) 42 if err != nil { 43 return err 44 } 45 46 txsSub, err := is.eventBus.SubscribeUnbuffered(context.Background(), subscriber, types.EventQueryTx) 47 if err != nil { 48 return err 49 } 50 51 go func() { 52 for { 53 msg := <-blockHeadersSub.Out() 54 eventDataHeader := msg.Data().(types.EventDataNewBlockHeader) 55 height := eventDataHeader.Header.Height 56 batch := NewBatch(eventDataHeader.NumTxs) 57 for i := int64(0); i < eventDataHeader.NumTxs; i++ { 58 msg2 := <-txsSub.Out() 59 txResult := msg2.Data().(types.EventDataTx).TxResult 60 if err = batch.Add(&txResult); err != nil { 61 is.Logger.Error("Can't add tx to batch", 62 "height", height, 63 "index", txResult.Index, 64 "err", err) 65 } 66 } 67 if err = is.idr.AddBatch(batch); err != nil { 68 is.Logger.Error("Failed to index block", "height", height, "err", err) 69 } else { 70 is.Logger.Info("Indexed block", "height", height) 71 } 72 } 73 }() 74 return nil 75 } 76 77 // OnStop implements service.Service by unsubscribing from all transactions. 78 func (is *IndexerService) OnStop() { 79 if is.eventBus.IsRunning() { 80 _ = is.eventBus.UnsubscribeAll(context.Background(), subscriber) 81 } 82 }