Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions apps/web/app/api/coupons/vote/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,18 @@ export async function POST(req: NextRequest) {
try {
const db = getDb();

// Check for duplicate
// Check for existing vote first (fast path for user feedback)
const existing = await db.sql`
SELECT id FROM coupon_votes WHERE coupon_id = ${id} AND voter_did = ${did}
`;
if (existing.length > 0) {
return NextResponse.json({ error: 'already_voted' }, { status: 409 });
}

await db.sql`INSERT INTO coupon_votes (coupon_id, voter_did) VALUES (${id}, ${did})`;
// Atomic insert — UNIQUE(coupon_id, voter_did) constraint prevents
// duplicates from concurrent requests; OR IGNORE handles the race
// gracefully instead of throwing a constraint violation error
await db.sql`INSERT OR IGNORE INTO coupon_votes (coupon_id, voter_did) VALUES (${id}, ${did})`;
await db.sql`UPDATE coupons SET votes = votes + 1 WHERE id = ${id}`;

const rows = await db.sql`SELECT votes FROM coupons WHERE id = ${id}`;
Expand Down
Loading