Skip to content

Commit

Permalink
fix: resolve indexer infinite loop
Browse files Browse the repository at this point in the history
on very slow drives or when run with limited resources, a node can have
a delay between the block existing & being saved and the block_results
getting saved. if the block exists, but the block_results do not, an
infinite loop occurs. the indexer will repeatedly request the block and
block_results until they both exist. the lack of delay can further
constrain the node's resources and result in many calls for block_results
before they are committed.

this commit updates the condition for waiting to include whenever an error
occurred during indexing. if the indexer fails to find the block_results
it will bombard the node with requests for it without backing off. this
change causes errors to trigger a wait. after waiting for either a new
block or for the timeout, the block results are more likely to exist.
  • Loading branch information
pirtleshell committed Oct 21, 2024
1 parent 6aa9e61 commit 34ff473
Showing 1 changed file with 12 additions and 4 deletions.
16 changes: 12 additions & 4 deletions server/indexer_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/cenkalti/backoff/v4"
"github.com/cometbft/cometbft/libs/service"
rpcclient "github.com/cometbft/cometbft/rpc/client"
coretypes "github.com/cometbft/cometbft/rpc/core/types"
"github.com/cometbft/cometbft/types"

ethermint "github.com/evmos/ethermint/types"
Expand Down Expand Up @@ -112,21 +113,28 @@ func (eis *EVMIndexerService) OnStart() error {
lastBlock = latestBlock
}
for {
if latestBlock <= lastBlock {
// nothing to index. wait for signal of new block
var block *coretypes.ResultBlock
var blockResult *coretypes.ResultBlockResults
if latestBlock <= lastBlock || err != nil {
// two cases:
// 1. nothing to index (indexer is caught up). wait for signal of new block.
// 2. previous attempt to index errored (failed to fetch the Block or BlockResults).
// in this case, wait before retrying the data fetching, rather than infinite looping
// a failing fetch. this can occur due to drive latency between the block existing and its
// block_results getting saved.
select {
case <-newBlockSignal:
case <-time.After(NewBlockWaitTimeout):
}
continue
}
for i := lastBlock + 1; i <= latestBlock; i++ {
block, err := eis.client.Block(ctx, &i)
block, err = eis.client.Block(ctx, &i)
if err != nil {
eis.Logger.Error("failed to fetch block", "height", i, "err", err)
break
}
blockResult, err := eis.client.BlockResults(ctx, &i)
blockResult, err = eis.client.BlockResults(ctx, &i)
if err != nil {
eis.Logger.Error("failed to fetch block result", "height", i, "err", err)
break
Expand Down

0 comments on commit 34ff473

Please sign in to comment.