@@ -130,8 +130,8 @@ func (s *Store[H]) Start(ctx context.Context) error {
130
130
default :
131
131
}
132
132
133
- if err := s .loadHeadAndTail (ctx ); err != nil && ! errors . Is ( err , header . ErrNotFound ) {
134
- return err
133
+ if err := s .init (ctx ); err != nil {
134
+ return fmt . Errorf ( "header/store: initializing: %w" , err )
135
135
}
136
136
137
137
ctx , cancel := context .WithCancel (context .Background ())
@@ -560,10 +560,24 @@ func (s *Store[H]) readByKey(ctx context.Context, key datastore.Key) (H, error)
560
560
561
561
var h header.Hash
562
562
if err := h .UnmarshalJSON (b ); err != nil {
563
+ return zero , fmt .Errorf ("unmarshaling header hash at %s key: %w" , key , err )
564
+ }
565
+
566
+ hdr , err := s .Get (ctx , h )
567
+ if err != nil {
568
+ if errors .Is (err , header .ErrNotFound ) {
569
+ derr := s .ds .Delete (ctx , key )
570
+ if derr != nil {
571
+ err = errors .Join (
572
+ err ,
573
+ fmt .Errorf ("deleting key %s, header for which was not found: %w" , key , derr ),
574
+ )
575
+ }
576
+ }
563
577
return zero , err
564
578
}
565
579
566
- return s . Get ( ctx , h )
580
+ return hdr , nil
567
581
}
568
582
569
583
func (s * Store [H ]) get (ctx context.Context , hash header.Hash ) ([]byte , error ) {
@@ -677,39 +691,53 @@ func (s *Store[H]) nextTail(ctx context.Context) (tail H, changed bool) {
677
691
return tail , changed
678
692
}
679
693
680
- func (s * Store [H ]) loadHeadAndTail (ctx context.Context ) error {
694
+ // init loads the head and tail headers and sets them on the store.
695
+ // allows partial initialization of either tail or head if one of the is not found.
696
+ func (s * Store [H ]) init (ctx context.Context ) error {
681
697
head , err := s .readByKey (ctx , headKey )
682
- if err != nil {
683
- return fmt .Errorf ("header/store: cannot load headKey: %w" , err )
698
+ if err != nil && ! errors .Is (err , header .ErrNotFound ) {
699
+ return fmt .Errorf ("reading headKey: %w" , err )
700
+ }
701
+ if ! head .IsZero () {
702
+ s .contiguousHead .Store (& head )
703
+ s .heightSub .Init (head .Height ())
704
+ log .Debugw ("initialized head" , "height" , head .Height ())
684
705
}
685
706
686
707
tail , err := s .readByKey (ctx , tailKey )
687
- if err != nil {
688
- return fmt .Errorf ("header/store: cannot load tailKey: %w" , err )
708
+ if err != nil && ! errors .Is (err , header .ErrNotFound ) {
709
+ return fmt .Errorf ("reading tailKey: %w" , err )
710
+ }
711
+ if ! tail .IsZero () {
712
+ s .tailHeader .Store (& tail )
713
+ log .Debugw ("initialized tail" , "height" , tail .Height ())
689
714
}
690
715
691
- s .init (head , tail )
692
716
return nil
693
717
}
694
718
719
+ // ensureInit initializes the store with the given headers if it is not already initialized.
695
720
func (s * Store [H ]) ensureInit (headers []H ) {
696
- headExist , tailExist := s .contiguousHead .Load () != nil , s .tailHeader .Load () != nil
697
- if len (headers ) == 0 || (tailExist && headExist ) {
721
+ if len (headers ) == 0 {
698
722
return
699
- } else if tailExist || headExist {
700
- panic ("header/store: head and tail must be both present or absent" )
701
723
}
702
724
703
- tail , head := headers [0 ], headers [len (headers )- 1 ]
704
- s .init (head , tail )
705
- }
725
+ if headPtr := s .contiguousHead .Load (); headPtr == nil {
726
+ head := headers [len (headers )- 1 ]
727
+ if s .contiguousHead .CompareAndSwap (headPtr , & head ) {
728
+ s .heightSub .Init (head .Height ())
729
+ log .Debugw ("initialized head" , "height" , head .Height ())
730
+ }
731
+ }
706
732
707
- func (s * Store [H ]) init (head , tail H ) {
708
- s .contiguousHead .Store (& head )
709
- s .heightSub .Init (head .Height ())
710
- s .tailHeader .Store (& tail )
733
+ if tailPtr := s .tailHeader .Load (); tailPtr == nil {
734
+ tail := headers [0 ]
735
+ s .tailHeader .CompareAndSwap (tailPtr , & tail )
736
+ log .Debugw ("initialized tail" , "height" , tail .Height ())
737
+ }
711
738
}
712
739
740
+ // deinit deinitializes the store.
713
741
func (s * Store [H ]) deinit () {
714
742
s .cache .Purge ()
715
743
s .heightIndex .cache .Purge ()
0 commit comments