Skip to content

Commit 9117e90

Browse files
authored
Merge pull request #5632 from AndriiDiachuk/cleanup-streaming-errors-for-block-not-ready
Cleanup streaming errors for block not ready
2 parents a762ee0 + f0adcfd commit 9117e90

File tree

5 files changed

+41
-16
lines changed

5 files changed

+41
-16
lines changed

engine/access/rpc/backend/backend_stream_blocks.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package backend
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67

78
"github.com/rs/zerolog"
@@ -283,7 +284,7 @@ func (b *backendSubscribeBlocks) getBlockDigestResponse(blockStatus flow.BlockSt
283284

284285
// getBlockHeader returns the block header for the given block height.
285286
// Expected errors during normal operation:
286-
// - storage.ErrNotFound: block for the given block height is not available.
287+
// - subscription.ErrBlockNotReady: block for the given block height is not available.
287288
func (b *backendSubscribeBlocks) getBlockHeader(height uint64, expectedBlockStatus flow.BlockStatus) (*flow.Header, error) {
288289
err := b.validateHeight(height, expectedBlockStatus)
289290
if err != nil {
@@ -293,6 +294,9 @@ func (b *backendSubscribeBlocks) getBlockHeader(height uint64, expectedBlockStat
293294
// since we are querying a finalized or sealed block header, we can use the height index and save an ID computation
294295
header, err := b.headers.ByHeight(height)
295296
if err != nil {
297+
if errors.Is(err, storage.ErrNotFound) {
298+
return nil, fmt.Errorf("failed to retrieve block header for height %d: %w", height, subscription.ErrBlockNotReady)
299+
}
296300
return nil, err
297301
}
298302

@@ -301,7 +305,7 @@ func (b *backendSubscribeBlocks) getBlockHeader(height uint64, expectedBlockStat
301305

302306
// getBlock returns the block for the given block height.
303307
// Expected errors during normal operation:
304-
// - storage.ErrNotFound: block for the given block height is not available.
308+
// - subscription.ErrBlockNotReady: block for the given block height is not available.
305309
func (b *backendSubscribeBlocks) getBlock(height uint64, expectedBlockStatus flow.BlockStatus) (*flow.Block, error) {
306310
err := b.validateHeight(height, expectedBlockStatus)
307311
if err != nil {
@@ -311,6 +315,9 @@ func (b *backendSubscribeBlocks) getBlock(height uint64, expectedBlockStatus flo
311315
// since we are querying a finalized or sealed block, we can use the height index and save an ID computation
312316
block, err := b.blocks.ByHeight(height)
313317
if err != nil {
318+
if errors.Is(err, storage.ErrNotFound) {
319+
return nil, fmt.Errorf("failed to retrieve block for height %d: %w", height, subscription.ErrBlockNotReady)
320+
}
314321
return nil, err
315322
}
316323

@@ -319,7 +326,7 @@ func (b *backendSubscribeBlocks) getBlock(height uint64, expectedBlockStatus flo
319326

320327
// validateHeight checks if the given block height is valid and available based on the expected block status.
321328
// Expected errors during normal operation:
322-
// - storage.ErrNotFound: block for the given block height is not available.
329+
// - subscription.ErrBlockNotReady when unable to retrieve the block by height.
323330
func (b *backendSubscribeBlocks) validateHeight(height uint64, expectedBlockStatus flow.BlockStatus) error {
324331
highestHeight, err := b.blockTracker.GetHighestHeight(expectedBlockStatus)
325332
if err != nil {
@@ -330,7 +337,7 @@ func (b *backendSubscribeBlocks) validateHeight(height uint64, expectedBlockStat
330337
// note: it's possible for the data to exist in the data store before the notification is
331338
// received. this ensures a consistent view is available to all streams.
332339
if height > highestHeight {
333-
return fmt.Errorf("block %d is not available yet: %w", height, storage.ErrNotFound)
340+
return fmt.Errorf("block %d is not available yet: %w", height, subscription.ErrBlockNotReady)
334341
}
335342

336343
return nil

engine/access/state_stream/backend/backend.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package backend
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"time"
78

@@ -12,7 +13,6 @@ import (
1213
"github.com/onflow/flow-go/engine/access/index"
1314
"github.com/onflow/flow-go/engine/access/state_stream"
1415
"github.com/onflow/flow-go/engine/access/subscription"
15-
"github.com/onflow/flow-go/fvm/errors"
1616
"github.com/onflow/flow-go/model/flow"
1717
"github.com/onflow/flow-go/module/execution"
1818
"github.com/onflow/flow-go/module/executiondatasync/execution_data"
@@ -144,18 +144,23 @@ func New(
144144

145145
// getExecutionData returns the execution data for the given block height.
146146
// Expected errors during normal operation:
147-
// - storage.ErrNotFound or execution_data.BlobNotFoundError: execution data for the given block height is not available.
147+
// - subscription.ErrBlockNotReady: execution data for the given block height is not available.
148148
func (b *StateStreamBackend) getExecutionData(ctx context.Context, height uint64) (*execution_data.BlockExecutionDataEntity, error) {
149149
highestHeight := b.ExecutionDataTracker.GetHighestHeight()
150150
// fail early if no notification has been received for the given block height.
151151
// note: it's possible for the data to exist in the data store before the notification is
152152
// received. this ensures a consistent view is available to all streams.
153153
if height > highestHeight {
154-
return nil, fmt.Errorf("execution data for block %d is not available yet: %w", height, storage.ErrNotFound)
154+
return nil, fmt.Errorf("execution data for block %d is not available yet: %w", height, subscription.ErrBlockNotReady)
155155
}
156156

157157
execData, err := b.execDataCache.ByHeight(ctx, height)
158158
if err != nil {
159+
if errors.Is(err, storage.ErrNotFound) ||
160+
execution_data.IsBlobNotFoundError(err) {
161+
err = errors.Join(err, subscription.ErrBlockNotReady)
162+
return nil, fmt.Errorf("could not get execution data for block %d: %w", height, err)
163+
}
159164
return nil, fmt.Errorf("could not get execution data for block %d: %w", height, err)
160165
}
161166

engine/access/state_stream/backend/backend_account_statuses.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ package backend
22

33
import (
44
"context"
5+
"fmt"
56

67
"github.com/rs/zerolog"
78

89
"github.com/onflow/flow-go/engine/access/state_stream"
910
"github.com/onflow/flow-go/engine/access/subscription"
11+
"github.com/onflow/flow-go/fvm/errors"
1012
"github.com/onflow/flow-go/model/flow"
13+
"github.com/onflow/flow-go/storage"
1114
)
1215

1316
type AccountStatusesResponse struct {
@@ -54,7 +57,7 @@ func (b *AccountStatusesBackend) SubscribeAccountStatusesFromStartBlockID(
5457
// SubscribeAccountStatusesFromStartHeight subscribes to the streaming of account status changes starting from
5558
// a specific block height, with an optional status filter.
5659
// Errors:
57-
// - codes.ErrNotFound if could not get block by start height.
60+
// - codes.ErrNotFound if could not get block by start height.
5861
// - codes.Internal if there is an internal error.
5962
func (b *AccountStatusesBackend) SubscribeAccountStatusesFromStartHeight(
6063
ctx context.Context,
@@ -84,12 +87,20 @@ func (b *AccountStatusesBackend) SubscribeAccountStatusesFromLatestBlock(
8487
}
8588

8689
// getAccountStatusResponseFactory returns a function that returns the account statuses response for a given height.
90+
//
91+
// Errors:
92+
// - subscription.ErrBlockNotReady: If block header for the specified block height is not found.
93+
// - error: An error, if any, encountered during getting events from storage or execution data.
8794
func (b *AccountStatusesBackend) getAccountStatusResponseFactory(
8895
filter state_stream.AccountStatusFilter,
8996
) subscription.GetDataByHeightFunc {
9097
return func(ctx context.Context, height uint64) (interface{}, error) {
9198
eventsResponse, err := b.eventsRetriever.GetAllEventsResponse(ctx, height)
9299
if err != nil {
100+
if errors.Is(err, storage.ErrNotFound) ||
101+
errors.Is(err, storage.ErrHeightNotIndexed) {
102+
return nil, fmt.Errorf("block %d is not available yet: %w", height, subscription.ErrBlockNotReady)
103+
}
93104
return nil, err
94105
}
95106
filteredProtocolEvents := filter.Filter(eventsResponse.Events)

engine/access/state_stream/backend/backend_events.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ package backend
22

33
import (
44
"context"
5+
"fmt"
56

67
"github.com/rs/zerolog"
78

89
"github.com/onflow/flow-go/engine/access/state_stream"
910
"github.com/onflow/flow-go/engine/access/subscription"
11+
"github.com/onflow/flow-go/fvm/errors"
1012
"github.com/onflow/flow-go/model/flow"
13+
"github.com/onflow/flow-go/storage"
1114
)
1215

1316
type EventsBackend struct {
@@ -126,12 +129,16 @@ func (b *EventsBackend) SubscribeEventsFromLatest(ctx context.Context, filter st
126129
// - filter: The event filter used to filter events.
127130
//
128131
// Expected errors during normal operation:
129-
// - codes.NotFound: If block header for the specified block height is not found, if events for the specified block height are not found.
132+
// - subscription.ErrBlockNotReady: execution data for the given block height is not available.
130133
func (b *EventsBackend) getResponseFactory(filter state_stream.EventFilter) subscription.GetDataByHeightFunc {
131134
return func(ctx context.Context, height uint64) (response interface{}, err error) {
132135
eventsResponse, err := b.eventsRetriever.GetAllEventsResponse(ctx, height)
133136
if err != nil {
134-
return nil, err
137+
if errors.Is(err, storage.ErrNotFound) ||
138+
errors.Is(err, storage.ErrHeightNotIndexed) {
139+
return nil, subscription.ErrBlockNotReady
140+
}
141+
return nil, fmt.Errorf("block %d is not available yet: %w", height, subscription.ErrBlockNotReady)
135142
}
136143

137144
eventsResponse.Events = filter.Filter(eventsResponse.Events)

engine/access/subscription/streamer.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import (
1010
"golang.org/x/time/rate"
1111

1212
"github.com/onflow/flow-go/engine"
13-
"github.com/onflow/flow-go/module/executiondatasync/execution_data"
14-
"github.com/onflow/flow-go/storage"
1513
)
1614

1715
// ErrBlockNotReady represents an error indicating that a block is not yet available or ready.
@@ -105,10 +103,7 @@ func (s *Streamer) sendAllAvailable(ctx context.Context) error {
105103
}
106104

107105
if err != nil {
108-
if errors.Is(err, storage.ErrNotFound) ||
109-
errors.Is(err, storage.ErrHeightNotIndexed) ||
110-
execution_data.IsBlobNotFoundError(err) ||
111-
errors.Is(err, ErrBlockNotReady) {
106+
if errors.Is(err, ErrBlockNotReady) {
112107
// no more available
113108
return nil
114109
}

0 commit comments

Comments
 (0)