@@ -163,13 +163,23 @@ func GetEntryBundle(ctx context.Context, f EntryBundleFetcherFunc, i, logSize ui
163
163
span .SetAttributes (indexKey .Int64 (otel .Clamp64 (i )), logSizeKey .Int64 (otel .Clamp64 (logSize )))
164
164
165
165
bundle := api.EntryBundle {}
166
- sRaw , err := f (ctx , i , layout .PartialTileSize (0 , i , logSize ))
167
- if err != nil {
168
- if errors .Is (err , os .ErrNotExist ) {
169
- return bundle , fmt .Errorf ("leaf bundle at index %d not found: %v" , i , err )
166
+ p := layout .PartialTileSize (0 , i , logSize )
167
+ sRaw , err := f (ctx , i , p )
168
+ switch {
169
+ case errors .Is (err , os .ErrNotExist ) && p == 0 :
170
+ return bundle , fmt .Errorf ("full leaf bundle at index %d not found: %v" , i , err )
171
+ case errors .Is (err , os .ErrNotExist ) && p > 0 :
172
+ // It could be that the partial bundle was removed as the tree has grown and a full bundle is now present, so try
173
+ // falling back to that.
174
+ sRaw , err = f (ctx , i , 0 )
175
+ if err != nil {
176
+ return bundle , fmt .Errorf ("partial bundle at %[1]d.p/%[2]d and full bundle at %[1]d both not found: %[3]w" , i , p , err )
170
177
}
178
+ case err != nil :
171
179
return bundle , fmt .Errorf ("failed to fetch leaf bundle at index %d: %v" , i , err )
180
+ default :
172
181
}
182
+
173
183
if err := bundle .UnmarshalText (sRaw ); err != nil {
174
184
return bundle , fmt .Errorf ("failed to parse EntryBundle at index %d: %v" , i , err )
175
185
}
@@ -403,7 +413,8 @@ func (n *nodeCache) GetNode(ctx context.Context, id compact.NodeID) ([]byte, err
403
413
t , ok := n .tiles [tKey ]
404
414
if ! ok {
405
415
span .AddEvent ("cache miss" )
406
- tileRaw , err := n .getTile (ctx , tileLevel , tileIndex , layout .PartialTileSize (tileLevel , tileIndex , n .logSize ))
416
+ p := layout .PartialTileSize (tileLevel , tileIndex , n .logSize )
417
+ tileRaw , err := fetchPartialOrFullTile (ctx , n .getTile , tileLevel , tileIndex , p )
407
418
if err != nil {
408
419
return nil , fmt .Errorf ("failed to fetch tile: %v" , err )
409
420
}
@@ -430,3 +441,26 @@ func (n *nodeCache) GetNode(ctx context.Context, id compact.NodeID) ([]byte, err
430
441
}
431
442
return r .GetRootHash (nil )
432
443
}
444
+
445
+ // fetchPartialOrFullTile attempts to fetch the tile at the provided coordinates.
446
+ // If no tile is found, and the coordinates refer to a partial tile, fallback to trying the corresponding
447
+ // full tile.
448
+ func fetchPartialOrFullTile (ctx context.Context , f TileFetcherFunc , l , i uint64 , p uint8 ) ([]byte , error ) {
449
+ sRaw , err := f (ctx , l , i , p )
450
+ switch {
451
+ case errors .Is (err , os .ErrNotExist ) && p == 0 :
452
+ return sRaw , fmt .Errorf ("full tile at index %d not found: %w" , i , err )
453
+ case errors .Is (err , os .ErrNotExist ) && p > 0 :
454
+ // It could be that the partial tile was removed as the tree has grown and a full tile is now present, so try
455
+ // falling back to that.
456
+ sRaw , err = f (ctx , l , i , 0 )
457
+ if err != nil {
458
+ return sRaw , fmt .Errorf ("partial tile at %[1]d/%[2]d.p/%[3]d and full bundle at %[1]d/%[2]d both not found: %[4]w" , l , i , p , err )
459
+ }
460
+ return sRaw , nil
461
+ case err != nil :
462
+ return sRaw , fmt .Errorf ("failed to fetch tile at %d/%d(.p/%d]): %v" , l , i , p , err )
463
+ default :
464
+ return sRaw , nil
465
+ }
466
+ }
0 commit comments