Skip to content

Commit 451773f

Browse files
committed
refactor(webapp): route the $transaction helper to the passed client's pool resilience
1 parent 99fac30 commit 451773f

1 file changed

Lines changed: 55 additions & 26 deletions

File tree

apps/webapp/app/db.server.ts

Lines changed: 55 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,31 @@ export const runOpsLegacyTransactionResilience = resolveTransactionResilience("r
129129
budgetBurst: env.RUN_OPS_LEGACY_DATABASE_TRANSACTION_START_RETRY_BUDGET_BURST,
130130
});
131131

132-
function withTransactionDefaults(options?: PrismaTransactionOptions): PrismaTransactionOptions {
132+
const transactionResilienceByClient = new WeakMap<object, TransactionResilienceConfig>();
133+
134+
/**
135+
* Associates a writer client with its pool's resilience config so the `$transaction` helper can
136+
* pick the right `maxWait` + retry budget for whichever client it is handed, rather than always
137+
* using the control-plane pool. Returns the client for inline use at construction.
138+
*/
139+
function registerTransactionResilience<T extends object>(
140+
client: T,
141+
resilience: TransactionResilienceConfig
142+
): T {
143+
transactionResilienceByClient.set(client, resilience);
144+
return client;
145+
}
146+
147+
function withTransactionDefaults(
148+
client: PrismaClientOrTransaction,
149+
options?: PrismaTransactionOptions
150+
): PrismaTransactionOptions {
151+
const resilience =
152+
transactionResilienceByClient.get(client as object) ?? controlPlaneTransactionResilience;
133153
return {
134-
maxWait: controlPlaneTransactionResilience.maxWait,
154+
maxWait: resilience.maxWait,
135155
...options,
136-
startRetry: options?.startRetry ?? controlPlaneTransactionResilience.startRetry,
156+
startRetry: options?.startRetry ?? resilience.startRetry,
137157
};
138158
}
139159

@@ -171,7 +191,7 @@ async function $transactionInner<R>(
171191
options?: PrismaTransactionOptions
172192
): Promise<R | undefined> {
173193
if (typeof fnOrName === "string") {
174-
const effectiveOptions = withTransactionDefaults(options);
194+
const effectiveOptions = withTransactionDefaults(prisma, options);
175195
return await startActiveSpan(fnOrName, async (span) => {
176196
span.setAttribute("$transaction", true);
177197

@@ -205,7 +225,7 @@ async function $transactionInner<R>(
205225
prisma,
206226
fnOrName,
207227
logTransactionPrismaError,
208-
withTransactionDefaults(typeof fnOrOptions === "function" ? undefined : fnOrOptions)
228+
withTransactionDefaults(prisma, typeof fnOrOptions === "function" ? undefined : fnOrOptions)
209229
);
210230
}
211231
}
@@ -264,7 +284,10 @@ function captureInfraErrorsRunOps(client: RunOpsPrismaClient): RunOpsPrismaClien
264284
}
265285

266286
export const prisma = singleton("prisma", () =>
267-
captureInfrastructureErrors(tagDatasource("control-plane-writer", getClient()))
287+
registerTransactionResilience(
288+
captureInfrastructureErrors(tagDatasource("control-plane-writer", getClient())),
289+
controlPlaneTransactionResilience
290+
)
268291
);
269292

270293
export const $replica: PrismaReplicaClient = singleton("replica", () => {
@@ -393,15 +416,18 @@ const runOpsTopology: RunOpsTopology = singleton("runOpsTopology", () => {
393416
{
394417
controlPlane: { writer: prisma, replica: $replica },
395418
buildNewWriter: (url, clientType) =>
396-
captureInfraErrorsRunOps(
397-
tagDatasourceRunOps(
398-
"run-ops-writer",
399-
buildRunOpsWriterClient({
400-
url,
401-
clientType,
402-
useDriverAdapter: env.RUN_OPS_DATABASE_WRITER_DRIVER_ADAPTER === "1",
403-
})
404-
)
419+
registerTransactionResilience(
420+
captureInfraErrorsRunOps(
421+
tagDatasourceRunOps(
422+
"run-ops-writer",
423+
buildRunOpsWriterClient({
424+
url,
425+
clientType,
426+
useDriverAdapter: env.RUN_OPS_DATABASE_WRITER_DRIVER_ADAPTER === "1",
427+
})
428+
)
429+
),
430+
runOpsTransactionResilience
405431
),
406432
// Brand the run-ops replica (only built for a real replica URL) so routed replica reads stay
407433
// off the primary. When no replica URL is set, selectRunOpsTopology reuses the writer here —
@@ -422,17 +448,20 @@ const runOpsTopology: RunOpsTopology = singleton("runOpsTopology", () => {
422448
// Legacy client shares the exact control-plane wrapper stack (the legacy DB carries the full
423449
// control-plane schema); markReadReplicaClient only on a real replica URL, as with the NEW replica.
424450
buildLegacyWriter: (url, clientType) =>
425-
captureInfrastructureErrors(
426-
tagDatasource(
427-
"legacy-run-ops-writer",
428-
buildWriterClient({
429-
url,
430-
clientType,
431-
poolTimeout: env.RUN_OPS_LEGACY_DATABASE_WRITER_POOL_TIMEOUT,
432-
connectTimeout: env.RUN_OPS_LEGACY_DATABASE_WRITER_CONNECTION_TIMEOUT,
433-
useDriverAdapter: env.RUN_OPS_LEGACY_DATABASE_WRITER_DRIVER_ADAPTER === "1",
434-
})
435-
)
451+
registerTransactionResilience(
452+
captureInfrastructureErrors(
453+
tagDatasource(
454+
"legacy-run-ops-writer",
455+
buildWriterClient({
456+
url,
457+
clientType,
458+
poolTimeout: env.RUN_OPS_LEGACY_DATABASE_WRITER_POOL_TIMEOUT,
459+
connectTimeout: env.RUN_OPS_LEGACY_DATABASE_WRITER_CONNECTION_TIMEOUT,
460+
useDriverAdapter: env.RUN_OPS_LEGACY_DATABASE_WRITER_DRIVER_ADAPTER === "1",
461+
})
462+
)
463+
),
464+
runOpsLegacyTransactionResilience
436465
),
437466
buildLegacyReplica: (url, clientType) =>
438467
markReadReplicaClient(

0 commit comments

Comments
 (0)