fix(idempotency): guard claim + order inserts against reindex duplicates#45
Merged
Conversation
claimAction and transferSale did bare inserts with no idempotency, so every re-indexed block re-inserted the claim/order as a fresh row -- surfacing as duplicate claims that look un-approved and phantom shop purchases that drain balances in the UI. Add a count-guard on the natural key before insert; the transferSale guard sits at the top of the withTransaction so it also skips the duplicate product stock decrement. Mirrors the existing token.js dedup guard. DB-level enforcement lands via the backend claims_dedup_idx / orders_dedup_idx. 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
claimActionandtransferSaledid bare.insert()with no idempotency. Every re-indexed block (microfork, pm2 restart resume, manual reindex) re-inserted the claim/order as a fresh row. User-visible symptoms:pendingrow with no checks, while the original was already approved.Prod magnitude (muda): ~3987 extra claim rows, ~5503 extra order rows. Only
token.js(transfers/mints) had the dedup guard; claims and orders were left bare.Fix
Mirror the existing
token.jscount-guard:claimAction: count on(created_tx, action_id, claimer_id)before insert; return if it exists.transferSale: guard at the top of thewithTransactionon(created_tx, from_id, product_id)→ returns early, so it also skips the duplicateproducts.unitsstock decrement (secondary bug).A single maker can't claim the same action twice in one tx, and a checkout is one
transfersaleper product, so these natural keys collapse true duplicates without dropping real rows.DB-level enforcement
Paired backend migrations add the matching unique indexes (
claims_dedup_idx,orders_dedup_idx) and dedup existing prod rows — backend PR #334. Deploy this (event-source) first to stop new duplicates, then run the backend migration.🤖 Generated with Claude Code