Skip to content

Commit 7a0a73e

Browse files
d-csTrigger.dev RepoOps
authored andcommitted
feat(run-store, webapp): wire server-only execution snapshot rollout
Enables gradual execution snapshot storage rollout without requiring changes to task SDKs or worker requests. Running tasks retain their original snapshot storage location. Mono-RevId: 9bb14e5ab2496009717a14b6081db5e12f160595
1 parent 5f359a4 commit 7a0a73e

110 files changed

Lines changed: 2610 additions & 2294 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎apps/supervisor/src/index.ts‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -742,8 +742,6 @@ class ManagedSupervisor {
742742
nextAttemptNumber: message.run.attemptNumber,
743743
snapshotId: message.snapshot.id,
744744
snapshotFriendlyId: message.snapshot.friendlyId,
745-
// Carry the run's storage route to the runner pod so its start request echoes it back.
746-
snapshotRoute: message.snapshotRoute,
747745
placementTags: message.placementTags,
748746
traceContext: message.run.traceContext,
749747
annotations: message.run.annotations,
@@ -767,7 +765,6 @@ class ManagedSupervisor {
767765
{
768766
runFriendlyId: message.run.friendlyId,
769767
snapshotFriendlyId: message.snapshot.friendlyId,
770-
snapshotRoute: message.snapshotRoute,
771768
},
772769
restore
773770
);
@@ -811,7 +808,6 @@ class ManagedSupervisor {
811808
private async reportRestoreFailure({
812809
runFriendlyId,
813810
snapshotFriendlyId,
814-
snapshotRoute,
815811
runnerId,
816812
outcome,
817813
}: RestoreFailure) {
@@ -830,7 +826,7 @@ class ManagedSupervisor {
830826
return;
831827
}
832828
const settled = await settleRestoreFailure(
833-
{ runnerId, outcome, snapshotRoute },
829+
{ runnerId, outcome },
834830
{
835831
deleteRunner: (name, uid) => manager.deleteRestoreRunner(name, uid),
836832
report: (body) =>

‎apps/supervisor/src/services/restoreWatcher.test.ts‎

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,6 @@ import { Registry } from "prom-client";
33
import type { RestoreWatchResult } from "../workloadManager/runCrd.js";
44
import { RestoreWatcher, type RestoreFailure } from "./restoreWatcher.js";
55

6-
const route = (organizationId: string) => ({
7-
version: 1 as const,
8-
residency: "mirrored" as const,
9-
organizationId,
10-
});
11-
126
const failed: RestoreWatchResult = {
137
ok: false,
148
reason: "StartError",
@@ -38,11 +32,10 @@ function setup(opts: { reportFailure?: (failure: RestoreFailure) => Promise<void
3832
const target = {
3933
runFriendlyId: "run_a",
4034
snapshotFriendlyId: "snapshot_1",
41-
snapshotRoute: route("org_1"),
4235
};
4336

4437
describe("RestoreWatcher", () => {
45-
it("reports a failed restore with the dequeued snapshot and its route", async () => {
38+
it("reports a failed restore with the dequeued snapshot", async () => {
4639
const { watcher, outcomes, reportFailure } = setup();
4740

4841
const watched = watcher.watch(target, { runnerId: "runner-a", uid: "uid-a" });
@@ -52,42 +45,28 @@ describe("RestoreWatcher", () => {
5245
expect(reportFailure).toHaveBeenCalledWith({
5346
runFriendlyId: "run_a",
5447
snapshotFriendlyId: "snapshot_1",
55-
snapshotRoute: route("org_1"),
5648
runnerId: "runner-a",
5749
outcome: failed,
5850
});
5951
});
6052

61-
it("names the snapshot and route dequeued last when the restore is redelivered", async () => {
53+
it("names the snapshot dequeued last when the restore is redelivered", async () => {
6254
const { watcher, outcomes, awaitRestore, reportFailure } = setup();
6355

6456
const watched = watcher.watch(target, { runnerId: "runner-a", uid: "uid-a" });
6557
await watcher.watch(
66-
{ runFriendlyId: "run_a", snapshotFriendlyId: "snapshot_2", snapshotRoute: route("org_2") },
58+
{ runFriendlyId: "run_a", snapshotFriendlyId: "snapshot_2" },
6759
{ runnerId: "runner-a", uid: "uid-a" }
6860
);
6961
outcomes[0]!.resolve(failed);
7062
await watched;
7163

7264
expect(awaitRestore).toHaveBeenCalledTimes(1);
7365
expect(reportFailure).toHaveBeenCalledWith(
74-
expect.objectContaining({ snapshotFriendlyId: "snapshot_2", snapshotRoute: route("org_2") })
66+
expect.objectContaining({ snapshotFriendlyId: "snapshot_2" })
7567
);
7668
});
7769

78-
it("reports a restore adopted after a restart without a route", async () => {
79-
const { watcher, outcomes, reportFailure } = setup();
80-
81-
const watched = watcher.watch(
82-
{ runFriendlyId: "run_a", snapshotFriendlyId: "snapshot_1" },
83-
{ runnerId: "runner-a", uid: "uid-a" }
84-
);
85-
outcomes[0]!.resolve(failed);
86-
await watched;
87-
88-
expect(reportFailure.mock.calls[0]![0].snapshotRoute).toBeUndefined();
89-
});
90-
9170
it("reports nothing for a watch the shutdown ended, whatever it resolved with", async () => {
9271
const { watcher, outcomes, reportFailure } = setup();
9372

‎apps/supervisor/src/services/restoreWatcher.ts‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import type { SnapshotRouteWire } from "@trigger.dev/core/v3";
21
import { SimpleStructuredLogger } from "@trigger.dev/core/v3/utils/structuredLogger";
32
import { Counter, Gauge, Histogram, type Registry } from "prom-client";
43
import {
@@ -12,14 +11,12 @@ import {
1211
type RestoreWatchTarget = {
1312
runFriendlyId: string;
1413
snapshotFriendlyId: string;
15-
snapshotRoute?: SnapshotRouteWire;
1614
};
1715

1816
/** A failed restore, with what the watch or the Runner knew of its run. */
1917
export type RestoreFailure = {
2018
runFriendlyId?: string;
2119
snapshotFriendlyId?: string;
22-
snapshotRoute?: SnapshotRouteWire;
2320
runnerId: string;
2421
outcome: RestoreWatchResult & { ok: false };
2522
};
@@ -93,7 +90,6 @@ export class RestoreWatcher {
9390
const watched = this.watches.get(runnerId);
9491
if (watched && (watched.uid === undefined || uid === undefined || watched.uid === uid)) {
9592
watched.snapshotFriendlyId = target.snapshotFriendlyId;
96-
watched.snapshotRoute = target.snapshotRoute;
9793
return;
9894
}
9995
// The redelivery replaced the Runner, so the watch on the old one has nothing left to say.
@@ -140,7 +136,6 @@ export class RestoreWatcher {
140136
await this.report({
141137
runFriendlyId,
142138
snapshotFriendlyId: entry.snapshotFriendlyId,
143-
snapshotRoute: entry.snapshotRoute,
144139
runnerId,
145140
outcome,
146141
});

‎apps/supervisor/src/workloadManager/compute.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,6 @@ export class ComputeWorkloadManager implements WorkloadManager {
157157
TRIGGER_DEPLOYMENT_VERSION: opts.deploymentVersion,
158158
TRIGGER_RUN_ID: opts.runFriendlyId,
159159
TRIGGER_SNAPSHOT_ID: opts.snapshotFriendlyId,
160-
...(opts.snapshotRoute ? { TRIGGER_SNAPSHOT_ROUTE: JSON.stringify(opts.snapshotRoute) } : {}),
161160
TRIGGER_SUPERVISOR_API_PROTOCOL: this.opts.workloadApiProtocol,
162161
TRIGGER_SUPERVISOR_API_PORT: String(this.opts.workloadApiPort),
163162
TRIGGER_SUPERVISOR_API_DOMAIN: this.opts.workloadApiDomain ?? "",

‎apps/supervisor/src/workloadManager/docker.ts‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,6 @@ export class DockerWorkloadManager implements WorkloadManager {
7878
`TRIGGER_DEPLOYMENT_VERSION=${opts.deploymentVersion}`,
7979
`TRIGGER_RUN_ID=${opts.runFriendlyId}`,
8080
`TRIGGER_SNAPSHOT_ID=${opts.snapshotFriendlyId}`,
81-
...(opts.snapshotRoute
82-
? [`TRIGGER_SNAPSHOT_ROUTE=${JSON.stringify(opts.snapshotRoute)}`]
83-
: []),
8481
`TRIGGER_SUPERVISOR_API_PROTOCOL=${this.opts.workloadApiProtocol}`,
8582
`TRIGGER_SUPERVISOR_API_PORT=${this.opts.workloadApiPort}`,
8683
`TRIGGER_SUPERVISOR_API_DOMAIN=${this.opts.workloadApiDomain ?? getDockerHostDomain()}`,

‎apps/supervisor/src/workloadManager/kubernetes.ts‎

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -215,14 +215,6 @@ export class KubernetesWorkloadManager implements WorkloadManager {
215215
name: "TRIGGER_SNAPSHOT_ID",
216216
value: opts.snapshotFriendlyId,
217217
},
218-
...(opts.snapshotRoute
219-
? [
220-
{
221-
name: "TRIGGER_SNAPSHOT_ROUTE",
222-
value: JSON.stringify(opts.snapshotRoute),
223-
},
224-
]
225-
: []),
226218
{
227219
name: "TRIGGER_SUPERVISOR_API_PROTOCOL",
228220
value: this.opts.workloadApiProtocol,

‎apps/supervisor/src/workloadManager/runCrd.test.ts‎

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,6 @@ describe("run-crd carries every shared create-option or excludes it on purpose",
401401
"runFriendlyId",
402402
"snapshotId",
403403
"snapshotFriendlyId",
404-
"snapshotRoute",
405404
"traceContext",
406405
"annotations",
407406
"hasPrivateLink",
@@ -417,8 +416,6 @@ describe("run-crd carries every shared create-option or excludes it on purpose",
417416
* creation by another route, such as the runner's name or its token Secret.
418417
*/
419418
const RUN_CRD_EXCLUDED: Partial<Record<ListedKey, string>> = {
420-
snapshotRoute:
421-
"Superseded transport, not a run-crd gap: snapshot routing is becoming server-owned (a run's residency is decided from its stored state, not a runner-provided field), so the runner-facing route is being removed rather than built into the Runner. This entry, the field, and the pod backends that set it come out together when that lands.",
422419
nextAttemptNumber:
423420
"Not a spec field: it selects the runner's name via getRunnerId, so the attempt lives in the object's name rather than in the spec runnerBodyFor builds.",
424421
deploymentToken:
@@ -459,9 +456,6 @@ describe("run-crd carries every shared create-option or excludes it on purpose",
459456
runFriendlyId: { runFriendlyId: "run_other" },
460457
snapshotId: { snapshotId: "snapshot_other_internal" },
461458
snapshotFriendlyId: { snapshotFriendlyId: "snapshot_other" },
462-
snapshotRoute: {
463-
snapshotRoute: { version: 1, residency: "redis-primary", organizationId: "org_abc" },
464-
},
465459
traceContext: { traceContext: { traceparent: "00-probe-probe-01" } },
466460
annotations: {
467461
annotations: {
@@ -1685,21 +1679,6 @@ describe("settleRestoreFailure", () => {
16851679
});
16861680
});
16871681

1688-
it("sends the dequeued run's snapshot route with the report", async () => {
1689-
const d = deps();
1690-
const snapshotRoute = {
1691-
version: 1 as const,
1692-
residency: "mirrored" as const,
1693-
organizationId: "org_1",
1694-
};
1695-
1696-
await settleRestoreFailure({ ...failure("SnapshotNodeGone"), snapshotRoute }, d);
1697-
1698-
expect(d.report).toHaveBeenCalledWith(
1699-
expect.objectContaining({ outcome: "fail", snapshotRoute })
1700-
);
1701-
});
1702-
17031682
// The Runner may be running a guest the watch never saw start.
17041683
it("neither deletes nor reports a Runner the watch timed out on", async () => {
17051684
const d = deps();

‎apps/supervisor/src/workloadManager/runCrd.ts‎

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,7 @@ import {
88
type ObjectCache,
99
} from "@kubernetes/client-node";
1010
import { SimpleStructuredLogger } from "@trigger.dev/core/v3/utils/structuredLogger";
11-
import type {
12-
CheckpointType,
13-
EnvironmentType,
14-
MachinePreset,
15-
SnapshotRouteWire,
16-
} from "@trigger.dev/core/v3";
11+
import type { CheckpointType, EnvironmentType, MachinePreset } from "@trigger.dev/core/v3";
1712
import { type K8sApi, createK8sApi } from "../clients/kubernetes.js";
1813
import { ReconnectingInformer } from "../clients/reconnectingInformer.js";
1914
import { getRestoreRunnerId, getRunnerId } from "../util.js";
@@ -1093,7 +1088,6 @@ export type RestoreOutcomeReport = (body: {
10931088
outcome: "requeue" | "fail";
10941089
reason: string;
10951090
message?: string;
1096-
snapshotRoute?: SnapshotRouteWire;
10971091
}) => Promise<{ success: true } | { success: false; error: string; statusCode?: number }>;
10981092

10991093
export type RestoreFailureSettlement =
@@ -1118,8 +1112,6 @@ export async function settleRestoreFailure(
11181112
failure: {
11191113
runnerId: string;
11201114
outcome: RestoreWatchResult & { ok: false };
1121-
/** The dequeued run's route, which spares the platform a read to find it. */
1122-
snapshotRoute?: SnapshotRouteWire;
11231115
},
11241116
deps: {
11251117
deleteRunner: (runnerId: string, uid: string) => Promise<void>;
@@ -1149,7 +1141,6 @@ export async function settleRestoreFailure(
11491141
outcome: action.outcome,
11501142
reason,
11511143
message: message ?? error,
1152-
...(failure.snapshotRoute ? { snapshotRoute: failure.snapshotRoute } : {}),
11531144
});
11541145
const settled: Extract<RestoreFailureSettlement, { action: "reported" }> = result.success
11551146
? { action: "reported", outcome: action.outcome, result: "ok" }

‎apps/supervisor/src/workloadManager/types.ts‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import type {
33
MachinePreset,
44
PlacementTag,
55
RunAnnotations,
6-
SnapshotRouteWire,
76
} from "@trigger.dev/core/v3";
87

98
export interface WorkloadManagerOptions {
@@ -51,8 +50,6 @@ export interface WorkloadManagerCreateOptions {
5150
runFriendlyId: string;
5251
snapshotId: string;
5352
snapshotFriendlyId: string;
54-
// The run's storage route, materialized as the TRIGGER_SNAPSHOT_ROUTE env var for a cold start.
55-
snapshotRoute?: SnapshotRouteWire;
5653
// Trace context for OTel span emission (W3C format: { traceparent: "00-...", tracestate?: "..." })
5754
traceContext?: Record<string, unknown>;
5855
annotations?: RunAnnotations;

‎apps/webapp/app/env.server.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1381,6 +1381,9 @@ const EnvironmentSchema = z
13811381
.string()
13821382
.default(process.env.REDIS_TLS_DISABLED ?? "false"),
13831383

1384+
// Infrastructure endpoint only. Modes and organization overrides are polled feature flags.
1385+
RUN_ENGINE_SNAPSHOT_STORE_REDIS_URL: z.string().optional(),
1386+
13841387
RUN_ENGINE_RUN_LOCK_REDIS_HOST: z
13851388
.string()
13861389
.optional()

0 commit comments

Comments
 (0)