Skip to content

[#8] Add Voucher clone — single-use redemption with atomic claim guarantee - #17

Open
lincai505011-ops wants to merge 1 commit into
quicksilverj2:mainfrom
lincai505011-ops:bounty-8
Open

[#8] Add Voucher clone — single-use redemption with atomic claim guarantee#17
lincai505011-ops wants to merge 1 commit into
quicksilverj2:mainfrom
lincai505011-ops:bounty-8

Conversation

@lincai505011-ops

Copy link
Copy Markdown

What

Adds the Voucher clone: single-use voucher redemption with atomic claim guarantee under concurrent load.

Design

  • Pattern B: Atomic UPDATE … RETURNING — uses raw SQL UPDATE "Voucher" SET "redeemedBy" = $userId … WHERE "redeemedBy" IS NULL RETURNING * so Postgres serialises concurrent claimants on the row lock. No race, no 5xx.
  • Empty RETURNING set → clean 404 (voucher not found) or 409 (already redeemed).
  • Idempotent by construction: exactly one concurrent redeem wins, rest get 409.

Changes

File Purpose
prisma/schema.prisma Added Voucher model — code PK, value, redeemedBy (nullable), redeemedAt, createdAt
prisma/migrations/0001_voucher/migration.sql Migration: CREATE TABLE
src/app.ts Added POST /voucher (create) and POST /voucher/:code/redeem (atomic redeem) routes; added voucher counter to /metrics
prisma/seed.ts Registered voucher clone in gallery
test/voucher.test.ts 5 tests: happy path, already-redeemed 409, not-found 404, validation 400, concurrent redeems invariant
probes/concurrency-voucher.mjs Live concurrency probe: 20 concurrent redeems → exactly one 200, rest 409, zero 5xx

Invariant

20 concurrent redeems of one voucher → exactly one succeeds (200), the rest get clean 409 — zero 5xx.

Closes #8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bounty] Voucher clone (single-use redemption)

1 participant