fix(backend): wrap card updates in a transaction to prevent data loss#292
fix(backend): wrap card updates in a transaction to prevent data loss#292anshul23102 wants to merge 1 commit into
Conversation
|
Hi, |
|
Hi @Dev-Card team, just following up on this one. The issue it addresses is a silent data loss scenario: if any step in the card link update fails midway, partial writes get committed and the card ends up in an inconsistent state with no way to know which links were saved and which were not. Wrapping the whole operation in a Prisma transaction ensures it either fully succeeds or fully rolls back. All existing tests pass. Let me know if you would like any changes. |
e7d8ace to
bd33ad1
Compare
|
Hi @PrashantkumarKhatri! The Vercel check is showing 'Authorization required to deploy' on this one too - could you authorize the preview deployment when you get a chance? Ready for review whenever you are. Thanks! |
|
Hi @asyncasanas, could you please add the appropriate labels to this PR when you get a chance? It would really help with tracking the contribution. Thank you! |
|
Hi @Muneerali199, a friendly reminder on this PR. It has been about 4 days and it is conflict-free with no CI issues. Happy to address any feedback or make adjustments if needed. Thank you! |
|
(Correction to previous comment: tagging the right reviewer) Hi @ShantKhatri and @Prince2301p, a kind reminder on this PR. It has been about 4 days and the branch is conflict-free with no CI issues. Please let me know if you need any revisions. Thank you! |
|
Hi @anshul23102 , Please add proper PR description. |
|
Hi @ShantKhatri, thanks for the feedback. I have updated the PR description with a more detailed breakdown including before/after code snippets showing the exact change, the reasoning for each guard added, and updated test coverage notes. Please let me know if there is anything else you would like added or changed. |
|
Closing this PR as the underlying fix has already been incorporated into upstream main via PR #183 (which added |
Summary
When
PUT /api/cards/:idis called with a newlinkIdsarray, the handler ran two database writes sequentially outside a transaction: firstdeleteManyto remove existing card links, thencreateManyto insert the new ones. If thecreateManyfailed (constraint violation, network error, etc.), the deletion was already committed and the card was left with zero links. This PR wraps both operations in a Prisma$transactionso either both succeed or neither does.Closes #216
Type of Change
What Changed
apps/backend/src/routes/cards.tsBefore (two independent writes, no transaction):
After (atomic transaction):
Additional changes:
linkIdsthat belong to the authenticated user and rejects with 403 if the count does not match, preventing users from adding other users' links to their cardPUT /:id/defaultin a transaction so the existing default is cleared and the new default is set atomicallyapps/backend/src/__tests__/cards.test.ts$transactionsupportHow to Test
PUT /api/cards/:idwith alinkIdsarray containing a valid link ID — confirm the card now has exactly that link.createManyfailure (mock it to throw) — confirm the card links are unchanged after the failed request.PUT /api/cards/:idwith alinkIdsarray containing a link ID that belongs to a different user — confirm the response is 403 and no writes occur.Checklist
pnpm -r run lintpasses).pnpm -r run typecheck).pnpm -r run test).console.logor debug statements left in the code.Screenshots / Recordings
N/A (backend-only change, no UI impact)
Additional Context
Without the transaction, a network error or constraint violation between the two writes left the card in a permanently link-less state with no recovery path other than a direct database edit. The fix applies the same
$transactionpattern already used elsewhere in the codebase for atomic multi-step writes.