/** * Transaktions-Helper: SERIALIZABLE mit Retry bei Serialisierungs- * konflikten (Prisma-Fehlercode P2034). * * Postgres bricht bei Parallelitaets-Anomalien unter SERIALIZABLE eine * der beteiligten Transaktionen ab. Wiederholbare Operationen (z. B. * Registrierung mit Invite-Verbrauch, Rollen-Aenderung) werden dann * einfach erneut ausgefuehrt - der Konflikt loest sich auf, weil die * andere Transaktion inzwischen committet hat. */ import { Prisma } from '@prisma/client'; import { prisma } from '@/lib/db/client'; /** Ist es ein wiederholbarer Serialisierungs-Konflikt? */ function isSerializationError(error: unknown): boolean { return ( error instanceof Prisma.PrismaClientKnownRequestError && error.code === 'P2034' ); } /** * Fuehrt die Operation in einer SERIALIZABLE-Transaktion aus und * wiederholt sie bei Serialisierungs-Konflikten (max. 3 Nachlaeufe). */ export async function withSerializableTx( operation: (tx: Prisma.TransactionClient) => Promise, maxRetries = 3, ): Promise { for (let attempt = 0; ; attempt++) { try { return await prisma.$transaction(operation, { isolationLevel: 'Serializable', }); } catch (error) { if (attempt >= maxRetries || !isSerializationError(error)) { throw error; } // Naechster Versuch: Die abgebrochene Transaktion hat nichts // committet, ein erneuter Lauf sieht den aktuellen Stand. } } }