Skip to content

Commit 719ae83

Browse files
authored
Add support for specifying machine preset at trigger time (#1608)
* add machine preset trigger option * add changeset * add examples to changeset * machinePreset -> machine * task options now also accept machine as simple string * update openapi spec
1 parent 7eda228 commit 719ae83

File tree

10 files changed

+140
-58
lines changed

10 files changed

+140
-58
lines changed

.changeset/gold-melons-fetch.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
"@trigger.dev/sdk": patch
3+
"@trigger.dev/core": patch
4+
---
5+
6+
Add support for specifying machine preset at trigger time. Works with any trigger function:
7+
8+
```ts
9+
// Same as usual, will use the machine preset on childTask, defaults to "small-1x"
10+
await childTask.trigger({ message: "Hello, world!" });
11+
12+
// This will override the task's machine preset and any defaults. Works with all trigger functions.
13+
await childTask.trigger({ message: "Hello, world!" }, { machine: "small-2x" });
14+
await childTask.triggerAndWait({ message: "Hello, world!" }, { machine: "small-2x" });
15+
16+
await childTask.batchTrigger([
17+
{ payload: { message: "Hello, world!" }, options: { machine: "micro" } },
18+
{ payload: { message: "Hello, world!" }, options: { machine: "large-1x" } },
19+
]);
20+
await childTask.batchTriggerAndWait([
21+
{ payload: { message: "Hello, world!" }, options: { machine: "micro" } },
22+
{ payload: { message: "Hello, world!" }, options: { machine: "large-1x" } },
23+
]);
24+
25+
await tasks.trigger<typeof childTask>(
26+
"child",
27+
{ message: "Hello, world!" },
28+
{ machine: "small-2x" }
29+
);
30+
await tasks.batchTrigger<typeof childTask>("child", [
31+
{ payload: { message: "Hello, world!" }, options: { machine: "micro" } },
32+
{ payload: { message: "Hello, world!" }, options: { machine: "large-1x" } },
33+
]);
34+
```

apps/webapp/app/v3/machinePresets.server.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ export function machinePresetFromName(name: MachinePresetName): MachinePreset {
3131
};
3232
}
3333

34+
export function machinePresetFromRun(run: { machinePreset: string | null }): MachinePreset | null {
35+
const presetName = MachinePresetName.safeParse(run.machinePreset).data;
36+
37+
if (!presetName) {
38+
return null;
39+
}
40+
41+
return machinePresetFromName(presetName);
42+
}
43+
3444
// Finds the smallest machine preset name that satisfies the given CPU and memory requirements
3545
function derivePresetNameFromValues(cpu: number, memory: number): MachinePresetName {
3646
for (const [name, preset] of Object.entries(machines)) {

apps/webapp/app/v3/marqs/sharedQueueConsumer.server.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import { RestoreCheckpointService } from "../services/restoreCheckpoint.server";
4343
import { SEMINTATTRS_FORCE_RECORDING, tracer } from "../tracer.server";
4444
import { generateJWTTokenForEnvironment } from "~/services/apiAuth.server";
4545
import { EnvironmentVariable } from "../environmentVariables/repository";
46-
import { machinePresetFromConfig } from "../machinePresets.server";
46+
import { machinePresetFromConfig, machinePresetFromRun } from "../machinePresets.server";
4747
import { env } from "~/env.server";
4848
import {
4949
FINAL_ATTEMPT_STATUSES,
@@ -413,7 +413,9 @@ export class SharedQueueConsumer {
413413
cliVersion: deployment.worker.cliVersion,
414414
startedAt: existingTaskRun.startedAt ?? new Date(),
415415
baseCostInCents: env.CENTS_PER_RUN,
416-
machinePreset: machinePresetFromConfig(backgroundTask.machineConfig ?? {}).name,
416+
machinePreset:
417+
existingTaskRun.machinePreset ??
418+
machinePresetFromConfig(backgroundTask.machineConfig ?? {}).name,
417419
maxDurationInSeconds: getMaxDuration(
418420
existingTaskRun.maxDurationInSeconds,
419421
backgroundTask.maxDurationInSeconds
@@ -542,8 +544,9 @@ export class SharedQueueConsumer {
542544

543545
// Retries for workers with disabled retry checkpoints will be handled just like normal attempts
544546
} else {
545-
const machineConfig = lockedTaskRun.lockedBy?.machineConfig;
546-
const machine = machinePresetFromConfig(machineConfig ?? {});
547+
const machine =
548+
machinePresetFromRun(lockedTaskRun) ??
549+
machinePresetFromConfig(lockedTaskRun.lockedBy?.machineConfig ?? {});
547550

548551
await this._sender.send("BACKGROUND_WORKER_MESSAGE", {
549552
backgroundWorkerId: deployment.worker.friendlyId,
@@ -1077,7 +1080,9 @@ class SharedQueueTasks {
10771080
const { backgroundWorkerTask, taskRun, queue } = attempt;
10781081

10791082
if (!machinePreset) {
1080-
machinePreset = machinePresetFromConfig(backgroundWorkerTask.machineConfig ?? {});
1083+
machinePreset =
1084+
machinePresetFromRun(attempt.taskRun) ??
1085+
machinePresetFromConfig(backgroundWorkerTask.machineConfig ?? {});
10811086
}
10821087

10831088
const metadata = await parsePacket({
@@ -1294,9 +1299,13 @@ class SharedQueueTasks {
12941299
},
12951300
});
12961301
}
1302+
12971303
const { backgroundWorkerTask, taskRun } = attempt;
12981304

1299-
const machinePreset = machinePresetFromConfig(backgroundWorkerTask.machineConfig ?? {});
1305+
const machinePreset =
1306+
machinePresetFromRun(attempt.taskRun) ??
1307+
machinePresetFromConfig(backgroundWorkerTask.machineConfig ?? {});
1308+
13001309
const execution = await this._executionFromAttempt(attempt, machinePreset);
13011310
const variables = await this.#buildEnvironmentVariables(
13021311
attempt.runtimeEnvironment,
@@ -1432,6 +1441,7 @@ class SharedQueueTasks {
14321441
machineConfig: true,
14331442
},
14341443
},
1444+
machinePreset: true,
14351445
},
14361446
});
14371447

@@ -1451,7 +1461,8 @@ class SharedQueueTasks {
14511461
attemptCount,
14521462
});
14531463

1454-
const machinePreset = machinePresetFromConfig(run.lockedBy?.machineConfig ?? {});
1464+
const machinePreset =
1465+
machinePresetFromRun(run) ?? machinePresetFromConfig(run.lockedBy?.machineConfig ?? {});
14551466

14561467
const variables = await this.#buildEnvironmentVariables(environment, run.id, machinePreset);
14571468

apps/webapp/app/v3/services/createTaskRunAttempt.server.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { AuthenticatedEnvironment } from "~/services/apiAuth.server";
66
import { logger } from "~/services/logger.server";
77
import { reportInvocationUsage } from "~/services/platform.v3.server";
88
import { generateFriendlyId } from "../friendlyIdentifiers";
9-
import { machinePresetFromConfig } from "../machinePresets.server";
9+
import { machinePresetFromConfig, machinePresetFromRun } from "../machinePresets.server";
1010
import { BaseService, ServiceValidationError } from "./baseService.server";
1111
import { CrashTaskRunService } from "./crashTaskRun.server";
1212
import { ExpireEnqueuedRunService } from "./expireEnqueuedRun.server";
@@ -173,7 +173,9 @@ export class CreateTaskRunAttemptService extends BaseService {
173173
});
174174
}
175175

176-
const machinePreset = machinePresetFromConfig(taskRun.lockedBy.machineConfig ?? {});
176+
const machinePreset =
177+
machinePresetFromRun(taskRun) ??
178+
machinePresetFromConfig(taskRun.lockedBy.machineConfig ?? {});
177179

178180
const metadata = await parsePacket({
179181
data: taskRun.metadata ?? undefined,

apps/webapp/app/v3/services/restoreCheckpoint.server.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { type Checkpoint } from "@trigger.dev/database";
22
import { logger } from "~/services/logger.server";
33
import { socketIo } from "../handleSocketIo.server";
4-
import { machinePresetFromConfig } from "../machinePresets.server";
4+
import { machinePresetFromConfig, machinePresetFromRun } from "../machinePresets.server";
55
import { BaseService } from "./baseService.server";
66
import { CreateCheckpointRestoreEventService } from "./createCheckpointRestoreEvent.server";
77
import { isRestorableAttemptStatus, isRestorableRunStatus } from "../taskStatus";
@@ -24,6 +24,7 @@ export class RestoreCheckpointService extends BaseService {
2424
run: {
2525
select: {
2626
status: true,
27+
machinePreset: true,
2728
},
2829
},
2930
attempt: {
@@ -69,8 +70,9 @@ export class RestoreCheckpointService extends BaseService {
6970
return;
7071
}
7172

72-
const { machineConfig } = checkpoint.attempt.backgroundWorkerTask;
73-
const machine = machinePresetFromConfig(machineConfig ?? {});
73+
const machine =
74+
machinePresetFromRun(checkpoint.run) ??
75+
machinePresetFromConfig(checkpoint.attempt.backgroundWorkerTask.machineConfig ?? {});
7476

7577
const restoreEvent = await this._prisma.checkpointRestoreEvent.findFirst({
7678
where: {

apps/webapp/app/v3/services/triggerTask.server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ export class TriggerTaskService extends BaseService {
415415
: undefined,
416416
runTags: bodyTags,
417417
oneTimeUseToken: options.oneTimeUseToken,
418+
machinePreset: body.options?.machine,
418419
},
419420
});
420421

docs/v3-openapi.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,6 +1595,18 @@ components:
15951595
We recommend prefixing tags with a namespace using an underscore or colon, like `user_1234567` or `org:9876543`. Stripe uses underscores.
15961596
items:
15971597
type: string
1598+
machine:
1599+
type: string
1600+
enum:
1601+
- micro
1602+
- small-1x
1603+
- small-2x
1604+
- medium-1x
1605+
- medium-2x
1606+
- large-1x
1607+
- large-2x
1608+
example: "small-2x"
1609+
description: The machine preset to use for this run. This will override the task's machine preset and any defaults.
15981610
TTL:
15991611
type:
16001612
- string

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { z } from "zod";
22
import { DeserializedJsonSchema } from "../../schemas/json.js";
33
import {
44
FlushedRunMetadata,
5+
MachinePresetName,
56
RunMetadataChangeOperation,
67
SerializedError,
78
TaskRunError,
@@ -91,6 +92,7 @@ export const TriggerTaskRequestBody = z.object({
9192
metadata: z.any(),
9293
metadataType: z.string().optional(),
9394
maxDuration: z.number().optional(),
95+
machine: MachinePresetName.optional(),
9496
})
9597
.optional(),
9698
});
@@ -131,6 +133,7 @@ export const BatchTriggerTaskItem = z.object({
131133
metadataType: z.string().optional(),
132134
maxDuration: z.number().optional(),
133135
parentAttempt: z.string().optional(),
136+
machine: MachinePresetName.optional(),
134137
})
135138
.optional(),
136139
});

packages/core/src/v3/types/tasks.ts

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import type { Schema as AISchema } from "ai";
2-
import { z } from "zod";
31
import { SerializableJson } from "../../schemas/json.js";
42
import { TriggerApiRequestOptions } from "../apiClient/index.js";
53
import { RunTags } from "../schemas/api.js";
64
import {
75
MachineCpu,
86
MachineMemory,
7+
MachinePresetName,
98
RetryOptions,
109
TaskMetadata,
1110
TaskRunContext,
@@ -220,41 +219,36 @@ type CommonTaskOptions<
220219
});
221220
* ```
222221
*/
223-
machine?: {
224-
/** vCPUs. The default is 0.5.
225-
*
226-
* Possible values:
227-
* - 0.25
228-
* - 0.5
229-
* - 1
230-
* - 2
231-
* - 4
232-
* @deprecated use preset instead
233-
*/
234-
cpu?: MachineCpu;
235-
/** In GBs of RAM. The default is 1.
236-
*
237-
* Possible values:
238-
* - 0.25
239-
* - 0.5
240-
* - 1
241-
* - 2
242-
* - 4
243-
* - 8
244-
* * @deprecated use preset instead
245-
*/
246-
memory?: MachineMemory;
247-
248-
/** Preset to use for the machine. Defaults to small-1x */
249-
preset?:
250-
| "micro"
251-
| "small-1x"
252-
| "small-2x"
253-
| "medium-1x"
254-
| "medium-2x"
255-
| "large-1x"
256-
| "large-2x";
257-
};
222+
machine?:
223+
| {
224+
/** vCPUs. The default is 0.5.
225+
*
226+
* Possible values:
227+
* - 0.25
228+
* - 0.5
229+
* - 1
230+
* - 2
231+
* - 4
232+
* @deprecated use preset instead
233+
*/
234+
cpu?: MachineCpu;
235+
/** In GBs of RAM. The default is 1.
236+
*
237+
* Possible values:
238+
* - 0.25
239+
* - 0.5
240+
* - 1
241+
* - 2
242+
* - 4
243+
* - 8
244+
* * @deprecated use preset instead
245+
*/
246+
memory?: MachineMemory;
247+
248+
/** Preset to use for the machine. Defaults to small-1x */
249+
preset?: MachinePresetName;
250+
}
251+
| MachinePresetName;
258252

259253
/**
260254
* The maximum duration in compute-time seconds that a task run is allowed to run. If the task run exceeds this duration, it will be stopped.
@@ -775,6 +769,11 @@ export type TriggerOptions = {
775769
* Minimum value is 5 seconds
776770
*/
777771
maxDuration?: number;
772+
773+
/**
774+
* The machine preset to use for this run. This will override the task's machine preset and any defaults.
775+
*/
776+
machine?: MachinePresetName;
778777
};
779778

780779
export type TriggerAndWaitOptions = Omit<TriggerOptions, "idempotencyKey" | "idempotencyKeyTTL">;

0 commit comments

Comments
 (0)