Skip to content

Commit 22a6035

Browse files
committed
fix supervisor api domain for split setups
1 parent 8ee6b49 commit 22a6035

File tree

6 files changed

+81
-21
lines changed

6 files changed

+81
-21
lines changed

apps/supervisor/src/env.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,31 @@ import { z } from "zod";
44
import { getDockerHostDomain } from "./util.js";
55

66
const Env = z.object({
7-
// This will come from `status.hostIP` in k8s
8-
WORKER_HOST_IP: z.string().default(getDockerHostDomain()),
9-
TRIGGER_API_URL: z.string().url(),
10-
TRIGGER_WORKER_TOKEN: z.string(),
117
// This will come from `spec.nodeName` in k8s
128
TRIGGER_WORKER_INSTANCE_NAME: z.string().default(randomUUID()),
9+
10+
// Required settings
11+
TRIGGER_API_URL: z.string().url(),
12+
TRIGGER_WORKER_TOKEN: z.string(),
1313
MANAGED_WORKER_SECRET: z.string(),
14-
TRIGGER_WORKLOAD_API_PORT: z.coerce.number().default(8020),
15-
TRIGGER_WORKLOAD_API_PORT_EXTERNAL: z.coerce.number().default(8020),
14+
15+
// Workload API settings (coordinator mode) - the workload API is what the run controller connects to
16+
TRIGGER_WORKLOAD_API_ENABLED: z.coerce.boolean().default(true),
17+
TRIGGER_WORKLOAD_API_PROTOCOL: z
18+
.string()
19+
.transform((s) => z.enum(["http", "https"]).parse(s.toLowerCase()))
20+
.default("http"),
21+
TRIGGER_WORKLOAD_API_DOMAIN: z.string().default(getDockerHostDomain()), // If unset, will use orchestrator-specific default
22+
TRIGGER_WORKLOAD_API_PORT_INTERNAL: z.coerce.number().default(8020), // This is the port the workload API listens on
23+
TRIGGER_WORKLOAD_API_PORT_EXTERNAL: z.coerce.number().default(8020), // This is the exposed port passed to the run controller
24+
25+
// Dequeue settings (provider mode)
26+
TRIGGER_DEQUEUE_ENABLED: z.coerce.boolean().default(true),
27+
TRIGGER_DEQUEUE_INTERVAL_MS: z.coerce.number().int().default(1000),
28+
29+
// Optional services
1630
TRIGGER_WARM_START_URL: z.string().optional(),
1731
TRIGGER_CHECKPOINT_URL: z.string().optional(),
18-
TRIGGER_DEQUEUE_INTERVAL_MS: z.coerce.number().int().default(1000),
1932

2033
// Used by the workload manager, e.g docker/k8s
2134
DOCKER_NETWORK: z.string().default("host"),

apps/supervisor/src/index.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ class ManagedSupervisor {
2929
private readonly warmStartUrl = env.TRIGGER_WARM_START_URL;
3030

3131
constructor() {
32-
const workerApiUrl = `http://${env.WORKER_HOST_IP}:${env.TRIGGER_WORKLOAD_API_PORT_EXTERNAL}`;
32+
const workloadApiProtocol = env.TRIGGER_WORKLOAD_API_PROTOCOL;
33+
const workloadApiDomain = env.TRIGGER_WORKLOAD_API_DOMAIN;
34+
const workloadApiPortExternal = env.TRIGGER_WORKLOAD_API_PORT_EXTERNAL;
3335

3436
if (this.warmStartUrl) {
3537
this.logger.log("[ManagedWorker] 🔥 Warm starts enabled", {
@@ -40,13 +42,17 @@ class ManagedSupervisor {
4042
if (this.isKubernetes) {
4143
this.resourceMonitor = new KubernetesResourceMonitor(createK8sApi(), "");
4244
this.workloadManager = new KubernetesWorkloadManager({
43-
workerApiUrl,
45+
workloadApiProtocol,
46+
workloadApiDomain,
47+
workloadApiPort: workloadApiPortExternal,
4448
warmStartUrl: this.warmStartUrl,
4549
});
4650
} else {
4751
this.resourceMonitor = new DockerResourceMonitor(new Docker());
4852
this.workloadManager = new DockerWorkloadManager({
49-
workerApiUrl,
53+
workloadApiProtocol,
54+
workloadApiDomain,
55+
workloadApiPort: workloadApiPortExternal,
5056
warmStartUrl: this.warmStartUrl,
5157
});
5258
}
@@ -57,6 +63,8 @@ class ManagedSupervisor {
5763
instanceName: env.TRIGGER_WORKER_INSTANCE_NAME,
5864
managedWorkerSecret: env.MANAGED_WORKER_SECRET,
5965
dequeueIntervalMs: env.TRIGGER_DEQUEUE_INTERVAL_MS,
66+
queueConsumerEnabled: env.TRIGGER_DEQUEUE_ENABLED,
67+
runNotificationsEnabled: env.TRIGGER_WORKLOAD_API_ENABLED,
6068
preDequeue: async () => {
6169
if (this.isKubernetes) {
6270
// TODO: Test k8s resource monitor and remove this
@@ -180,7 +188,7 @@ class ManagedSupervisor {
180188

181189
// Responds to workload requests only
182190
this.workloadServer = new WorkloadServer({
183-
port: env.TRIGGER_WORKLOAD_API_PORT,
191+
port: env.TRIGGER_WORKLOAD_API_PORT_INTERNAL,
184192
workerClient: this.workerSession.httpClient,
185193
checkpointClient: this.checkpointClient,
186194
});

apps/supervisor/src/workloadManager/docker.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,18 @@ import {
66
} from "./types.js";
77
import { x } from "tinyexec";
88
import { env } from "../env.js";
9-
import { RunnerId } from "../util.js";
9+
import { getDockerHostDomain, RunnerId } from "../util.js";
1010

1111
export class DockerWorkloadManager implements WorkloadManager {
1212
private readonly logger = new SimpleStructuredLogger("docker-workload-provider");
1313

14-
constructor(private opts: WorkloadManagerOptions) {}
14+
constructor(private opts: WorkloadManagerOptions) {
15+
if (opts.workloadApiDomain) {
16+
this.logger.warn("[DockerWorkloadProvider] ⚠️ Custom workload API domain", {
17+
domain: opts.workloadApiDomain,
18+
});
19+
}
20+
}
1521

1622
async create(opts: WorkloadManagerCreateOptions) {
1723
this.logger.log("[DockerWorkloadProvider] Creating container", { opts });
@@ -24,7 +30,9 @@ export class DockerWorkloadManager implements WorkloadManager {
2430
`--env=TRIGGER_ENV_ID=${opts.envId}`,
2531
`--env=TRIGGER_RUN_ID=${opts.runFriendlyId}`,
2632
`--env=TRIGGER_SNAPSHOT_ID=${opts.snapshotFriendlyId}`,
27-
`--env=TRIGGER_WORKER_API_URL=${this.opts.workerApiUrl}`,
33+
`--env=TRIGGER_SUPERVISOR_API_PROTOCOL=${this.opts.workloadApiProtocol}`,
34+
`--env=TRIGGER_SUPERVISOR_API_PORT=${this.opts.workloadApiPort}`,
35+
`--env=TRIGGER_SUPERVISOR_API_DOMAIN=${this.opts.workloadApiDomain ?? getDockerHostDomain()}`,
2836
`--env=TRIGGER_WORKER_INSTANCE_NAME=${env.TRIGGER_WORKER_INSTANCE_NAME}`,
2937
`--env=OTEL_EXPORTER_OTLP_ENDPOINT=${env.OTEL_EXPORTER_OTLP_ENDPOINT}`,
3038
`--env=TRIGGER_RUNNER_ID=${runnerId}`,

apps/supervisor/src/workloadManager/kubernetes.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ export class KubernetesWorkloadManager implements WorkloadManager {
2323

2424
constructor(private opts: WorkloadManagerOptions) {
2525
this.k8s = createK8sApi();
26+
27+
if (opts.workloadApiDomain) {
28+
this.logger.warn("[KubernetesWorkloadManager] ⚠️ Custom workload API domain", {
29+
domain: opts.workloadApiDomain,
30+
});
31+
}
2632
}
2733

2834
async create(opts: WorkloadManagerCreateOptions) {
@@ -72,8 +78,26 @@ export class KubernetesWorkloadManager implements WorkloadManager {
7278
value: opts.snapshotFriendlyId,
7379
},
7480
{
75-
name: "TRIGGER_WORKER_API_URL",
76-
value: this.opts.workerApiUrl,
81+
name: "TRIGGER_SUPERVISOR_API_PROTOCOL",
82+
value: this.opts.workloadApiProtocol,
83+
},
84+
{
85+
name: "TRIGGER_SUPERVISOR_API_PORT",
86+
value: `${this.opts.workloadApiPort}`,
87+
},
88+
{
89+
name: "TRIGGER_SUPERVISOR_API_DOMAIN",
90+
...(this.opts.workloadApiDomain
91+
? {
92+
value: this.opts.workloadApiDomain,
93+
}
94+
: {
95+
valueFrom: {
96+
fieldRef: {
97+
fieldPath: "status.hostIP",
98+
},
99+
},
100+
}),
77101
},
78102
{
79103
name: "TRIGGER_WORKER_INSTANCE_NAME",

apps/supervisor/src/workloadManager/types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { type EnvironmentType, type MachinePreset } from "@trigger.dev/core/v3";
22

33
export interface WorkloadManagerOptions {
4-
workerApiUrl: string;
4+
workloadApiProtocol: "http" | "https";
5+
workloadApiDomain?: string; // If unset, will use orchestrator-specific default
6+
workloadApiPort: number;
57
warmStartUrl?: string;
68
}
79

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ const Env = z.object({
3636
NODE_EXTRA_CA_CERTS: z.string().optional(),
3737

3838
// Set at runtime
39-
TRIGGER_WORKER_API_URL: z.string().url(),
39+
TRIGGER_SUPERVISOR_API_PROTOCOL: z.enum(["http", "https"]),
40+
TRIGGER_SUPERVISOR_API_DOMAIN: z.string(),
41+
TRIGGER_SUPERVISOR_API_PORT: z.coerce.number(),
4042
TRIGGER_WORKLOAD_CONTROLLER_ID: z.string().default(`controller_${randomUUID()}`),
4143
TRIGGER_ENV_ID: z.string(),
4244
TRIGGER_RUN_ID: z.string().optional(), // This is only useful for cold starts
@@ -84,6 +86,8 @@ class ManagedRunController {
8486
private readonly snapshotPoller: HeartbeatService;
8587
private readonly snapshotPollIntervalSeconds: number;
8688

89+
private readonly workerApiUrl: string;
90+
8791
private state:
8892
| {
8993
phase: "RUN";
@@ -246,8 +250,10 @@ class ManagedRunController {
246250
this.heartbeatIntervalSeconds = opts.heartbeatIntervalSeconds || 30;
247251
this.snapshotPollIntervalSeconds = 5;
248252

253+
this.workerApiUrl = `${env.TRIGGER_SUPERVISOR_API_PROTOCOL}://${env.TRIGGER_SUPERVISOR_API_DOMAIN}:${env.TRIGGER_SUPERVISOR_API_PORT}`;
254+
249255
this.httpClient = new WorkloadHttpClient({
250-
workerApiUrl: env.TRIGGER_WORKER_API_URL,
256+
workerApiUrl: this.workerApiUrl,
251257
deploymentId: env.TRIGGER_DEPLOYMENT_ID,
252258
runnerId: env.TRIGGER_RUNNER_ID,
253259
});
@@ -746,8 +752,7 @@ class ManagedRunController {
746752
}
747753

748754
createSocket() {
749-
const wsUrl = new URL(env.TRIGGER_WORKER_API_URL);
750-
wsUrl.pathname = "/workload";
755+
const wsUrl = new URL("/workload", this.workerApiUrl);
751756

752757
this.socket = io(wsUrl.href, {
753758
transports: ["websocket"],

0 commit comments

Comments
 (0)