From 341483de3f4ae690f22c16d48cffef5fd90297f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Thu, 21 May 2026 11:19:04 +0200 Subject: [PATCH] fix(medications): swallow concurrent-projection duplicates in intake backfill PR #191 added a today-window backfill to /api/medications/intake. The v1.4.39.4 dashboard symmetry fix wires the exact same projection into /api/dashboard/summary, which means two parallel routes can now race the same (userId, medicationId, scheduledFor, REMINDER) row between their existence probes and createMany calls. The @@unique on (userId, medicationId, scheduledFor, source) is the structural backstop; without skipDuplicates: true the loser of that race would surface a constraint violation as a 5xx. Pair the createMany with skipDuplicates: true so Postgres swallows the rejected rows and both routes still return 2xx. Matches the same flag the dashboard route ships with. --- src/app/api/medications/intake/route.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/app/api/medications/intake/route.ts b/src/app/api/medications/intake/route.ts index ac2d53eb8..73dc12607 100644 --- a/src/app/api/medications/intake/route.ts +++ b/src/app/api/medications/intake/route.ts @@ -146,6 +146,15 @@ export const GET = apiHandler(async (request: NextRequest) => { // keeps the doctor-report + analytics filters byte-stable. source: "REMINDER", })), + // v1.4.39 W-SERVER-FIX-2 — paired with the schema-level + // @@unique([userId, medicationId, scheduledFor, source]). A + // concurrent dashboard-summary hit (the second route that now + // runs the same projection) can race a duplicate row in + // between this route's existence probe and createMany; the + // flag tells Postgres to swallow the rejected rows so the + // request still returns 2xx. The unique constraint is the + // structural backstop, this is the defense-in-depth. + skipDuplicates: true, }); }