From 167d0d3857d7060ba3cc33f4953d4b893578b886 Mon Sep 17 00:00:00 2001 From: Eric Allam Date: Wed, 22 Apr 2026 09:47:55 +0100 Subject: [PATCH] feat(run-engine): flag to route getSnapshotsSince through read replica --- .server-changes/read-replica-snapshots-since.md | 6 ++++++ apps/webapp/app/env.server.ts | 1 + apps/webapp/app/v3/runEngine.server.ts | 2 ++ internal-packages/run-engine/src/engine/index.ts | 3 ++- internal-packages/run-engine/src/engine/types.ts | 4 ++++ 5 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 .server-changes/read-replica-snapshots-since.md diff --git a/.server-changes/read-replica-snapshots-since.md b/.server-changes/read-replica-snapshots-since.md new file mode 100644 index 00000000000..24f4f070c7d --- /dev/null +++ b/.server-changes/read-replica-snapshots-since.md @@ -0,0 +1,6 @@ +--- +area: webapp +type: improvement +--- + +Add `RUN_ENGINE_READ_REPLICA_SNAPSHOTS_SINCE_ENABLED` flag (default off) to route the Prisma reads inside `RunEngine.getSnapshotsSince` through the read-only replica client. Offloads the snapshot polling queries (fired by every running task runner) from the primary. When disabled, behavior is unchanged. diff --git a/apps/webapp/app/env.server.ts b/apps/webapp/app/env.server.ts index b839af6eb5d..ba40624058f 100644 --- a/apps/webapp/app/env.server.ts +++ b/apps/webapp/app/env.server.ts @@ -835,6 +835,7 @@ const EnvironmentSchema = z .enum(["log", "error", "warn", "info", "debug"]) .default("info"), RUN_ENGINE_TREAT_PRODUCTION_EXECUTION_STALLS_AS_OOM: z.string().default("0"), + RUN_ENGINE_READ_REPLICA_SNAPSHOTS_SINCE_ENABLED: z.string().default("0"), /** How long should the presence ttl last */ DEV_PRESENCE_SSE_TIMEOUT: z.coerce.number().int().default(30_000), diff --git a/apps/webapp/app/v3/runEngine.server.ts b/apps/webapp/app/v3/runEngine.server.ts index b55bc352a24..8db60aed1ac 100644 --- a/apps/webapp/app/v3/runEngine.server.ts +++ b/apps/webapp/app/v3/runEngine.server.ts @@ -19,6 +19,8 @@ function createRunEngine() { logLevel: env.RUN_ENGINE_WORKER_LOG_LEVEL, treatProductionExecutionStallsAsOOM: env.RUN_ENGINE_TREAT_PRODUCTION_EXECUTION_STALLS_AS_OOM === "1", + readReplicaSnapshotsSinceEnabled: + env.RUN_ENGINE_READ_REPLICA_SNAPSHOTS_SINCE_ENABLED === "1", worker: { disabled: env.RUN_ENGINE_WORKER_ENABLED === "0", workers: env.RUN_ENGINE_WORKER_COUNT, diff --git a/internal-packages/run-engine/src/engine/index.ts b/internal-packages/run-engine/src/engine/index.ts index b3e85b7839f..92cf7365a9c 100644 --- a/internal-packages/run-engine/src/engine/index.ts +++ b/internal-packages/run-engine/src/engine/index.ts @@ -1633,7 +1633,8 @@ export class RunEngine { snapshotId: string; tx?: PrismaClientOrTransaction; }): Promise { - const prisma = tx ?? this.prisma; + const prisma = + tx ?? (this.options.readReplicaSnapshotsSinceEnabled ? this.readOnlyPrisma : this.prisma); try { const snapshots = await getExecutionSnapshotsSince(prisma, runId, snapshotId); diff --git a/internal-packages/run-engine/src/engine/types.ts b/internal-packages/run-engine/src/engine/types.ts index cd90e0b8ac4..255643ef2f5 100644 --- a/internal-packages/run-engine/src/engine/types.ts +++ b/internal-packages/run-engine/src/engine/types.ts @@ -145,6 +145,10 @@ export type RunEngineOptions = { /** Optional maximum TTL for all runs (e.g. "14d"). If set, runs without an explicit TTL * will use this as their TTL, and runs with a TTL larger than this will be clamped. */ defaultMaxTtl?: string; + /** When true, `getSnapshotsSince` reads through the read-only replica client instead + * of the primary. Defaults to false. Callers passing an explicit `tx` always use + * that client regardless of this flag. */ + readReplicaSnapshotsSinceEnabled?: boolean; tracer: Tracer; meter?: Meter; logger?: Logger;