Repository navigation
docs: add idempotency posture decision - #1325
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
|
Warning Review limit reached
More reviews will be available in 58 minutes and 53 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: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
|
Failed to generate code suggestions for PR |
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
|
Closes #1320. Custom-command and embed-template POSTs hit `@@unique([guildId, name])` on replay (retry-after-flake, double-click) and surfaced a P2002-derived error even though the first request succeeded. - Catch P2002 in the two create routes, fetch the existing row, return it with 200. Idempotent success per the house pattern in `decisions/2026-06-12-idempotency-posture.md` (PR #1325). - Documented choice on genuine conflicts (same name, different payload): same path — the existing record is returned and the client edits via PATCH. No 409, no payload diffing. - The `created` server log is skipped on replay since nothing was created. - If the existing row vanished between P2002 and the fetch (delete race), the original error propagates — no silent 200 with an empty body. - Specs per route: replay returns existing + skips log; vanished-row race rethrows; embeds lookup uses the stored lowercased name. Backend suite: 1000/1000. <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Make named create routes idempotent. Replayed POSTs that hit the unique (guildId, name) return the existing record with 200 instead of a P2002 error for custom commands and embed templates (#1320). - **Bug Fixes** - Catch P2002 in both create routes; fetch and return the existing row (200). - Skip "created" server log on replays; if payload differs, edit via PATCH (no 409). - For embeds, look up by the stored lowercased name. - If the row disappears between P2002 and fetch, rethrow (no silent 200). - Add `isUniqueViolation` helper and integration tests for replay, delete race, and lowercase lookup. <sup>Written for commit ec62d97. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/LucasSantana-Dev/Lucky/pull/1326?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
Closes #1319. Double-submitting the support form (double-click, retry after a flaky response) created two reports and pinged the staff channel twice. - **Web form** generates one `crypto.randomUUID()` per form instance and sends it as `sid`; a retry of the same form reuses the key, a fresh mount is a new submission. - **Schema**: `SupportReport.submissionKey String? @unique` (+ migration). Nullable unique — NULLs don't collide, so bot-surface and older clients are unaffected. - **Service**: create catches P2002 on the key and returns the original report's id with `deduped: true` — dedup happens before the non-transactional staff ping, per `decisions/2026-06-12-idempotency-posture.md` (PR #1325). - **Route**: replayed `sid` → 200 with the original id, no second staff notification; malformed `sid` → 400. Specs: service (replay, no-key rethrow, vanished-row rethrow), route (pass-through, dedup skips ping, 400), web form (sid shape, retry reuses the same key). Verified: shared 16/16, backend support suite 21/21, frontend Support page 7/7; prisma-migration-verifier pass. <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Make support-report submissions idempotent to prevent duplicate reports and duplicate staff pings (#1319). The web form sends a per-mount UUID sid; the backend stores it as a nullable-unique submissionKey and returns the original report id on replays. - **New Features** - Frontend: generate one sid with crypto.randomUUID per form mount; retries reuse it. - API: accept optional sid (8–64 chars, [a-zA-Z0-9_-]); forward to the service. - Service/Route: persist submissionKey; on unique hit, fetch original id and return 200 without a second staff notification (normal create still 201). - Older clients and bot submissions without a key are unaffected. - **Migration** - Run the DB migration to add a nullable-unique submissionKey column (and index) to support_reports. <sup>Written for commit 6129d43. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/LucasSantana-Dev/Lucky/pull/1328?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->



Records the 2026-06-12 idempotency decision (research-and-decide run):
Summary by cubic
Adds an ADR that defines our idempotency posture: no blanket
Idempotency-Keymiddleware, targeted dedup fixes (#1319, #1320), and a house pattern (natural-key upserts, P2002-as-success, pre-side-effect dedup).Notes the reaction-role toggle race (#1199) is accepted for now and when to revisit (multi-instance, payments, public API).
Written for commit ed6f252. Summary will update on new commits.