Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/chain.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ async function claimPage (communityContract, lowerBound, limit) {
// ascending, never reused and never deleted (verifyclaim only mutates status).
// event-source processes actions in chain order, so the claim created by the
// action being processed is the FIRST claim on chain for this (action, claimer)
// with an id above every claim id already recorded — `afterId`, the DB's current
// max claim id.
// with an id above every claim id already recorded up to this block — `afterId`,
// the DB's max claim id with created_block <= the action's block (see claimAction).
//
// Reading forward from a watermark, rather than counting a pair's claims and
// taking the nth, is what makes this safe under truncation: a short page just
Expand Down
14 changes: 13 additions & 1 deletion src/updaters/community.js
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,19 @@ async function claimAction (db, payload, blockInfo, context) {
// catches it, un-claims this action's global_seq in _processed_actions so a
// later reindex can pick it up, and pages via Sentry. It is therefore
// impossible for a resolve failure to reach the INSERT below with a serial id.
const { watermark } = await db.instance.one('SELECT coalesce(max(id), 0) AS watermark FROM claims')
//
// The watermark is the highest claim id recorded AT OR BEFORE this block, not the
// table-wide max. Indexing live, the two are the same number (nothing later exists
// yet). On a reindex they differ: the table-wide max sits above every claim the
// replay revisits, so a claim skipped by a ResolveError could never be resolved —
// the lookup started above its id and threw again. Bounding by block puts the
// watermark back where it stood when the claim was first seen. A same-block claim
// recorded after this one can still push it too high; that only throws (skip and
// retry), never resolves to a wrong id.
const { watermark } = await db.instance.one(
'SELECT coalesce(max(id), 0) AS watermark FROM claims WHERE created_block <= $1',
[blockInfo.blockNumber]
)
let claimId
try {
claimId = await resolveClaimId(
Expand Down
Loading