Skip to content

fix(indexer): apply the rest of a block delivered in two parts - #79

Merged
lucca65 merged 1 commit into
masterfrom
fix/split-block-drop
Oct 18, 2026
Merged

lucca65 merged 1 commit into
masterfrom
fix/split-block-drop

Conversation

@lucca65

@lucca65 lucca65 commented Oct 18, 2026

Copy link
Copy Markdown
Member

Summary

The indexer silently dropped the second part of a block that GetActionsReader handed over in two parts.

How a block gets split:

  • a 100-action get_actions batch ends inside the block; or
  • one contract's fetch saw the block and the next contract's fetch didn't, or the other way round (the reader polls cambiatus.cm, cambiatus.tk and cambiatus.es one after another).

Both parts carry the same synthetic hash (synthetic-N). GetActionsHandler.handleBlock skipped any block whose number and hash matched the last processed one, so the second part never reached the updaters. The reader had already advanced its seq cursor and seen-set, so nothing re-read it. No error was logged.

Prod hit it. On 2026-10-14 at 11:58 UTC, in block 437155575, the cambiatus.tk::transfer was indexed and its cambiatus.cm::transfersale was skipped. In the prod DB that block has 1 transfer and 0 orders. The pm2 logs show 1 split in about 330 action blocks over the last 3 weeks. Older logs are rotated away. Repairing that order is a separate decision; this PR doesn't touch data.

Fix

handleBlock skips a repeated block only when it carries no actions. Applying the second part is safe:

  • the reader never re-sends an action it has already seen (seenGlobalSeqs);
  • every updater is ledgered on global_action_seq (_processed_actions), so a real duplicate would be a no-op anyway.

Test plan

  • test/split_block.test.js (new, no DB):
    • "applies both parts" was RED before the fix (only the first part reached the updaters) and is GREEN after;
    • "still skips an empty re-delivery of the last block" passes.
  • yarn test: 17 passing. yarn format is clean.
  • Lane (chain :8899, private DB): the claim-limits mirror run with this fix, together with the next PR, 5 of 5 accounts match chain mbrclaim, and claims (325) and checks (16) match chain exactly. The reader split 36 blocks in that run; before this fix, a run lost 7 claims this way.
  • code-simplifier: no changes.

🤖 Generated with Claude Code

GetActionsReader can hand one block over twice: when a 100-action batch ends inside
the block, or when one contract's get_actions saw the block and another's didn't yet.
Both parts carry the same synthetic hash, and handleBlock skipped any block whose
number and hash matched the last one processed, so the second part was dropped for
good (the reader had already advanced its seq cursor and seen-set).

Prod hit it on 2026-10-14: block 437155575's cambiatus.tk::transfer was indexed, its
cambiatus.cm::transfersale was skipped, and that order is missing from Postgres.

Skip a repeated block only when it carries no actions. Applying the second part is
safe: the reader never re-sends an action it has seen, and every updater is ledgered
on global_action_seq.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@lucca65
lucca65 merged commit 6cd98d1 into master Oct 18, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant