🐛 server: make card creation idempotent#1093
Conversation
|
Warning Review limit reached
More reviews will be available in 44 minutes and 42 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more credits in the billing tab to continue. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (6)
WalkthroughThis PR makes card creation idempotent by fetching a user's existing cards from Panda and adopting active orphan cards instead of always creating new ones. It adds a ChangesCard creation idempotency via orphan card adoption
🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
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. Comment |
There was a problem hiding this comment.
Code Review
This pull request makes card creation idempotent by checking for existing active cards ("orphan cards") and adopting them instead of creating duplicates. It also introduces a getCards utility to fetch a user's cards, handles card limit errors by returning a 409 Conflict status, and adds comprehensive unit and integration tests to verify these behaviors. There are no review comments, so I have no feedback to provide.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
🦋 Changeset detectedLatest commit: 73b8aa4 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 137d157985
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
✅ All tests passed. |
137d157 to
708e81f
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
server/api/card.ts (1)
537-539:⚠️ Potential issue | 🟠 Major | ⚡ Quick winUse upsert semantics when persisting an adopted orphan card.
This path always inserts
card.id. If a row with the sameidalready exists locally inDELETEDstate, the PK collision returns 500 and breaks idempotent recovery. Persist adoption with conflict handling (reactivate/update) instead of unconditional insert.proposed fix
- await database - .insert(cards) - .values([{ id: card.id, credentialId, lastFour: card.last4, mode, productId: SIGNATURE_PRODUCT_ID }]); + await database + .insert(cards) + .values([{ id: card.id, credentialId, lastFour: card.last4, mode, productId: SIGNATURE_PRODUCT_ID }]) + .onConflictDoUpdate({ + target: cards.id, + set: { + credentialId, + lastFour: card.last4, + mode, + status: "ACTIVE", + productId: SIGNATURE_PRODUCT_ID, + }, + });
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 113bd687-f60c-4837-881c-a214921b77ac
📒 Files selected for processing (6)
.changeset/swift-pandas-reconcile.mdserver/api/card.tsserver/test/api/card.test.tsserver/test/e2e.tsserver/test/utils/panda.test.tsserver/utils/panda.ts
708e81f to
73b8aa4
Compare
Summary by CodeRabbit