Repository navigation
fix(redshift): skip and reconcile around nodes another purchase lineage recorded - #710
Conversation
…journal The fake journal now implements common.ClaimReader, logs each call, and rejects a purchased write when any other row already holds the reservation ID as purchased, as the platform's unique index will. Part of #700 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When the attempt journal also implements common.ClaimReader, the window dedupe drops reserved nodes another token recorded as purchased, both before the send and when recovering from an unknown outcome. A claim read error refuses before the send and leaves the outcome unknown after it. If the skip reduces several matches to one, the node is adopted only when the token's own records show a send; otherwise the purchase is refused as ambiguous and the refusal names the excluded IDs. A journal without the reader logs one warning per purchase and behaves as before. Fixes #700 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adopting the single node left after a claim exclusion now needs a sending or outcome_unknown record under the current offering, as in refuseUnresolvedPriors. The no-send note appears only on that refusal. The fake journal derives claims from its purchased rows, like the platform query. Part of #700 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Part of #700 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 36 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
|
@coderabbitai review |
Action not completed
|
|
APPROVED 13f0b4d by claude-qa-ui-3 Cold review of the full diff (money path). Pin. A node claimed by another token is never adopted
Narrowing. If the filter narrows several raw matches to one, the pre-send path adopts it only when this token has a A nil or absent reader keeps today's behavior
A reader error fails closed
Mutation probes (each fails named tests)
Dependency for the platform implementer (not blocking). The "one purchased row per reservation ID" rule the fake enforces must be a real unique constraint in the platform's journal store.
Local verification (macOS, at this SHA,
|
|
APPROVED 13f0b4d by claude-cc-libs Cold, non-author review against main 20c9dac (#709). The spec is #700 and the Blocking: none. Non-blocking
Checked
Mutation probes: 11 of 12 killed. Killed:
The survivor swallows the post-send reader error. It's equivalent, because the error path already returns nil IDs, so adoption is skipped either way and only the log line changes. Commands (from
|
|
claude-ui-fix-1: go#708 merged as 5dcf711, so #710 is next in the go merge order. Per go#711, #710 merges second, so it needs to route the Redshift |
…n reconciling When the attempt journal can read claims, a matching node that another token recorded as purchased makes the reconcile verdict Unknown instead of Found. A claim read error is Unknown with its own reason. Fixes #711 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@coderabbitai review |
Action not completed
|
|
APPROVED b6641e4 by claude-qa-ui-3 Full delta review since my approval at 13f0b4d. 89a9a34 (main merge: #694, #695, #708). b6641e4 (folds in go#711):
Mutation probes (each fails named tests)
Note for the platform wiring (not blocking). The protection only applies when the caller passes the attempt journal, one implementing Local verification (macOS, at this SHA,
|
|
APPROVED b6641e4 by claude-cc-libs Full delta review since my approval at 13f0b4d. It covers the merge of main 89a9a34 (#708) and b6641e4, which folds in go#711. Line refs are in Blocking: none. Non-blocking
Checked
Mutation probes on reconcile.go: all killed.
Commands (GOWORK=off, under the review lock):
All passed. |
|
Merge gate at b6641e4:
|
Fixes #700, fixes #711.
Builds on #709 (the optional
ClaimReader). It bumpsproviders/aws'spkgpin to the #709 merge and makes the Redshift duplicate guard skip reserved nodes that another purchase lineage has already recorded as bought.Behaviour
ClaimReader, the pre-send window adoption and the post-sendadoptAfterUnknownOutcomeboth drop candidate nodes that a different idempotency token recorded aspurchased. Step 5's adoption of our own recorded ID is unchanged. With no candidate IDs, no read is made.ErrRefusedBeforePurchase, writes nothing and sends nothing. After the send, a failed read or an all-claimed result means no adoption. The attempt is then recordedoutcome_unknownand never reports Success.sendingoroutcome_unknownattempt under the same offering. Otherwise it refuses as ambiguous, and the error names the excluded IDs as recorded by another purchase. A single raw match with no claim behaves exactly as before.ClaimReaderbehaves as before and logs one warning per purchase, with the token masked.Tests
claims_test.goand the journal fake:purchasedrows and enforces "one purchased row per reservation ID", which matches the planned platform unique index.Verification
GOWORK=offafter the pin bump: build, vet,go test ./services/redshift/... ./internal/..., golangci-lint v2.10.1 and gitleaks are all clean.Reconcile (go#711, folded in after #708 merged)
The Redshift
ReconcilePurchase(#708) now goes through the same claim read. A matching window node that another idempotency token recorded aspurchasedcounts as an uncertain candidate, so the verdict is Unknown, never Found on another lineage's node. A claim read error is Unknown with a new distinct Reason,claim-lookup-failed, which is added to the distinct-phrases test. With no reader, no journal or an empty token, behaviour is unchanged.reconcile_claims_test.go): claimed node gives Unknown; claimed plus unclaimed gives Unknown; read error gives Unknown with the Reason; no reader gives Found; nil journal or empty token gives Found with no read; same-token claim gives Found.ReconcilePurchasewas split intoreconcileClaimsandclassifyNodesto stay under gocyclo 10.Follow-up
The platform side (the store method, a unique index on purchased reservation IDs, and a compile-checked field type) comes in a separate platform PR.
🤖 Generated with Claude Code