@@ -3,12 +3,10 @@ import {
33 PrismaClient ,
44 boundedIn ,
55 $transaction as transac ,
6- TokenBucketRetryBudget ,
76 type PrismaClientOrTransaction ,
87 type PrismaReplicaClient ,
98 type PrismaTransactionClient ,
109 type PrismaTransactionOptions ,
11- type TransactionStartRetryConfig ,
1210} from "@trigger.dev/database" ;
1311import { RunOpsPrismaClient } from "@internal/run-ops-database" ;
1412import { markReadReplicaClient } from "@internal/run-store" ;
@@ -34,6 +32,12 @@ import {
3432import { computeRunOpsSplitReadEnabled } from "./v3/runOpsMigration/runOpsSplitReadGate" ;
3533import { assertControlPlaneCoresidencyAdvisory } from "./v3/runOpsMigration/controlPlaneCoresidencySentinel.server" ;
3634import { DATASOURCE_CONTEXT_KEY , startActiveSpan } from "./v3/tracer.server" ;
35+ import {
36+ controlPlaneTransactionResilience ,
37+ runOpsLegacyTransactionResilience ,
38+ runOpsTransactionResilience ,
39+ type TransactionResilienceConfig ,
40+ } from "./v3/transactionResilience.server" ;
3741import type { Span } from "@opentelemetry/api" ;
3842import { context , trace } from "@opentelemetry/api" ;
3943import { queryPerformanceMonitor } from "./utils/queryPerformanceMonitor.server" ;
@@ -61,74 +65,6 @@ function logTransactionPrismaError(error: Prisma.PrismaClientKnownRequestError)
6165 } ) ;
6266}
6367
64- /**
65- * Resolved transaction-resilience config for one writer pool. Each pool gets its own
66- * {@link TransactionStartRetryConfig} (with its OWN token bucket, so a storm on one pool cannot
67- * drain another's retry budget) plus the `maxWait` applied when that pool opens a transaction.
68- * Env is read here at the app boundary (IoC); the library never reads env.
69- */
70- export type TransactionResilienceConfig = {
71- maxWait : number ;
72- startRetry : TransactionStartRetryConfig ;
73- } ;
74-
75- function resolveTransactionResilience (
76- pool : "control-plane" | "run-ops" | "run-ops-legacy" ,
77- overrides : {
78- maxWaitMs ?: number ;
79- enabled ?: boolean ;
80- maxAttempts ?: number ;
81- backoffMinMs ?: number ;
82- backoffMaxMs ?: number ;
83- budgetPerSec ?: number ;
84- budgetBurst ?: number ;
85- }
86- ) : TransactionResilienceConfig {
87- const budgetPerSec =
88- overrides . budgetPerSec ?? env . DATABASE_TRANSACTION_START_RETRY_BUDGET_PER_SEC ;
89- const budgetBurst = overrides . budgetBurst ?? env . DATABASE_TRANSACTION_START_RETRY_BUDGET_BURST ;
90- return {
91- maxWait : Math . max ( 0 , overrides . maxWaitMs ?? env . DATABASE_TRANSACTION_MAX_WAIT_MS ) ,
92- startRetry : {
93- options : {
94- enabled : overrides . enabled ?? env . DATABASE_TRANSACTION_START_RETRY_ENABLED ,
95- maxAttempts : overrides . maxAttempts ?? env . DATABASE_TRANSACTION_START_RETRY_MAX_ATTEMPTS ,
96- backoffMinMs : overrides . backoffMinMs ?? env . DATABASE_TRANSACTION_START_RETRY_BACKOFF_MIN_MS ,
97- backoffMaxMs : overrides . backoffMaxMs ?? env . DATABASE_TRANSACTION_START_RETRY_BACKOFF_MAX_MS ,
98- } ,
99- budget : new TokenBucketRetryBudget ( { ratePerSec : budgetPerSec , burst : budgetBurst } ) ,
100- onRetry : ( { attempt, delayMs } ) =>
101- logger . warn ( "retrying transaction start after acquisition failure" , {
102- pool,
103- attempt,
104- delayMs,
105- } ) ,
106- } ,
107- } ;
108- }
109-
110- export const controlPlaneTransactionResilience = resolveTransactionResilience ( "control-plane" , { } ) ;
111-
112- export const runOpsTransactionResilience = resolveTransactionResilience ( "run-ops" , {
113- maxWaitMs : env . RUN_OPS_DATABASE_TRANSACTION_MAX_WAIT_MS ,
114- enabled : env . RUN_OPS_DATABASE_TRANSACTION_START_RETRY_ENABLED ,
115- maxAttempts : env . RUN_OPS_DATABASE_TRANSACTION_START_RETRY_MAX_ATTEMPTS ,
116- backoffMinMs : env . RUN_OPS_DATABASE_TRANSACTION_START_RETRY_BACKOFF_MIN_MS ,
117- backoffMaxMs : env . RUN_OPS_DATABASE_TRANSACTION_START_RETRY_BACKOFF_MAX_MS ,
118- budgetPerSec : env . RUN_OPS_DATABASE_TRANSACTION_START_RETRY_BUDGET_PER_SEC ,
119- budgetBurst : env . RUN_OPS_DATABASE_TRANSACTION_START_RETRY_BUDGET_BURST ,
120- } ) ;
121-
122- export const runOpsLegacyTransactionResilience = resolveTransactionResilience ( "run-ops-legacy" , {
123- maxWaitMs : env . RUN_OPS_LEGACY_DATABASE_TRANSACTION_MAX_WAIT_MS ,
124- enabled : env . RUN_OPS_LEGACY_DATABASE_TRANSACTION_START_RETRY_ENABLED ,
125- maxAttempts : env . RUN_OPS_LEGACY_DATABASE_TRANSACTION_START_RETRY_MAX_ATTEMPTS ,
126- backoffMinMs : env . RUN_OPS_LEGACY_DATABASE_TRANSACTION_START_RETRY_BACKOFF_MIN_MS ,
127- backoffMaxMs : env . RUN_OPS_LEGACY_DATABASE_TRANSACTION_START_RETRY_BACKOFF_MAX_MS ,
128- budgetPerSec : env . RUN_OPS_LEGACY_DATABASE_TRANSACTION_START_RETRY_BUDGET_PER_SEC ,
129- budgetBurst : env . RUN_OPS_LEGACY_DATABASE_TRANSACTION_START_RETRY_BUDGET_BURST ,
130- } ) ;
131-
13268const transactionResilienceByClient = new WeakMap < object , TransactionResilienceConfig > ( ) ;
13369
13470/**
0 commit comments