fix(claims): make verifyClaim block-atomic, idempotent, non-swallowing#55
Merged
Merged
Conversation
The old verifyClaim opened a nested db.withTransaction on a SEPARATE connection and swallowed every error via .catch(logError). On a transient failure the vote's check write rolled back while demux's outer block tx still committed _index_state past the block — the vote was lost and never retried. Root cause of claims stuck `pending` in Postgres while `approved` on chain (e.g. muda claim 19879, verifier ivamdasilvac vote dropped). - Write on the block-level `db` so the check insert, status recompute, and the _processed_actions ledger row commit or roll back together; a transient error now rolls back the whole block and demux retries it. - Idempotent insert: INSERT ... ON CONFLICT (claim_id, validator_id) DO NOTHING — no count-then-insert race, and the check_added trigger does not re-fire on replay. - Resolve claim / action / verifier BEFORE the insert; skip-and-log if any is missing (id drift / DB behind chain) instead of throwing. A throw here would deterministically crash-loop the indexer under pm2 and halt every community. Matches the assignRole / upsertAction skip-and-log pattern. - Guard the usages_left decrement with `usages_left > 0` (no negatives). GetActionsReader: add a seq-continuity tripwire in _loadNextBatch that logs loudly when get_actions returns a first account_action_seq ahead of the requested cursor (a history hole), so a future gap surfaces immediately instead of weeks later as a stuck claim. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Claims can end up stuck
pendingin Postgres whileapprovedon chain, making them "unapprovable": the UI reads the DB status, offers a vote, and the chain rejects it withCan't vote on already verified claim. Confirmed on muda claim 19879 — chain had 2/2 approving checks (majority reached), Postgres had only 1; validatorivamdasilvac'sverifyclaimwas never indexed.Root cause
The old
verifyClaimran its writes inside a nesteddb.withTransactionon a separate connection and swallowed every error with.catch(logError). On a transient failure the check write rolled back while demux's outer block tx still committed_index_statepast the block — the vote was lost and never retried.Fix
dbso the check insert, status recompute, and the_processed_actionsledger row commit or roll back together. A transient error now rolls back the whole block → demux retries it.INSERT ... ON CONFLICT (claim_id, validator_id) DO NOTHING(no count-then-insert race;check_addedtrigger doesn't re-fire on replay).assignRole/upsertAction.> 0(no negatives).GetActionsReader._loadNextBatchnow logs loudly ifget_actionsreturns a firstaccount_action_seqahead of the requested cursor (a history hole).Deploy notes
checks_claim_validator_uniq+_processed_actions(both present in prod).pm2 jlistrestart_timeper the runbook (crash-loop guard).Staff-reviewed; verdict SHIP.
🤖 Generated with Claude Code