Skip to content

Commit 31b8559

Browse files
committed
add new core server only export
1 parent 983bb41 commit 31b8559

File tree

10 files changed

+641
-17
lines changed

10 files changed

+641
-17
lines changed

apps/coordinator/src/checkpointer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ExponentialBackoff } from "@trigger.dev/core/v3/apps";
2-
import { testDockerCheckpoint } from "@trigger.dev/core/v3/checkpoints";
2+
import { testDockerCheckpoint } from "@trigger.dev/core/v3/serverOnly";
33
import { nanoid } from "nanoid";
44
import fs from "node:fs/promises";
55
import { ChaosMonkey } from "./chaosMonkey";

packages/core/package.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
"./v3/workers": "./src/v3/workers/index.ts",
6060
"./v3/schemas": "./src/v3/schemas/index.ts",
6161
"./v3/runEngineWorker": "./src/v3/runEngineWorker/index.ts",
62-
"./v3/checkpoints": "./src/v3/checkpoints/index.ts"
62+
"./v3/serverOnly": "./src/v3/serverOnly/index.ts"
6363
},
6464
"sourceDialects": [
6565
"@triggerdotdev/source"
@@ -178,8 +178,8 @@
178178
"v3/runEngineWorker": [
179179
"dist/commonjs/v3/runEngineWorker/index.d.ts"
180180
],
181-
"v3/checkpoints": [
182-
"dist/commonjs/v3/checkpoints/index.d.ts"
181+
"v3/serverOnly": [
182+
"dist/commonjs/v3/serverOnly/index.d.ts"
183183
]
184184
}
185185
},
@@ -663,15 +663,15 @@
663663
"default": "./dist/commonjs/v3/runEngineWorker/index.js"
664664
}
665665
},
666-
"./v3/checkpoints": {
666+
"./v3/serverOnly": {
667667
"import": {
668-
"@triggerdotdev/source": "./src/v3/checkpoints/index.ts",
669-
"types": "./dist/esm/v3/checkpoints/index.d.ts",
670-
"default": "./dist/esm/v3/checkpoints/index.js"
668+
"@triggerdotdev/source": "./src/v3/serverOnly/index.ts",
669+
"types": "./dist/esm/v3/serverOnly/index.d.ts",
670+
"default": "./dist/esm/v3/serverOnly/index.js"
671671
},
672672
"require": {
673-
"types": "./dist/commonjs/v3/checkpoints/index.d.ts",
674-
"default": "./dist/commonjs/v3/checkpoints/index.js"
673+
"types": "./dist/commonjs/v3/serverOnly/index.d.ts",
674+
"default": "./dist/commonjs/v3/serverOnly/index.js"
675675
}
676676
}
677677
},

packages/core/src/v3/checkpoints/index.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { CheckpointType } from "./runEngine.js";
2+
import z from "zod";
3+
4+
const CallbackUrl = z
5+
.string()
6+
.url()
7+
.transform((url) => new URL(url));
8+
9+
export const CheckpointServiceSuspendRequestBody = z.object({
10+
type: CheckpointType,
11+
containerId: z.string(),
12+
simulate: z.boolean().optional(),
13+
leaveRunning: z.boolean().optional(),
14+
reason: z.string().optional(),
15+
callbacks: z
16+
.object({
17+
/** These headers will sent to all callbacks */
18+
headers: z.record(z.string()).optional(),
19+
/** This will be hit before suspending the container. Suspension will proceed unless we receive an error response. */
20+
preSuspend: CallbackUrl.optional(),
21+
/** This will be hit after suspending or failure to suspend the container */
22+
completion: CallbackUrl.optional(),
23+
})
24+
.optional(),
25+
});
26+
27+
export type CheckpointServiceSuspendRequestBody = z.infer<
28+
typeof CheckpointServiceSuspendRequestBody
29+
>;
30+
export type CheckpointServiceSuspendRequestBodyInput = z.input<
31+
typeof CheckpointServiceSuspendRequestBody
32+
>;
33+
34+
export const CheckpointServiceSuspendResponseBody = z.object({
35+
ok: z.literal(true),
36+
});
37+
38+
export type CheckpointServiceSuspendResponseBody = z.infer<
39+
typeof CheckpointServiceSuspendResponseBody
40+
>;
41+
42+
export const CheckpointServiceRestoreRequestBody = z.discriminatedUnion("type", [
43+
z.object({
44+
type: z.literal(CheckpointType.Enum.DOCKER),
45+
containerId: z.string(),
46+
}),
47+
z.object({
48+
type: z.literal(CheckpointType.Enum.KUBERNETES),
49+
containerId: z.string(),
50+
}),
51+
]);
52+
53+
export type CheckpointServiceRestoreRequestBody = z.infer<
54+
typeof CheckpointServiceRestoreRequestBody
55+
>;
56+
export type CheckpointServiceRestoreRequestBodyInput = z.input<
57+
typeof CheckpointServiceRestoreRequestBody
58+
>;

packages/core/src/v3/schemas/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ export * from "./config.js";
1212
export * from "./build.js";
1313
export * from "./runEngine.js";
1414
export * from "./webhooks.js";
15+
export * from "./checkpoints.js";
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import { SupervisorHttpClient } from "../runEngineWorker/index.js";
2+
import {
3+
CheckpointServiceSuspendRequestBodyInput,
4+
CheckpointServiceSuspendResponseBody,
5+
CheckpointServiceRestoreRequestBodyInput,
6+
} from "../schemas/checkpoints.js";
7+
import { DequeuedMessage } from "../schemas/runEngine.js";
8+
import { SimpleStructuredLogger } from "../utils/structuredLogger.js";
9+
10+
export type CheckpointClientOptions = {
11+
apiUrl: URL;
12+
workerClient: SupervisorHttpClient;
13+
};
14+
15+
export class CheckpointClient {
16+
private readonly logger = new SimpleStructuredLogger("checkpoint-client");
17+
private readonly apiUrl: URL;
18+
private readonly workerClient: SupervisorHttpClient;
19+
20+
private get restoreUrl() {
21+
return new URL("/api/v1/restore", this.apiUrl);
22+
}
23+
24+
private get suspendUrl() {
25+
return new URL("/api/v1/suspend", this.apiUrl);
26+
}
27+
28+
constructor(opts: CheckpointClientOptions) {
29+
this.apiUrl = opts.apiUrl;
30+
this.workerClient = opts.workerClient;
31+
}
32+
33+
async suspendRun({
34+
runFriendlyId,
35+
snapshotFriendlyId,
36+
containerId,
37+
runnerId,
38+
}: {
39+
runFriendlyId: string;
40+
snapshotFriendlyId: string;
41+
containerId: string;
42+
runnerId: string;
43+
}): Promise<boolean> {
44+
const completionUrl = this.workerClient.getSuspendCompletionUrl(
45+
runFriendlyId,
46+
snapshotFriendlyId,
47+
runnerId
48+
);
49+
50+
const res = await fetch(this.suspendUrl, {
51+
method: "POST",
52+
headers: {
53+
"Content-Type": "application/json",
54+
},
55+
body: JSON.stringify({
56+
type: "DOCKER",
57+
containerId,
58+
callbacks: {
59+
completion: completionUrl.url,
60+
headers: completionUrl.headers,
61+
},
62+
} satisfies CheckpointServiceSuspendRequestBodyInput),
63+
});
64+
65+
if (!res.ok) {
66+
this.logger.error("[CheckpointClient] Suspend request failed", {
67+
runFriendlyId,
68+
snapshotFriendlyId,
69+
containerId,
70+
});
71+
return false;
72+
}
73+
74+
this.logger.debug("[CheckpointClient] Suspend request success", {
75+
runFriendlyId,
76+
snapshotFriendlyId,
77+
containerId,
78+
status: res.status,
79+
contentType: res.headers.get("content-type"),
80+
});
81+
82+
try {
83+
const data = await res.json();
84+
const parsedData = CheckpointServiceSuspendResponseBody.safeParse(data);
85+
86+
if (!parsedData.success) {
87+
this.logger.error("[CheckpointClient] Suspend response invalid", {
88+
runFriendlyId,
89+
snapshotFriendlyId,
90+
containerId,
91+
data,
92+
});
93+
return false;
94+
}
95+
} catch (error) {
96+
this.logger.error("[CheckpointClient] Suspend response error", {
97+
error,
98+
text: await res.text(),
99+
});
100+
return false;
101+
}
102+
103+
return true;
104+
}
105+
106+
async restoreRun({
107+
runFriendlyId,
108+
snapshotFriendlyId,
109+
checkpoint,
110+
}: {
111+
runFriendlyId: string;
112+
snapshotFriendlyId: string;
113+
checkpoint: NonNullable<DequeuedMessage["checkpoint"]>;
114+
}): Promise<boolean> {
115+
const res = await fetch(this.restoreUrl, {
116+
method: "POST",
117+
headers: {
118+
"Content-Type": "application/json",
119+
},
120+
body: JSON.stringify({
121+
type: "DOCKER",
122+
containerId: checkpoint.location,
123+
} satisfies CheckpointServiceRestoreRequestBodyInput),
124+
});
125+
126+
if (!res.ok) {
127+
this.logger.error("[CheckpointClient] Restore request failed", {
128+
runFriendlyId,
129+
snapshotFriendlyId,
130+
checkpoint,
131+
});
132+
return false;
133+
}
134+
135+
return true;
136+
}
137+
}

0 commit comments

Comments
 (0)