Repository navigation
feat(purchase): record Redshift purchase attempts in a durable journal - #1824
Conversation
Add the purchase_attempts table and the PostgresStore RecordAttempt and PriorAttempts methods that implement common.AttemptJournal. The upsert encodes the transition table; offering_id is write-once. Part of LeanerCloud/cloud-commitments-go#107 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
ManagerConfig gains AttemptJournal, set to the config store by the post-DB Manager config, and each per-rec dispatch passes it in PurchaseOptions. Part of LeanerCloud/cloud-commitments-go#107 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A failed rec that still carries a commitment ID keeps it as PurchaseID. The failure email switches to the outcome-unknown variant and names the node, and the failure log marker lists the IDs. Part of LeanerCloud/cloud-commitments-go#107 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…plate An unrecorded commitment now selects the outcome-unknown email on its own, so a caller that assigns OutcomeUnknown later cannot switch it back to the retry wording. The ID line names a non-Redshift commitment generically, and the log-marker test pins the exact ID list. Part of LeanerCloud/cloud-commitments-go#107 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Open PR #1239 takes 000158-000160, so this migration moves to 000161. Part of LeanerCloud/cloud-commitments-go#107 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 43 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 12a6b74 by claude-qa-ui-4 Cold review against go#107 decision A, with the go contract pkg/common/attempt_journal.go at the pinned c83aef8b18a9.
Runs (GOMAXPROCS=4, -p 2):
Non-blocking, but please follow up (money path):
|
|
APPROVED 12a6b74 by claude-darling Cold review; I did not write this change. This is a money path with a migration. It implements go#107 decision A on top of #702's claim and Contract (go pinned at c83aef8; go.mod unchanged)
Migration 000161
One time source. The PR adds no Non-Redshift unchanged. Only the go redshift package reads Email precedence. Double-buy. Redshift redrive is still refused ( Findings (low)
Probes (scoped with
CI at this head: 41 of 41 pass, including Unit Tests, Integration (config, purchase, migrations rest, server, api) and the migration down gate. Run https://github.com/LeanerCloud/cloud-commitments-platform/actions/runs/42302937370. |
|
Merge gate at 12a6b74:
|
Part of LeanerCloud/cloud-commitments-go#107. This is the platform side of the Redshift purchase attempt journal. The go side shipped in cloud-commitments-go #696 (contract) and #701 (Redshift flow), and is pinned here by #1817.
What
purchase_attempts. Keyed by (idempotency token, execution ID). It stores the attempt state (sending,purchasedoroutcome_unknown, exactly go's strings), the reservation ID, and a write-once offering ID. A CHECK makes a rowpurchasedif and only if it has a reservation ID. The down migration drops the table.store_postgres_attempts.go).PostgresStoreimplementscommon.AttemptJournal:RecordAttemptvalidates the record, then does one autocommit upsert whose WHERE clause encodes go's transition table:sendingorpurchased;sendingtopurchasedoroutcome_unknown;outcome_unknowntopurchased;purchasedtopurchasedonly with the same ID.Anything else, including identical repeats and a first row of
outcome_unknown, is an error. The offering ID is written once.PriorAttemptsreads all attempts for a token.Neither method runs inside a caller's transaction.
ManagerConfig.AttemptJournalis set only on the post-DB manager, through a new purepostDBPurchaseManagerConfig. The pre-DB manager keeps a nil journal, which keeps go's existing window dedupe.PurchaseIDwithPurchased=false. A Retry successor that fails without an ID keeps its predecessor's ID.OutcomeUnknowndirectly.unrecorded_commitment_ids=for deployments without email.Tests and verification (local, macOS, throttled; branch merged with main incl. #1816 and #1239 at 12a6b74)
go testfor config, purchase, email, server and ctxutil pass.TestIdempotencyKeyCopyHasSingleWriterpasses, so this change adds no IdempotencyKey writer.-tags integrationfor config (the 16 transition cases, an invalid record rejected before any SQL, PriorAttempts across executions, offering ID write-once), migrations (000158-000161 and the down path, on top of fix(recommendations): key stored recs, rec ID and purchase identity on RDS az_config (#408) #1239) and purchase pass.Deploy order
Apply migration 000161 BEFORE deploying this code. With
DB_AUTO_MIGRATEoff, deploying the code first fails closed: the journal'sPriorAttemptsandRecordAttempthit a missing table, so every tokenized Redshift purchase is refused before the send. That is an outage for Redshift buys, never a double buy. Other services are unaffected. #1239 (000158-000160) has already merged, so there is no migration-number conflict.Ordering
This lands before #702 PR3b, which uses
ManagerConfig.AttemptJournal. The migration is 000161 because #1239 takes 000158-000160.🤖 Generated with Claude Code