@@ -21,11 +21,11 @@ const (
2121 dAFetcherRetries = 10
2222)
2323
24- // daRetriever encapsulates DA retrieval with pending events management
24+ // daRetriever encapsulates DA retrieval with pending events management.
25+ // Pending events are persisted via Manager.pendingEventsCache to avoid data loss on retries or restarts.
2526type daRetriever struct {
26- manager * Manager
27- mutex sync.RWMutex // mutex for pendingEvents
28- pendingEvents map [uint64 ]pendingDAEvent
27+ manager * Manager
28+ mutex sync.RWMutex // mutex for pendingEvents
2929}
3030
3131// pendingDAEvent represents a DA event waiting for processing
@@ -38,8 +38,7 @@ type pendingDAEvent struct {
3838// newDARetriever creates a new DA retriever
3939func newDARetriever (manager * Manager ) * daRetriever {
4040 return & daRetriever {
41- manager : manager ,
42- pendingEvents : make (map [uint64 ]pendingDAEvent ),
41+ manager : manager ,
4342 }
4443}
4544
@@ -51,6 +50,9 @@ func (m *Manager) DARetrieveLoop(ctx context.Context) {
5150
5251// run executes the main DA retrieval loop
5352func (dr * daRetriever ) run (ctx context.Context ) {
53+ // attempt to process any pending events loaded from disk before starting retrieval loop.
54+ dr .processPendingEvents (ctx )
55+
5456 // blobsFoundCh is used to track when we successfully found a header so
5557 // that we can continue to try and find headers that are in the next DA height.
5658 // This enables syncing faster than the DA block time.
@@ -292,17 +294,23 @@ func (dr *daRetriever) sendHeightEventIfValid(ctx context.Context, header *types
292294 dr .processEvent (ctx , header , data , daHeight )
293295}
294296
295- // queuePendingEvent queues a DA event that cannot be processed immediately
297+ // queuePendingEvent queues a DA event that cannot be processed immediately.
298+ // The event is persisted via pendingEventsCache to survive restarts.
296299func (dr * daRetriever ) queuePendingEvent (header * types.SignedHeader , data * types.Data , daHeight uint64 ) {
297300 dr .mutex .Lock ()
298301 defer dr .mutex .Unlock ()
299302
303+ if dr .manager .pendingEventsCache == nil {
304+ return
305+ }
306+
300307 height := header .Height ()
301- dr . pendingEvents [ height ] = pendingDAEvent {
308+ event : = pendingDAEvent {
302309 header : header ,
303310 data : data ,
304311 daHeight : daHeight ,
305312 }
313+ dr .manager .pendingEventsCache .SetItem (height , & event )
306314
307315 dr .manager .logger .Debug ().
308316 Uint64 ("height" , height ).
@@ -341,10 +349,12 @@ func (dr *daRetriever) processEvent(ctx context.Context, header *types.SignedHea
341349 Uint64 ("daHeight" , daHeight ).
342350 Msg ("sent complete height event with header and data" )
343351 default :
352+ // Channel full: keep event in pending cache for retry
353+ dr .queuePendingEvent (header , data , daHeight )
344354 dr .manager .logger .Warn ().
345355 Uint64 ("height" , header .Height ()).
346356 Uint64 ("daHeight" , daHeight ).
347- Msg ("heightInCh backlog full, dropping complete event" )
357+ Msg ("heightInCh backlog full, re-queued event to pending cache " )
348358 }
349359
350360 // Try to process any pending events that might now be ready
@@ -353,6 +363,10 @@ func (dr *daRetriever) processEvent(ctx context.Context, header *types.SignedHea
353363
354364// processPendingEvents tries to process queued DA events that might now be ready
355365func (dr * daRetriever ) processPendingEvents (ctx context.Context ) {
366+ if dr .manager .pendingEventsCache == nil {
367+ return
368+ }
369+
356370 currentHeight , err := dr .manager .GetStoreHeight (ctx )
357371 if err != nil {
358372 dr .manager .logger .Debug ().Err (err ).Msg ("failed to get store height for pending DA events" )
@@ -362,15 +376,21 @@ func (dr *daRetriever) processPendingEvents(ctx context.Context) {
362376 dr .mutex .Lock ()
363377 defer dr .mutex .Unlock ()
364378
365- for height , event := range dr .pendingEvents {
379+ toDelete := make ([]uint64 , 0 )
380+ dr .manager .pendingEventsCache .RangeByHeight (func (height uint64 , event * pendingDAEvent ) bool {
366381 if height <= currentHeight + 1 {
367382 dr .manager .logger .Debug ().
368383 Uint64 ("height" , height ).
369384 Uint64 ("daHeight" , event .daHeight ).
370385 Msg ("processing previously queued DA event" )
371386 go dr .processEvent (ctx , event .header , event .data , event .daHeight )
372- delete ( dr . pendingEvents , height )
387+ toDelete = append ( toDelete , height )
373388 }
389+ return true
390+ })
391+
392+ for _ , h := range toDelete {
393+ dr .manager .pendingEventsCache .DeleteItem (h )
374394 }
375395}
376396
0 commit comments