From efd2883db5318a837797647ff1548e3557f5e9ca Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Wed, 15 Oct 2025 19:18:34 +0000 Subject: [PATCH 1/3] Remove transaction retry functionality from Access RPC backend Co-Authored-By: peter.argue@flowfoundation.org --- .../node_builder/access_node_builder.go | 4 - engine/access/rpc/backend/backend.go | 2 - .../transactions/retrier/mock/retrier.go | 50 ----- .../retrier/mock/transaction_sender.go | 47 ----- .../rpc/backend/transactions/retrier/noop.go | 19 -- .../backend/transactions/retrier/retrier.go | 181 ------------------ .../stream/stream_backend_test.go | 1 - .../rpc/backend/transactions/transactions.go | 35 ---- .../backend/transactions/transactions_test.go | 146 -------------- engine/access/rpc/engine.go | 10 +- 10 files changed, 1 insertion(+), 494 deletions(-) delete mode 100644 engine/access/rpc/backend/transactions/retrier/mock/retrier.go delete mode 100644 engine/access/rpc/backend/transactions/retrier/mock/transaction_sender.go delete mode 100644 engine/access/rpc/backend/transactions/retrier/noop.go delete mode 100644 engine/access/rpc/backend/transactions/retrier/retrier.go diff --git a/cmd/access/node_builder/access_node_builder.go b/cmd/access/node_builder/access_node_builder.go index 5c2dce02ebb..d1697031f40 100644 --- a/cmd/access/node_builder/access_node_builder.go +++ b/cmd/access/node_builder/access_node_builder.go @@ -157,7 +157,6 @@ type AccessNodeConfig struct { logTxTimeToExecuted bool logTxTimeToFinalizedExecuted bool logTxTimeToSealed bool - retryEnabled bool rpcMetricsEnabled bool executionDataSyncEnabled bool publicNetworkExecutionDataEnabled bool @@ -253,7 +252,6 @@ func DefaultAccessNodeConfig() *AccessNodeConfig { logTxTimeToFinalizedExecuted: false, logTxTimeToSealed: false, pingEnabled: false, - retryEnabled: false, rpcMetricsEnabled: false, nodeInfoFile: "", apiRatelimits: nil, @@ -1288,7 +1286,6 @@ func (builder *FlowAccessNodeBuilder) extraFlags() { "ping-enabled", defaultConfig.pingEnabled, "whether to enable the ping process that pings all other peers and report the connectivity to metrics") - flags.BoolVar(&builder.retryEnabled, "retry-enabled", defaultConfig.retryEnabled, "whether to enable the retry mechanism at the access node level") flags.BoolVar(&builder.rpcMetricsEnabled, "rpc-metrics-enabled", defaultConfig.rpcMetricsEnabled, "whether to enable the rpc metrics") flags.UintVar(&builder.TxResultCacheSize, "transaction-result-cache-size", defaultConfig.TxResultCacheSize, "transaction result cache size.(Disabled by default i.e 0)") flags.StringVarP(&builder.nodeInfoFile, @@ -2130,7 +2127,6 @@ func (builder *FlowAccessNodeBuilder) Build() (cmd.Node, error) { ChainID: node.RootChainID, AccessMetrics: notNil(builder.AccessMetrics), ConnFactory: connFactory, - RetryEnabled: builder.retryEnabled, MaxHeightRange: backendConfig.MaxHeightRange, Log: node.Logger, SnapshotHistoryLimit: backend.DefaultSnapshotHistoryLimit, diff --git a/engine/access/rpc/backend/backend.go b/engine/access/rpc/backend/backend.go index 2c00ae9bc28..73906cc4f42 100644 --- a/engine/access/rpc/backend/backend.go +++ b/engine/access/rpc/backend/backend.go @@ -96,7 +96,6 @@ type Params struct { ChainID flow.ChainID AccessMetrics module.AccessMetrics ConnFactory connection.ConnectionFactory - RetryEnabled bool MaxHeightRange uint Log zerolog.Logger SnapshotHistoryLimit int @@ -251,7 +250,6 @@ func New(params Params) (*Backend, error) { HistoricalAccessNodeClients: params.HistoricalAccessNodes, NodeCommunicator: params.Communicator, ConnFactory: params.ConnFactory, - EnableRetries: params.RetryEnabled, NodeProvider: params.ExecNodeIdentitiesProvider, Blocks: params.Blocks, Collections: params.Collections, diff --git a/engine/access/rpc/backend/transactions/retrier/mock/retrier.go b/engine/access/rpc/backend/transactions/retrier/mock/retrier.go deleted file mode 100644 index 9dc257e6640..00000000000 --- a/engine/access/rpc/backend/transactions/retrier/mock/retrier.go +++ /dev/null @@ -1,50 +0,0 @@ -// Code generated by mockery. DO NOT EDIT. - -package mock - -import ( - flow "github.com/onflow/flow-go/model/flow" - mock "github.com/stretchr/testify/mock" -) - -// Retrier is an autogenerated mock type for the Retrier type -type Retrier struct { - mock.Mock -} - -// RegisterTransaction provides a mock function with given fields: height, tx -func (_m *Retrier) RegisterTransaction(height uint64, tx *flow.TransactionBody) { - _m.Called(height, tx) -} - -// Retry provides a mock function with given fields: height -func (_m *Retrier) Retry(height uint64) error { - ret := _m.Called(height) - - if len(ret) == 0 { - panic("no return value specified for Retry") - } - - var r0 error - if rf, ok := ret.Get(0).(func(uint64) error); ok { - r0 = rf(height) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// NewRetrier creates a new instance of Retrier. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewRetrier(t interface { - mock.TestingT - Cleanup(func()) -}) *Retrier { - mock := &Retrier{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/engine/access/rpc/backend/transactions/retrier/mock/transaction_sender.go b/engine/access/rpc/backend/transactions/retrier/mock/transaction_sender.go deleted file mode 100644 index 1322ab974c2..00000000000 --- a/engine/access/rpc/backend/transactions/retrier/mock/transaction_sender.go +++ /dev/null @@ -1,47 +0,0 @@ -// Code generated by mockery. DO NOT EDIT. - -package mock - -import ( - context "context" - - flow "github.com/onflow/flow-go/model/flow" - mock "github.com/stretchr/testify/mock" -) - -// TransactionSender is an autogenerated mock type for the TransactionSender type -type TransactionSender struct { - mock.Mock -} - -// SendRawTransaction provides a mock function with given fields: ctx, tx -func (_m *TransactionSender) SendRawTransaction(ctx context.Context, tx *flow.TransactionBody) error { - ret := _m.Called(ctx, tx) - - if len(ret) == 0 { - panic("no return value specified for SendRawTransaction") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *flow.TransactionBody) error); ok { - r0 = rf(ctx, tx) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// NewTransactionSender creates a new instance of TransactionSender. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewTransactionSender(t interface { - mock.TestingT - Cleanup(func()) -}) *TransactionSender { - mock := &TransactionSender{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/engine/access/rpc/backend/transactions/retrier/noop.go b/engine/access/rpc/backend/transactions/retrier/noop.go deleted file mode 100644 index 5f228e078c7..00000000000 --- a/engine/access/rpc/backend/transactions/retrier/noop.go +++ /dev/null @@ -1,19 +0,0 @@ -package retrier - -import ( - "github.com/onflow/flow-go/model/flow" -) - -type NoopRetrier struct{} - -var _ Retrier = (*NoopRetrier)(nil) - -func NewNoopRetrier() *NoopRetrier { - return &NoopRetrier{} -} - -func (n *NoopRetrier) Retry(_ uint64) error { - return nil -} - -func (n *NoopRetrier) RegisterTransaction(_ uint64, _ *flow.TransactionBody) {} diff --git a/engine/access/rpc/backend/transactions/retrier/retrier.go b/engine/access/rpc/backend/transactions/retrier/retrier.go deleted file mode 100644 index 8f829827a14..00000000000 --- a/engine/access/rpc/backend/transactions/retrier/retrier.go +++ /dev/null @@ -1,181 +0,0 @@ -package retrier - -import ( - "context" - "errors" - "fmt" - "sync" - - "github.com/rs/zerolog" - - "github.com/onflow/flow-go/engine/access/rpc/backend/transactions/status" - "github.com/onflow/flow-go/model/flow" - "github.com/onflow/flow-go/state" - "github.com/onflow/flow-go/storage" -) - -// RetryFrequency has to be less than TransactionExpiry or else this module does nothing -const RetryFrequency uint64 = 120 // Blocks - -type Transactions map[flow.Identifier]*flow.TransactionBody -type BlockHeightToTransactions map[uint64]Transactions - -type TransactionSender interface { - SendRawTransaction(ctx context.Context, tx *flow.TransactionBody) error -} - -type Retrier interface { - Retry(height uint64) error - RegisterTransaction(height uint64, tx *flow.TransactionBody) -} - -// RetrierImpl implements a simple retry mechanism for transaction submission. -type RetrierImpl struct { - log zerolog.Logger - - mu sync.RWMutex - pendingTransactions BlockHeightToTransactions - - blocks storage.Blocks - collections storage.Collections - - txSender TransactionSender - txStatusDeriver *status.TxStatusDeriver -} - -func NewRetrier( - log zerolog.Logger, - blocks storage.Blocks, - collections storage.Collections, - txSender TransactionSender, - txStatusDeriver *status.TxStatusDeriver, -) *RetrierImpl { - return &RetrierImpl{ - log: log, - pendingTransactions: BlockHeightToTransactions{}, - blocks: blocks, - collections: collections, - txSender: txSender, - txStatusDeriver: txStatusDeriver, - } -} - -// Retry attempts to resend transactions for a specified block height. -// It performs cleanup operations, including pruning old transactions, and retries sending -// transactions that are still pending. -// The method takes a block height as input. If the provided height is lower than -// flow.DefaultTransactionExpiry, no retries are performed, and the method returns nil. -// No errors expected during normal operations. -func (r *RetrierImpl) Retry(height uint64) error { - // No need to retry if height is lower than DefaultTransactionExpiry - if height < flow.DefaultTransactionExpiry { - return nil - } - - // naive cleanup for now, prune every 120 Blocks - if height%RetryFrequency == 0 { - r.prune(height) - } - - heightToRetry := height - flow.DefaultTransactionExpiry + RetryFrequency - - for heightToRetry < height { - err := r.retryTxsAtHeight(heightToRetry) - if err != nil { - return err - } - heightToRetry = heightToRetry + RetryFrequency - } - return nil -} - -// RegisterTransaction adds a transaction that could possibly be retried -func (r *RetrierImpl) RegisterTransaction(height uint64, tx *flow.TransactionBody) { - r.mu.Lock() - defer r.mu.Unlock() - if r.pendingTransactions[height] == nil { - r.pendingTransactions[height] = make(map[flow.Identifier]*flow.TransactionBody) - } - r.pendingTransactions[height][tx.ID()] = tx -} - -func (r *RetrierImpl) prune(height uint64) { - r.mu.Lock() - defer r.mu.Unlock() - // If height is less than the default, there will be no expired Transactions - if height < flow.DefaultTransactionExpiry { - return - } - for h := range r.pendingTransactions { - if h < height-flow.DefaultTransactionExpiry { - delete(r.pendingTransactions, h) - } - } -} - -// retryTxsAtHeight retries transactions at a specific block height. -// It looks up transactions at the specified height and retries sending -// raw transactions for those that are still pending. It also cleans up -// transactions that are no longer pending or have an unknown status. -// Error returns: -// - errors are unexpected and potentially symptoms of internal implementation bugs or state corruption (fatal). -func (r *RetrierImpl) retryTxsAtHeight(heightToRetry uint64) error { - r.mu.Lock() - defer r.mu.Unlock() - txsAtHeight := r.pendingTransactions[heightToRetry] - for txID, tx := range txsAtHeight { - // find the block for the transaction - block, err := r.lookupBlock(txID) - if err != nil { - if !errors.Is(err, storage.ErrNotFound) { - return err - } - block = nil - } - - // find the transaction status - var status flow.TransactionStatus - if block == nil { - status, err = r.txStatusDeriver.DeriveUnknownTransactionStatus(tx.ReferenceBlockID) - } else { - status, err = r.txStatusDeriver.DeriveTransactionStatus(block.Height, false) - } - - if err != nil { - if !errors.Is(err, state.ErrUnknownSnapshotReference) { - return err - } - continue - } - if status == flow.TransactionStatusPending { - err = r.txSender.SendRawTransaction(context.Background(), tx) - if err != nil { - r.log.Info(). - Str("retry", fmt.Sprintf("retryTxsAtHeight: %v", heightToRetry)). - Err(err). - Msg("failed to send raw transactions") - } - } else if status != flow.TransactionStatusUnknown { - // not pending or unknown, don't need to retry anymore - delete(txsAtHeight, txID) - } - } - return nil -} - -// Error returns: -// - `storage.ErrNotFound` - collection referenced by transaction or block by a collection has not been found. -// - all other errors are unexpected and potentially symptoms of internal implementation bugs or state corruption (fatal). -func (r *RetrierImpl) lookupBlock(txID flow.Identifier) (*flow.Block, error) { - collection, err := r.collections.LightByTransactionID(txID) - if err != nil { - return nil, err - } - - block, err := r.blocks.ByCollectionID(collection.ID()) - if err != nil { - return nil, err - } - - return block, nil -} diff --git a/engine/access/rpc/backend/transactions/stream/stream_backend_test.go b/engine/access/rpc/backend/transactions/stream/stream_backend_test.go index 630a2671480..4cbfaccd5ac 100644 --- a/engine/access/rpc/backend/transactions/stream/stream_backend_test.go +++ b/engine/access/rpc/backend/transactions/stream/stream_backend_test.go @@ -313,7 +313,6 @@ func (s *TransactionStreamSuite) initializeBackend() { HistoricalAccessNodeClients: nil, NodeCommunicator: nodeCommunicator, ConnFactory: s.connectionFactory, - EnableRetries: false, NodeProvider: execNodeProvider, Blocks: s.blocks, Collections: s.collections, diff --git a/engine/access/rpc/backend/transactions/transactions.go b/engine/access/rpc/backend/transactions/transactions.go index e04831f7e03..8db04625e23 100644 --- a/engine/access/rpc/backend/transactions/transactions.go +++ b/engine/access/rpc/backend/transactions/transactions.go @@ -19,7 +19,6 @@ import ( "github.com/onflow/flow-go/engine/access/rpc/backend/node_communicator" "github.com/onflow/flow-go/engine/access/rpc/backend/transactions/error_messages" "github.com/onflow/flow-go/engine/access/rpc/backend/transactions/provider" - "github.com/onflow/flow-go/engine/access/rpc/backend/transactions/retrier" txstatus "github.com/onflow/flow-go/engine/access/rpc/backend/transactions/status" "github.com/onflow/flow-go/engine/access/rpc/connection" "github.com/onflow/flow-go/engine/common/rpc" @@ -50,7 +49,6 @@ type Transactions struct { historicalAccessNodeClients []accessproto.AccessAPIClient nodeCommunicator node_communicator.Communicator connectionFactory connection.ConnectionFactory - retrier retrier.Retrier // Storages blocks storage.Blocks @@ -79,7 +77,6 @@ type Params struct { HistoricalAccessNodeClients []accessproto.AccessAPIClient NodeCommunicator node_communicator.Communicator ConnFactory connection.ConnectionFactory - EnableRetries bool NodeProvider *rpc.ExecutionNodeIdentitiesProvider Blocks storage.Blocks Collections storage.Collections @@ -117,18 +114,6 @@ func NewTransactionsBackend(params Params) (*Transactions, error) { scheduledCallbacksEnabled: params.ScheduledCallbacksEnabled, } - if params.EnableRetries { - txs.retrier = retrier.NewRetrier( - params.Log, - params.Blocks, - params.Collections, - txs, - params.TxStatusDeriver, - ) - } else { - txs.retrier = retrier.NewNoopRetrier() - } - return txs, nil } @@ -156,8 +141,6 @@ func (t *Transactions) SendTransaction(ctx context.Context, tx *flow.Transaction return status.Errorf(codes.Internal, "failed to store transaction: %v", err) } - go t.registerTransactionForRetry(tx) - return nil } @@ -627,21 +610,3 @@ func (t *Transactions) getHistoricalTransactionResult( } return nil, status.Errorf(codes.NotFound, "no known transaction with ID %s", txID) } - -func (t *Transactions) registerTransactionForRetry(tx *flow.TransactionBody) { - referenceBlock, err := t.state.AtBlockID(tx.ReferenceBlockID).Head() - if err != nil { - return - } - - t.retrier.RegisterTransaction(referenceBlock.Height, tx) -} - -// ATTENTION: might be a source of problems in future. We run this code on finalization gorotuine, -// potentially lagging finalization events if operations take long time. -// We might need to move this logic on dedicated goroutine and provide a way to skip finalization events if they are delivered -// too often for this engine. An example of similar approach - https://github.com/onflow/flow-go/blob/10b0fcbf7e2031674c00f3cdd280f27bd1b16c47/engine/common/follower/compliance_engine.go#L201.. -// No errors expected during normal operations. -func (t *Transactions) ProcessFinalizedBlockHeight(height uint64) error { - return t.retrier.Retry(height) -} diff --git a/engine/access/rpc/backend/transactions/transactions_test.go b/engine/access/rpc/backend/transactions/transactions_test.go index 7531cf6d29d..71360aa3d92 100644 --- a/engine/access/rpc/backend/transactions/transactions_test.go +++ b/engine/access/rpc/backend/transactions/transactions_test.go @@ -31,7 +31,6 @@ import ( "github.com/onflow/flow-go/engine/access/rpc/backend/node_communicator" "github.com/onflow/flow-go/engine/access/rpc/backend/transactions/error_messages" "github.com/onflow/flow-go/engine/access/rpc/backend/transactions/provider" - "github.com/onflow/flow-go/engine/access/rpc/backend/transactions/retrier" txstatus "github.com/onflow/flow-go/engine/access/rpc/backend/transactions/status" connectionmock "github.com/onflow/flow-go/engine/access/rpc/connection/mock" commonrpc "github.com/onflow/flow-go/engine/common/rpc" @@ -222,7 +221,6 @@ func (suite *Suite) defaultTransactionsParams() Params { HistoricalAccessNodeClients: nil, NodeCommunicator: nodeCommunicator, ConnFactory: suite.connectionFactory, - EnableRetries: true, NodeProvider: nodeProvider, Blocks: suite.blocks, Collections: suite.collections, @@ -1624,150 +1622,6 @@ func (suite *Suite) TestTransactionResultsByBlockIDFromExecutionNode() { } } -// TestTransactionRetry tests that the retry mechanism will send retries at specific times -func (suite *Suite) TestTransactionRetry() { - block := unittest.BlockFixture( - // Height needs to be at least DefaultTransactionExpiry before we start doing retries - unittest.Block.WithHeight(flow.DefaultTransactionExpiry + 1), - ) - transactionBody := unittest.TransactionBodyFixture(unittest.WithReferenceBlock(block.ID())) - headBlock := unittest.BlockFixture() - headBlock.Height = block.Height - 1 // head is behind the current block - suite.state.On("Final").Return(suite.snapshot, nil) - - suite.snapshot.On("Head").Return(headBlock.ToHeader(), nil) - snapshotAtBlock := protocolmock.NewSnapshot(suite.T()) - snapshotAtBlock.On("Head").Return(block.ToHeader(), nil) - suite.state.On("AtBlockID", block.ID()).Return(snapshotAtBlock, nil) - - // collection storage returns a not found error - suite.collections. - On("LightByTransactionID", transactionBody.ID()). - Return(nil, storage.ErrNotFound) - - client := accessmock.NewAccessAPIClient(suite.T()) - params := suite.defaultTransactionsParams() - params.StaticCollectionRPCClient = client - txBackend, err := NewTransactionsBackend(params) - suite.Require().NoError(err) - - retry := retrier.NewRetrier( - suite.log, - suite.blocks, - suite.collections, - txBackend, - txBackend.txStatusDeriver, - ) - retry.RegisterTransaction(block.Height, &transactionBody) - - client.On("SendTransaction", mock.Anything, mock.Anything).Return(&access.SendTransactionResponse{}, nil) - - // Don't retry on every height - err = retry.Retry(block.Height + 1) - suite.Require().NoError(err) - - client.AssertNotCalled(suite.T(), "SendTransaction", mock.Anything, mock.Anything) - - // Retry every `retryFrequency` - err = retry.Retry(block.Height + retrier.RetryFrequency) - suite.Require().NoError(err) - - client.AssertNumberOfCalls(suite.T(), "SendTransaction", 1) - - // do not retry if expired - err = retry.Retry(block.Height + retrier.RetryFrequency + flow.DefaultTransactionExpiry) - suite.Require().NoError(err) - - // Should've still only been called once - client.AssertNumberOfCalls(suite.T(), "SendTransaction", 1) -} - -// TestSuccessfulTransactionsDontRetry tests that the retry mechanism will send retries at specific times -func (suite *Suite) TestSuccessfulTransactionsDontRetry() { - collection := unittest.CollectionFixture(1) - light := collection.Light() - transactionBody := collection.Transactions[0] - txID := transactionBody.ID() - - block := unittest.BlockFixture() - blockID := block.ID() - - // setup chain state - _, fixedENIDs := suite.setupReceipts(block) - suite.fixedExecutionNodeIDs = fixedENIDs.NodeIDs() - - suite.state.On("Final").Return(suite.snapshot, nil) - suite.transactions.On("ByID", transactionBody.ID()).Return(transactionBody, nil) - suite.collections.On("LightByTransactionID", transactionBody.ID()).Return(light, nil) - suite.blocks.On("ByCollectionID", collection.ID()).Return(block, nil) - suite.snapshot.On("Identities", mock.Anything).Return(fixedENIDs, nil) - - exeEventReq := execproto.GetTransactionResultRequest{ - BlockId: blockID[:], - TransactionId: txID[:], - } - exeEventResp := execproto.GetTransactionResultResponse{ - Events: nil, - } - suite.executionAPIClient. - On("GetTransactionResult", context.Background(), &exeEventReq). - Return(&exeEventResp, status.Errorf(codes.NotFound, "not found")). - Times(len(fixedENIDs)) // should call each EN once - - suite.connectionFactory. - On("GetExecutionAPIClient", mock.Anything). - Return(suite.executionAPIClient, &mocks.MockCloser{}, nil). - Times(len(fixedENIDs)) - - params := suite.defaultTransactionsParams() - client := accessmock.NewAccessAPIClient(suite.T()) - params.StaticCollectionRPCClient = client - txBackend, err := NewTransactionsBackend(params) - suite.Require().NoError(err) - - retry := retrier.NewRetrier( - suite.log, - suite.blocks, - suite.collections, - txBackend, - txBackend.txStatusDeriver, - ) - retry.RegisterTransaction(block.Height, transactionBody) - - // first call - when block under test is greater height than the sealed head, but execution node does not know about Tx - result, err := txBackend.GetTransactionResult( - context.Background(), - txID, - flow.ZeroID, - flow.ZeroID, - entities.EventEncodingVersion_JSON_CDC_V0, - ) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - // status should be finalized since the sealed Blocks is smaller in height - suite.Assert().Equal(flow.TransactionStatusFinalized, result.Status) - - // Don't retry when block is finalized - err = retry.Retry(block.Height + 1) - suite.Require().NoError(err) - - client.AssertNotCalled(suite.T(), "SendTransaction", mock.Anything, mock.Anything) - - // Don't retry when block is finalized - err = retry.Retry(block.Height + retrier.RetryFrequency) - suite.Require().NoError(err) - - client.AssertNotCalled(suite.T(), "SendTransaction", mock.Anything, mock.Anything) - - // Don't retry when block is finalized - err = retry.Retry(block.Height + retrier.RetryFrequency + flow.DefaultTransactionExpiry) - suite.Require().NoError(err) - - // Should've still should not be called - client.AssertNotCalled(suite.T(), "SendTransaction", mock.Anything, mock.Anything) -} - func (suite *Suite) setupReceipts(block *flow.Block) ([]*flow.ExecutionReceipt, flow.IdentityList) { ids := unittest.IdentityListFixture(2, unittest.WithRole(flow.RoleExecution)) receipt1 := unittest.ReceiptForBlockFixture(block) diff --git a/engine/access/rpc/engine.go b/engine/access/rpc/engine.go index 4e0e9ff4394..b8f16f54706 100644 --- a/engine/access/rpc/engine.go +++ b/engine/access/rpc/engine.go @@ -185,22 +185,14 @@ func (e *Engine) OnFinalizedBlock(block *model.Block) { // The input to this callback is treated as trusted. // No errors expected during normal operations. func (e *Engine) processOnFinalizedBlock(_ *model.Block) error { - finalizedHeader := e.finalizedHeaderCache.Get() - - var err error // NOTE: The BlockTracker is currently only used by the access node and not by the observer node. if e.backend.BlockTracker != nil { - err = e.backend.BlockTracker.ProcessOnFinalizedBlock() + err := e.backend.BlockTracker.ProcessOnFinalizedBlock() if err != nil { return err } } - err = e.backend.ProcessFinalizedBlockHeight(finalizedHeader.Height) - if err != nil { - return fmt.Errorf("could not process finalized block height %d: %w", finalizedHeader.Height, err) - } - return nil } From 43fbf6462c0ef1f757732050d44f93b0a6bd4144 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Wed, 15 Oct 2025 19:24:02 +0000 Subject: [PATCH 2/3] Remove RetryEnabled from observer node builder Co-Authored-By: peter.argue@flowfoundation.org --- cmd/observer/node_builder/observer_builder.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/observer/node_builder/observer_builder.go b/cmd/observer/node_builder/observer_builder.go index e2958d9fefa..8e4947c5873 100644 --- a/cmd/observer/node_builder/observer_builder.go +++ b/cmd/observer/node_builder/observer_builder.go @@ -1973,7 +1973,6 @@ func (builder *ObserverServiceBuilder) enqueueRPCServer() { ChainID: node.RootChainID, AccessMetrics: accessMetrics, ConnFactory: connFactory, - RetryEnabled: false, MaxHeightRange: backendConfig.MaxHeightRange, Log: node.Logger, SnapshotHistoryLimit: backend.DefaultSnapshotHistoryLimit, From 59320d69310fc19be93da661a2ef6d87e6363fde Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 16 Oct 2025 00:10:04 +0000 Subject: [PATCH 3/3] Remove retrier entry from mockery configuration Co-Authored-By: peter.argue@flowfoundation.org --- .mockery.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.mockery.yaml b/.mockery.yaml index a99b7c9e56d..e40812da942 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -31,7 +31,6 @@ packages: github.com/onflow/flow-go/engine/access/rpc/backend/node_communicator: github.com/onflow/flow-go/engine/access/rpc/backend/transactions/error_messages: github.com/onflow/flow-go/engine/access/rpc/backend/transactions/provider: - github.com/onflow/flow-go/engine/access/rpc/backend/transactions/retrier: github.com/onflow/flow-go/engine/access/rpc/connection: github.com/onflow/flow-go/engine/access/state_stream: github.com/onflow/flow-go/engine/access/subscription: