fix(ST-511): add createWithCodeRetry helper to handle P2002 race on auto codes
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d48227ba23
commit
c62de4c0d0
1 changed files with 38 additions and 0 deletions
|
|
@ -1,5 +1,43 @@
|
|||
import { Prisma } from '@prisma/client'
|
||||
import { prisma } from '@/lib/prisma'
|
||||
|
||||
const MAX_AUTO_CODE_ATTEMPTS = 3
|
||||
|
||||
function isCodeUniqueConflict(error: unknown): boolean {
|
||||
if (!(error instanceof Prisma.PrismaClientKnownRequestError)) return false
|
||||
if (error.code !== 'P2002') return false
|
||||
const target = (error.meta as { target?: string[] | string } | undefined)?.target
|
||||
if (!target) return false
|
||||
if (Array.isArray(target)) return target.includes('code')
|
||||
return target.includes('code')
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an auto code, then run the create. If the insert collides with an
|
||||
* existing code (P2002 on the code column), regenerate and retry up to a small
|
||||
* number of attempts. Protects against the SELECT-MAX → INSERT race when two
|
||||
* concurrent requests pick the same next number.
|
||||
*/
|
||||
export async function createWithCodeRetry<T>(
|
||||
generate: () => Promise<string>,
|
||||
create: (code: string) => Promise<T>,
|
||||
): Promise<T> {
|
||||
let lastError: unknown
|
||||
for (let attempt = 0; attempt < MAX_AUTO_CODE_ATTEMPTS; attempt++) {
|
||||
const code = await generate()
|
||||
try {
|
||||
return await create(code)
|
||||
} catch (e) {
|
||||
if (isCodeUniqueConflict(e)) {
|
||||
lastError = e
|
||||
continue
|
||||
}
|
||||
throw e
|
||||
}
|
||||
}
|
||||
throw lastError ?? new Error('Kon geen unieke code genereren')
|
||||
}
|
||||
|
||||
const STORY_AUTO_RE = /^ST-(\d+)$/
|
||||
const PBI_AUTO_RE = /^PBI-(\d+)$/
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue