Transaktionen: Wartezeit 10 s und Zeitlimit 20 s statt Prisma-Standard

Unter paralleler Last scheiterten Tests sporadisch mit „Unable to start a transaction in the given time“.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 19:14:31 +02:00
co-authored by Claude Opus 5
parent 969bc4e12c
commit c3712598c1
+9 -3
View File
@@ -406,7 +406,7 @@ export function dbForTenant(tenantId: string) {
args,
(a) => delegate[operation](a),
);
});
}, TX_DEFAULTS);
},
},
},
@@ -415,6 +415,12 @@ export function dbForTenant(tenantId: string) {
export type TenantDb = ReturnType<typeof dbForTenant>;
/**
* Interactive transaction limits. Prisma defaults (maxWait 2 s, timeout 5 s) fail under parallel load
* (pool exhausted while notifications/mails run inside a transaction) → wider but still bounded.
*/
const TX_DEFAULTS = { maxWait: 10_000, timeout: 20_000 } as const;
/**
* Run `fn` atomically for one tenant. ALWAYS use this (or `inTransaction` in services)
* instead of `db.$transaction(...)` for multi-step writes — atomic in both modes:
@@ -431,7 +437,7 @@ export async function tenantTransaction<T>(
): Promise<T> {
if (!RLS_ENFORCED) {
if (isTransactionClient(db)) return fn(db);
return db.$transaction((tx) => fn(tx as unknown as TenantDb), options) as Promise<T>;
return db.$transaction((tx) => fn(tx as unknown as TenantDb), { ...TX_DEFAULTS, ...options }) as Promise<T>;
}
const active = tenantTx.getStore();
if (active) {
@@ -441,7 +447,7 @@ export async function tenantTransaction<T>(
return appBase!.$transaction(async (tx) => {
await tx.$executeRaw`SELECT set_config('app.tenant_id', ${tenantId}, true)`;
return tenantTx.run({ tenantId, tx }, () => fn(db));
}, options);
}, { ...TX_DEFAULTS, ...options });
}
/** Interactive transaction clients have no $transaction method. */