Skip to content

Commit 060bbc1

Browse files
committed
pull out env override logic
1 parent d3d6c48 commit 060bbc1

File tree

3 files changed

+290
-127
lines changed

3 files changed

+290
-127
lines changed

packages/cli-v3/src/entryPoints/managed-run-controller.ts

Lines changed: 39 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { logger } from "../utilities/logger.js";
22
import { TaskRunProcess } from "../executions/taskRunProcess.js";
33
import { env as stdEnv } from "std-env";
4-
import { z } from "zod";
5-
import { randomUUID } from "crypto";
64
import { readJSONFile } from "../utilities/fileSystem.js";
75
import {
86
type CompleteRunAttemptResult,
@@ -26,57 +24,13 @@ import {
2624
import { assertExhaustive } from "../utilities/assertExhaustive.js";
2725
import { setTimeout as sleep } from "timers/promises";
2826
import { io, type Socket } from "socket.io-client";
29-
30-
const DateEnv = z
31-
.string()
32-
.transform((val) => new Date(parseInt(val, 10)))
33-
.pipe(z.date());
34-
35-
// All IDs are friendly IDs
36-
const Env = z.object({
37-
// Set at build time
38-
TRIGGER_CONTENT_HASH: z.string(),
39-
TRIGGER_DEPLOYMENT_ID: z.string(),
40-
TRIGGER_DEPLOYMENT_VERSION: z.string(),
41-
TRIGGER_PROJECT_ID: z.string(),
42-
TRIGGER_PROJECT_REF: z.string(),
43-
NODE_ENV: z.string().default("production"),
44-
NODE_EXTRA_CA_CERTS: z.string().optional(),
45-
46-
// Set at runtime
47-
TRIGGER_WORKLOAD_CONTROLLER_ID: z.string().default(`controller_${randomUUID()}`),
48-
TRIGGER_ENV_ID: z.string(),
49-
TRIGGER_RUN_ID: z.string().optional(), // This is only useful for cold starts
50-
TRIGGER_SNAPSHOT_ID: z.string().optional(), // This is only useful for cold starts
51-
OTEL_EXPORTER_OTLP_ENDPOINT: z.string().url(),
52-
TRIGGER_WARM_START_URL: z.string().optional(),
53-
TRIGGER_WARM_START_CONNECTION_TIMEOUT_MS: z.coerce.number().default(30_000),
54-
TRIGGER_WARM_START_KEEPALIVE_MS: z.coerce.number().default(300_000),
55-
TRIGGER_MACHINE_CPU: z.string().default("0"),
56-
TRIGGER_MACHINE_MEMORY: z.string().default("0"),
57-
TRIGGER_RUNNER_ID: z.string(),
58-
TRIGGER_METADATA_URL: z.string().optional(),
59-
TRIGGER_PRE_SUSPEND_WAIT_MS: z.coerce.number().default(200),
60-
61-
// Timeline metrics
62-
TRIGGER_POD_SCHEDULED_AT_MS: DateEnv,
63-
TRIGGER_DEQUEUED_AT_MS: DateEnv,
64-
65-
// May be overridden
66-
TRIGGER_SUPERVISOR_API_PROTOCOL: z.enum(["http", "https"]),
67-
TRIGGER_SUPERVISOR_API_DOMAIN: z.string(),
68-
TRIGGER_SUPERVISOR_API_PORT: z.coerce.number(),
69-
TRIGGER_WORKER_INSTANCE_NAME: z.string(),
70-
TRIGGER_HEARTBEAT_INTERVAL_SECONDS: z.coerce.number().default(30),
71-
TRIGGER_SNAPSHOT_POLL_INTERVAL_SECONDS: z.coerce.number().default(5),
72-
TRIGGER_SUCCESS_EXIT_CODE: z.coerce.number().default(0),
73-
TRIGGER_FAILURE_EXIT_CODE: z.coerce.number().default(1),
74-
});
75-
76-
const env = Env.parse(stdEnv);
27+
import { RunnerEnv } from "./managed/env.js";
28+
import { MetadataClient } from "./managed/overrides.js";
7729

7830
logger.loggerLevel = "debug";
7931

32+
const env = new RunnerEnv(stdEnv);
33+
8034
type ManagedRunControllerOptions = {
8135
workerManifest: WorkerManifest;
8236
};
@@ -90,40 +44,10 @@ type Snapshot = {
9044
friendlyId: string;
9145
};
9246

93-
type Metadata = {
94-
TRIGGER_SUPERVISOR_API_PROTOCOL: string | undefined;
95-
TRIGGER_SUPERVISOR_API_DOMAIN: string | undefined;
96-
TRIGGER_SUPERVISOR_API_PORT: number | undefined;
97-
TRIGGER_WORKER_INSTANCE_NAME: string | undefined;
98-
TRIGGER_HEARTBEAT_INTERVAL_SECONDS: number | undefined;
99-
TRIGGER_SNAPSHOT_POLL_INTERVAL_SECONDS: number | undefined;
100-
TRIGGER_SUCCESS_EXIT_CODE: number | undefined;
101-
TRIGGER_FAILURE_EXIT_CODE: number | undefined;
102-
TRIGGER_RUNNER_ID: string | undefined;
103-
};
104-
105-
class MetadataClient {
106-
private readonly url: URL;
107-
108-
constructor(url: string) {
109-
this.url = new URL(url);
110-
}
111-
112-
async getEnvOverrides(): Promise<Metadata | null> {
113-
try {
114-
const response = await fetch(new URL("/env", this.url));
115-
return response.json();
116-
} catch (error) {
117-
console.error("Failed to fetch metadata", { error });
118-
return null;
119-
}
120-
}
121-
}
122-
12347
class ManagedRunController {
12448
private taskRunProcess?: TaskRunProcess;
12549

126-
private workerManifest: WorkerManifest;
50+
private readonly workerManifest: WorkerManifest;
12751

12852
private readonly httpClient: WorkloadHttpClient;
12953
private readonly warmStartClient: WarmStartClient | undefined;
@@ -132,18 +56,35 @@ class ManagedRunController {
13256
private socket: Socket<WorkloadServerToClientEvents, WorkloadClientToServerEvents>;
13357

13458
private readonly runHeartbeat: HeartbeatService;
135-
private heartbeatIntervalSeconds: number;
136-
13759
private readonly snapshotPoller: HeartbeatService;
138-
private snapshotPollIntervalSeconds: number;
13960

140-
private workerApiUrl: string;
141-
private workerInstanceName: string;
61+
get heartbeatIntervalSeconds() {
62+
return env.TRIGGER_HEARTBEAT_INTERVAL_SECONDS;
63+
}
64+
65+
get snapshotPollIntervalSeconds() {
66+
return env.TRIGGER_SNAPSHOT_POLL_INTERVAL_SECONDS;
67+
}
68+
69+
get runnerId() {
70+
return env.TRIGGER_RUNNER_ID;
71+
}
72+
73+
get successExitCode() {
74+
return env.TRIGGER_SUCCESS_EXIT_CODE;
75+
}
14276

143-
private runnerId: string;
77+
get failureExitCode() {
78+
return env.TRIGGER_FAILURE_EXIT_CODE;
79+
}
80+
81+
get workerApiUrl() {
82+
return env.TRIGGER_SUPERVISOR_API_URL;
83+
}
14484

145-
private successExitCode = env.TRIGGER_SUCCESS_EXIT_CODE;
146-
private failureExitCode = env.TRIGGER_FAILURE_EXIT_CODE;
85+
get workerInstanceName() {
86+
return env.TRIGGER_WORKER_INSTANCE_NAME;
87+
}
14788

14889
private state:
14990
| {
@@ -158,11 +99,6 @@ class ManagedRunController {
15899
constructor(opts: ManagedRunControllerOptions) {
159100
this.workerManifest = opts.workerManifest;
160101

161-
this.runnerId = env.TRIGGER_RUNNER_ID;
162-
163-
this.workerApiUrl = `${env.TRIGGER_SUPERVISOR_API_PROTOCOL}://${env.TRIGGER_SUPERVISOR_API_DOMAIN}:${env.TRIGGER_SUPERVISOR_API_PORT}`;
164-
this.workerInstanceName = env.TRIGGER_WORKER_INSTANCE_NAME;
165-
166102
this.httpClient = new WorkloadHttpClient({
167103
workerApiUrl: this.workerApiUrl,
168104
runnerId: this.runnerId,
@@ -172,7 +108,7 @@ class ManagedRunController {
172108
});
173109

174110
const properties = {
175-
...env,
111+
...env.raw,
176112
TRIGGER_POD_SCHEDULED_AT_MS: env.TRIGGER_POD_SCHEDULED_AT_MS.toISOString(),
177113
TRIGGER_DEQUEUED_AT_MS: env.TRIGGER_DEQUEUED_AT_MS.toISOString(),
178114
};
@@ -183,9 +119,6 @@ class ManagedRunController {
183119
properties,
184120
});
185121

186-
this.heartbeatIntervalSeconds = env.TRIGGER_HEARTBEAT_INTERVAL_SECONDS;
187-
this.snapshotPollIntervalSeconds = env.TRIGGER_SNAPSHOT_POLL_INTERVAL_SECONDS;
188-
189122
if (env.TRIGGER_METADATA_URL) {
190123
this.metadataClient = new MetadataClient(env.TRIGGER_METADATA_URL);
191124
}
@@ -834,45 +767,24 @@ class ManagedRunController {
834767
properties: { ...overrides },
835768
});
836769

837-
if (overrides.TRIGGER_SUCCESS_EXIT_CODE) {
838-
this.successExitCode = overrides.TRIGGER_SUCCESS_EXIT_CODE;
839-
}
840-
841-
if (overrides.TRIGGER_FAILURE_EXIT_CODE) {
842-
this.failureExitCode = overrides.TRIGGER_FAILURE_EXIT_CODE;
843-
}
770+
// Override the env with the new values
771+
env.override(overrides);
844772

773+
// Update services and clients with the new values
845774
if (overrides.TRIGGER_HEARTBEAT_INTERVAL_SECONDS) {
846-
this.heartbeatIntervalSeconds = overrides.TRIGGER_HEARTBEAT_INTERVAL_SECONDS;
847-
this.runHeartbeat.updateInterval(this.heartbeatIntervalSeconds * 1000);
775+
this.runHeartbeat.updateInterval(env.TRIGGER_HEARTBEAT_INTERVAL_SECONDS * 1000);
848776
}
849-
850777
if (overrides.TRIGGER_SNAPSHOT_POLL_INTERVAL_SECONDS) {
851-
this.snapshotPollIntervalSeconds = overrides.TRIGGER_SNAPSHOT_POLL_INTERVAL_SECONDS;
852-
this.snapshotPoller.updateInterval(this.snapshotPollIntervalSeconds * 1000);
853-
}
854-
855-
if (overrides.TRIGGER_WORKER_INSTANCE_NAME) {
856-
this.workerInstanceName = overrides.TRIGGER_WORKER_INSTANCE_NAME;
778+
this.snapshotPoller.updateInterval(env.TRIGGER_SNAPSHOT_POLL_INTERVAL_SECONDS * 1000);
857779
}
858-
859780
if (
860781
overrides.TRIGGER_SUPERVISOR_API_PROTOCOL ||
861782
overrides.TRIGGER_SUPERVISOR_API_DOMAIN ||
862783
overrides.TRIGGER_SUPERVISOR_API_PORT
863784
) {
864-
const protocol =
865-
overrides.TRIGGER_SUPERVISOR_API_PROTOCOL ?? env.TRIGGER_SUPERVISOR_API_PROTOCOL;
866-
const domain = overrides.TRIGGER_SUPERVISOR_API_DOMAIN ?? env.TRIGGER_SUPERVISOR_API_DOMAIN;
867-
const port = overrides.TRIGGER_SUPERVISOR_API_PORT ?? env.TRIGGER_SUPERVISOR_API_PORT;
868-
869-
this.workerApiUrl = `${protocol}://${domain}:${port}`;
870-
871785
this.httpClient.updateApiUrl(this.workerApiUrl);
872786
}
873-
874787
if (overrides.TRIGGER_RUNNER_ID) {
875-
this.runnerId = overrides.TRIGGER_RUNNER_ID;
876788
this.httpClient.updateRunnerId(this.runnerId);
877789
}
878790
}
@@ -1670,9 +1582,9 @@ await prodWorker.start();
16701582

16711583
function gatherProcessEnv(): Record<string, string> {
16721584
const $env = {
1673-
NODE_ENV: env.NODE_ENV,
1674-
NODE_EXTRA_CA_CERTS: env.NODE_EXTRA_CA_CERTS,
1675-
OTEL_EXPORTER_OTLP_ENDPOINT: env.OTEL_EXPORTER_OTLP_ENDPOINT,
1585+
NODE_ENV: stdEnv.NODE_ENV,
1586+
NODE_EXTRA_CA_CERTS: stdEnv.NODE_EXTRA_CA_CERTS,
1587+
OTEL_EXPORTER_OTLP_ENDPOINT: stdEnv.OTEL_EXPORTER_OTLP_ENDPOINT,
16761588
};
16771589

16781590
// Filter out undefined values

0 commit comments

Comments
 (0)