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 }