55 "fmt"
66 "math/big"
77 "sort"
8+ "sync"
89 "time"
910
1011 "github.com/rs/zerolog/log"
@@ -83,11 +84,33 @@ func (c *Committer) Start(ctx context.Context) {
8384 // Clean up staging data before starting the committer
8485 c .cleanupStagingData ()
8586
87+ if config .Cfg .Publisher .Mode == "parallel" {
88+ var wg sync.WaitGroup
89+ wg .Add (2 )
90+ go func () {
91+ defer wg .Done ()
92+ c .runCommitLoop (ctx , interval )
93+ }()
94+ go func () {
95+ defer wg .Done ()
96+ c .runPublishLoop (ctx , interval )
97+ }()
98+ <- ctx .Done ()
99+ wg .Wait ()
100+ log .Info ().Msg ("Committer shutting down" )
101+ c .publisher .Close ()
102+ return
103+ }
104+
105+ c .runCommitLoop (ctx , interval )
106+ log .Info ().Msg ("Committer shutting down" )
107+ c .publisher .Close ()
108+ }
109+
110+ func (c * Committer ) runCommitLoop (ctx context.Context , interval time.Duration ) {
86111 for {
87112 select {
88113 case <- ctx .Done ():
89- log .Info ().Msg ("Committer shutting down" )
90- c .publisher .Close ()
91114 return
92115 case workMode := <- c .workModeChan :
93116 if workMode != c .workMode && workMode != "" {
@@ -116,6 +139,24 @@ func (c *Committer) Start(ctx context.Context) {
116139 }
117140}
118141
142+ func (c * Committer ) runPublishLoop (ctx context.Context , interval time.Duration ) {
143+ for {
144+ select {
145+ case <- ctx .Done ():
146+ return
147+ default :
148+ time .Sleep (interval )
149+ if c .workMode == "" {
150+ log .Debug ().Msg ("Committer work mode not set, skipping publish" )
151+ continue
152+ }
153+ if err := c .publish (ctx ); err != nil {
154+ log .Error ().Err (err ).Msg ("Error publishing blocks" )
155+ }
156+ }
157+ }
158+ }
159+
119160func (c * Committer ) cleanupStagingData () {
120161 // Get the last committed block number from main storage
121162 latestCommittedBlockNumber , err := c .storage .MainStorage .GetMaxBlockNumber (c .rpc .GetChainID ())
@@ -293,6 +334,78 @@ func (c *Committer) getSequentialBlockDataToCommit(ctx context.Context) ([]commo
293334 return sequentialBlockData , nil
294335}
295336
337+ func (c * Committer ) getSequentialBlockDataToPublish (ctx context.Context ) ([]common.BlockData , error ) {
338+ chainID := c .rpc .GetChainID ()
339+ lastPublished , err := c .storage .StagingStorage .GetLastPublishedBlockNumber (chainID )
340+ if err != nil {
341+ return nil , fmt .Errorf ("failed to get last published block number: %v" , err )
342+ }
343+
344+ startBlock := new (big.Int ).Set (c .commitFromBlock )
345+ if lastPublished != nil && lastPublished .Sign () > 0 {
346+ startBlock = new (big.Int ).Add (lastPublished , big .NewInt (1 ))
347+ }
348+
349+ endBlock := new (big.Int ).Add (startBlock , big .NewInt (int64 (c .blocksPerCommit - 1 )))
350+ blockCount := new (big.Int ).Sub (endBlock , startBlock ).Int64 () + 1
351+ blockNumbers := make ([]* big.Int , blockCount )
352+ for i := int64 (0 ); i < blockCount ; i ++ {
353+ blockNumbers [i ] = new (big.Int ).Add (startBlock , big .NewInt (i ))
354+ }
355+
356+ blocksData , err := c .storage .StagingStorage .GetStagingData (storage.QueryFilter {ChainId : chainID , BlockNumbers : blockNumbers })
357+ if err != nil {
358+ return nil , fmt .Errorf ("error fetching blocks to publish: %v" , err )
359+ }
360+ if len (blocksData ) == 0 {
361+ return nil , nil
362+ }
363+
364+ sort .Slice (blocksData , func (i , j int ) bool {
365+ return blocksData [i ].Block .Number .Cmp (blocksData [j ].Block .Number ) < 0
366+ })
367+ if blocksData [0 ].Block .Number .Cmp (startBlock ) != 0 {
368+ log .Debug ().Msgf ("First block to publish %s does not match expected %s" , blocksData [0 ].Block .Number .String (), startBlock .String ())
369+ return nil , nil
370+ }
371+
372+ sequential := []common.BlockData {blocksData [0 ]}
373+ expected := new (big.Int ).Add (blocksData [0 ].Block .Number , big .NewInt (1 ))
374+ for i := 1 ; i < len (blocksData ); i ++ {
375+ if blocksData [i ].Block .Number .Cmp (blocksData [i - 1 ].Block .Number ) == 0 {
376+ continue
377+ }
378+ if blocksData [i ].Block .Number .Cmp (expected ) != 0 {
379+ break
380+ }
381+ sequential = append (sequential , blocksData [i ])
382+ expected .Add (expected , big .NewInt (1 ))
383+ }
384+
385+ return sequential , nil
386+ }
387+
388+ func (c * Committer ) publish (ctx context.Context ) error {
389+ blockData , err := c .getSequentialBlockDataToPublish (ctx )
390+ if err != nil {
391+ return err
392+ }
393+ if len (blockData ) == 0 {
394+ return nil
395+ }
396+
397+ if err := c .publisher .PublishBlockData (blockData ); err != nil {
398+ return err
399+ }
400+
401+ chainID := c .rpc .GetChainID ()
402+ highest := blockData [len (blockData )- 1 ].Block .Number
403+ if err := c .storage .StagingStorage .SetLastPublishedBlockNumber (chainID , highest ); err != nil {
404+ return err
405+ }
406+ return nil
407+ }
408+
296409func (c * Committer ) commit (ctx context.Context , blockData []common.BlockData ) error {
297410 blockNumbers := make ([]* big.Int , len (blockData ))
298411 highestBlock := blockData [0 ].Block
@@ -303,31 +416,6 @@ func (c *Committer) commit(ctx context.Context, blockData []common.BlockData) er
303416 }
304417 }
305418 log .Debug ().Msgf ("Committing %d blocks" , len (blockNumbers ))
306-
307- shouldPostCommitPublish := true
308-
309- if config .Cfg .Publisher .Mode == "pre-commit" {
310- chainID := c .rpc .GetChainID ()
311- lastPublished , err := c .storage .StagingStorage .GetLastPublishedBlockNumber (chainID )
312- if err != nil {
313- log .Error ().Err (err ).Msg ("Failed to get last published block number, falling back to post-commit" )
314- } else if lastPublished == nil || lastPublished .Cmp (highestBlock .Number ) < 0 {
315- go func () {
316- if err := c .publisher .PublishBlockData (blockData ); err != nil {
317- log .Error ().Err (err ).Msg ("Failed to publish block data to kafka" )
318- return
319- }
320- if err := c .storage .StagingStorage .SetLastPublishedBlockNumber (chainID , highestBlock .Number ); err != nil {
321- log .Error ().Err (err ).Msg ("Failed to set last published block number" )
322- }
323- }()
324- shouldPostCommitPublish = false
325- } else {
326- log .Debug ().Msgf ("Skipping publish, latest published block %s >= current %s" , lastPublished .String (), highestBlock .Number .String ())
327- shouldPostCommitPublish = false
328- }
329- }
330-
331419 mainStorageStart := time .Now ()
332420 if err := c .storage .MainStorage .InsertBlockData (blockData ); err != nil {
333421 log .Error ().Err (err ).Msgf ("Failed to commit blocks: %v" , blockNumbers )
@@ -336,7 +424,7 @@ func (c *Committer) commit(ctx context.Context, blockData []common.BlockData) er
336424 log .Debug ().Str ("metric" , "main_storage_insert_duration" ).Msgf ("MainStorage.InsertBlockData duration: %f" , time .Since (mainStorageStart ).Seconds ())
337425 metrics .MainStorageInsertDuration .Observe (time .Since (mainStorageStart ).Seconds ())
338426
339- if shouldPostCommitPublish {
427+ if config . Cfg . Publisher . Mode == "default" {
340428 go func () {
341429 if err := c .publisher .PublishBlockData (blockData ); err != nil {
342430 log .Error ().Err (err ).Msg ("Failed to publish block data to kafka" )
0 commit comments