Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/max-compute-seconds.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@trigger.dev/core": patch
"@trigger.dev/sdk": patch
"trigger.dev": patch
---

Add `maxComputeSeconds` as the user-facing replacement for `maxDuration` on `defineConfig`, task definitions, and trigger options. The new name makes the unit (compute-time seconds) unambiguous at the call site. `maxDuration` is JSDoc-deprecated and still accepted; if both are set, `maxComputeSeconds` wins. The `init` templates have been updated to use the new name.
4 changes: 2 additions & 2 deletions packages/cli-v3/templates/examples/schedule.mjs.template
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ export const firstScheduledTask = schedules.task({
id: "first-scheduled-task",
// Every hour
cron: "0 * * * *",
// Set an optional maxDuration to prevent tasks from running indefinitely
maxDuration: 300, // Stop executing after 300 secs (5 mins) of compute
// Set an optional maxComputeSeconds to prevent tasks from running indefinitely
maxComputeSeconds: 300, // Stop executing after 300 secs (5 mins) of compute
run: async (payload, { ctx }) => {
// The payload contains the last run timestamp that you can use to check if this is the first run
// And calculate the time since the last run
Expand Down
4 changes: 2 additions & 2 deletions packages/cli-v3/templates/examples/schedule.ts.template
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ export const firstScheduledTask = schedules.task({
id: "first-scheduled-task",
// Every hour
cron: "0 * * * *",
// Set an optional maxDuration to prevent tasks from running indefinitely
maxDuration: 300, // Stop executing after 300 secs (5 mins) of compute
// Set an optional maxComputeSeconds to prevent tasks from running indefinitely
maxComputeSeconds: 300, // Stop executing after 300 secs (5 mins) of compute
run: async (payload, { ctx }) => {
// The payload contains the last run timestamp that you can use to check if this is the first run
// And calculate the time since the last run
Expand Down
4 changes: 2 additions & 2 deletions packages/cli-v3/templates/examples/simple.mjs.template
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { logger, task, wait } from "@trigger.dev/sdk/v3";

export const helloWorldTask = task({
id: "hello-world",
// Set an optional maxDuration to prevent tasks from running indefinitely
maxDuration: 300, // Stop executing after 300 secs (5 mins) of compute
// Set an optional maxComputeSeconds to prevent tasks from running indefinitely
maxComputeSeconds: 300, // Stop executing after 300 secs (5 mins) of compute
run: async (payload, { ctx }) => {
logger.log("Hello, world!", { payload, ctx });

Expand Down
4 changes: 2 additions & 2 deletions packages/cli-v3/templates/examples/simple.ts.template
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { logger, task, wait } from "@trigger.dev/sdk/v3";

export const helloWorldTask = task({
id: "hello-world",
// Set an optional maxDuration to prevent tasks from running indefinitely
maxDuration: 300, // Stop executing after 300 secs (5 mins) of compute
// Set an optional maxComputeSeconds to prevent tasks from running indefinitely
maxComputeSeconds: 300, // Stop executing after 300 secs (5 mins) of compute
run: async (payload: any, { ctx }) => {
logger.log("Hello, world!", { payload, ctx });

Expand Down
4 changes: 2 additions & 2 deletions packages/cli-v3/templates/trigger.config.mjs.template
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ export default defineConfig({
project: "${projectRef}",
runtime: "${runtime}",
logLevel: "log",
// The max compute seconds a task is allowed to run. If the task run exceeds this duration, it will be stopped.
// The max compute seconds a task is allowed to run. If the run exceeds this, it will be stopped.
// You can override this on an individual task.
// See https://trigger.dev/docs/runs/max-duration
maxDuration: 3600,
maxComputeSeconds: 3600,
retries: {
enabledInDev: true,
default: {
Expand Down
4 changes: 2 additions & 2 deletions packages/cli-v3/templates/trigger.config.ts.template
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ export default defineConfig({
project: "${projectRef}",
runtime: "${runtime}",
logLevel: "log",
// The max compute seconds a task is allowed to run. If the task run exceeds this duration, it will be stopped.
// The max compute seconds a task is allowed to run. If the run exceeds this, it will be stopped.
// You can override this on an individual task.
// See https://trigger.dev/docs/runs/max-duration
maxDuration: 3600,
maxComputeSeconds: 3600,
retries: {
enabledInDev: true,
default: {
Expand Down
14 changes: 13 additions & 1 deletion packages/core/src/v3/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,16 +165,28 @@ export type TriggerConfig = {
*/
logLevel?: LogLevel;

/**
* 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.
*
* Minimum value is 5 seconds.
*
* Setting this value will affect all tasks in the project. You can override it on a per-task basis.
*
* @see https://trigger.dev/docs/tasks/overview#maxcomputeseconds-option
*/
maxComputeSeconds?: number;

/**
* 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.
*
* Minimum value is 5 seconds
*
* Setting this value will effect all tasks in the project.
*
* @deprecated Use `maxComputeSeconds` instead — same semantics, clearer unit. If both are set, `maxComputeSeconds` wins.
* @see https://trigger.dev/docs/tasks/overview#maxduration-option
*/
maxDuration: number;
maxDuration?: number;

/**
* Set a default time-to-live (TTL) for all task runs in the project. If a run is not executed within this time, it will be removed from the queue and never execute.
Expand Down
20 changes: 20 additions & 0 deletions packages/core/src/v3/types/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,10 +271,19 @@ type CommonTaskOptions<
}
| MachinePresetName;

/**
* 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.
*
* Minimum value is 5 seconds.
*/
maxComputeSeconds?: number;

/**
* 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.
*
* Minimum value is 5 seconds
*
* @deprecated Use `maxComputeSeconds` instead — same semantics, clearer unit. If both are set, `maxComputeSeconds` wins.
*/
maxDuration?: number;

Expand Down Expand Up @@ -876,12 +885,23 @@ export type TriggerOptions = {
*/
metadata?: Record<string, SerializableJson>;

/**
* 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.
*
* This will override the task's `maxComputeSeconds` (or the legacy `maxDuration`).
*
* Minimum value is 5 seconds.
*/
maxComputeSeconds?: number;

/**
* 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.
*
* This will override the task's maxDuration.
*
* Minimum value is 5 seconds
*
* @deprecated Use `maxComputeSeconds` instead — same semantics, clearer unit. If both are set, `maxComputeSeconds` wins.
*/
maxDuration?: number;

Expand Down
29 changes: 29 additions & 0 deletions packages/trigger-sdk/src/v3/config.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { describe, it, expect } from "vitest";
import { defineConfig } from "./config.js";

describe("defineConfig - maxComputeSeconds", () => {
it("uses maxComputeSeconds when only maxComputeSeconds is set", () => {
const cfg = defineConfig({ project: "p", maxComputeSeconds: 600 });
expect(cfg.maxDuration).toBe(600);
});

it("uses maxDuration when only maxDuration is set", () => {
const cfg = defineConfig({ project: "p", maxDuration: 600 });
expect(cfg.maxDuration).toBe(600);
});

it("prefers maxComputeSeconds when both are set", () => {
const cfg = defineConfig({ project: "p", maxComputeSeconds: 600, maxDuration: 9999 });
expect(cfg.maxDuration).toBe(600);
});

it("leaves maxDuration unset when neither is provided", () => {
const cfg = defineConfig({ project: "p" });
expect(cfg.maxDuration).toBeUndefined();
});

it("strips maxComputeSeconds from the returned config", () => {
const cfg = defineConfig({ project: "p", maxComputeSeconds: 600 });
expect((cfg as { maxComputeSeconds?: number }).maxComputeSeconds).toBeUndefined();
});
});
10 changes: 9 additions & 1 deletion packages/trigger-sdk/src/v3/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,15 @@ export type {
} from "@trigger.dev/core/v3";

export function defineConfig(config: TriggerConfig): TriggerConfig {
return config;
// `maxComputeSeconds` is the new name for `maxDuration`. If both are set, the new
// name wins. Internally the SDK and platform still read `maxDuration`, so we
// collapse the two fields here at the user-facing boundary.
const { maxComputeSeconds, maxDuration, ...rest } = config;
const resolved = maxComputeSeconds ?? maxDuration;
return {
...rest,
...(resolved !== undefined ? { maxDuration: resolved } : {}),
};
}

export type { TriggerConfig };
20 changes: 20 additions & 0 deletions packages/trigger-sdk/src/v3/maxComputeSeconds.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { describe, it, expect } from "vitest";
import { resolveMaxComputeSeconds } from "./maxComputeSeconds.js";

describe("resolveMaxComputeSeconds", () => {
it("returns maxComputeSeconds when only maxComputeSeconds is set", () => {
expect(resolveMaxComputeSeconds({ maxComputeSeconds: 300 })).toBe(300);
});

it("returns maxDuration when only maxDuration is set", () => {
expect(resolveMaxComputeSeconds({ maxDuration: 300 })).toBe(300);
});

it("prefers maxComputeSeconds when both are set", () => {
expect(resolveMaxComputeSeconds({ maxComputeSeconds: 300, maxDuration: 999 })).toBe(300);
});

it("returns undefined when neither is set", () => {
expect(resolveMaxComputeSeconds({})).toBeUndefined();
});
});
13 changes: 13 additions & 0 deletions packages/trigger-sdk/src/v3/maxComputeSeconds.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Collapse the user-facing `maxComputeSeconds` (new name) and `maxDuration` (deprecated)
* into a single value. If both are provided, `maxComputeSeconds` wins.
*
* Internal SDK/CLI/platform code only reads `maxDuration`, so all call sites that
* accept user input should funnel through this helper before forwarding the value.
*/
export function resolveMaxComputeSeconds(input: {
maxComputeSeconds?: number;
maxDuration?: number;
}): number | undefined {
return input.maxComputeSeconds ?? input.maxDuration;
}
33 changes: 17 additions & 16 deletions packages/trigger-sdk/src/v3/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
TaskRunExecutionResult,
TaskRunPromise,
} from "@trigger.dev/core/v3";
import { resolveMaxComputeSeconds } from "./maxComputeSeconds.js";
import { tracer } from "./tracer.js";

import type {
Expand Down Expand Up @@ -235,7 +236,7 @@ export function createTask<
queue: params.queue,
retry: params.retry ? { ...defaultRetryOptions, ...params.retry } : undefined,
machine: typeof params.machine === "string" ? { preset: params.machine } : params.machine,
maxDuration: params.maxDuration,
maxDuration: resolveMaxComputeSeconds(params),
ttl: params.ttl,
payloadSchema: params.jsonSchema,
fns: {
Expand Down Expand Up @@ -367,7 +368,7 @@ export function createSchemaTask<
queue: params.queue,
retry: params.retry ? { ...defaultRetryOptions, ...params.retry } : undefined,
machine: typeof params.machine === "string" ? { preset: params.machine } : params.machine,
maxDuration: params.maxDuration,
maxDuration: resolveMaxComputeSeconds(params),
ttl: params.ttl,
fns: {
run: params.run,
Expand Down Expand Up @@ -643,7 +644,7 @@ export async function batchTriggerById<TTask extends AnyTask>(
tags: item.options?.tags,
maxAttempts: item.options?.maxAttempts,
metadata: item.options?.metadata,
maxDuration: item.options?.maxDuration,
maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined,
idempotencyKey:
(await makeIdempotencyKey(item.options?.idempotencyKey)) ?? batchItemIdempotencyKey,
idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL,
Expand Down Expand Up @@ -900,7 +901,7 @@ export async function batchTriggerByIdAndWait<TTask extends AnyTask>(
tags: item.options?.tags,
maxAttempts: item.options?.maxAttempts,
metadata: item.options?.metadata,
maxDuration: item.options?.maxDuration,
maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined,
idempotencyKey:
(await makeIdempotencyKey(item.options?.idempotencyKey)) ?? batchItemIdempotencyKey,
idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL,
Expand Down Expand Up @@ -1159,7 +1160,7 @@ export async function batchTriggerTasks<TTasks extends readonly AnyTask[]>(
tags: item.options?.tags,
maxAttempts: item.options?.maxAttempts,
metadata: item.options?.metadata,
maxDuration: item.options?.maxDuration,
maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined,
idempotencyKey:
(await makeIdempotencyKey(item.options?.idempotencyKey)) ?? batchItemIdempotencyKey,
idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL,
Expand Down Expand Up @@ -1421,7 +1422,7 @@ export async function batchTriggerAndWaitTasks<TTasks extends readonly AnyTask[]
tags: item.options?.tags,
maxAttempts: item.options?.maxAttempts,
metadata: item.options?.metadata,
maxDuration: item.options?.maxDuration,
maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined,
idempotencyKey:
(await makeIdempotencyKey(item.options?.idempotencyKey)) ?? batchItemIdempotencyKey,
idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL,
Expand Down Expand Up @@ -1823,7 +1824,7 @@ async function* transformBatchItemsStream<TTask extends AnyTask>(
tags: item.options?.tags,
maxAttempts: item.options?.maxAttempts,
metadata: item.options?.metadata,
maxDuration: item.options?.maxDuration,
maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined,
idempotencyKey:
(await makeIdempotencyKey(item.options?.idempotencyKey)) ?? batchItemIdempotencyKey,
idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL,
Expand Down Expand Up @@ -1876,7 +1877,7 @@ async function* transformBatchItemsStreamForWait<TTask extends AnyTask>(
tags: item.options?.tags,
maxAttempts: item.options?.maxAttempts,
metadata: item.options?.metadata,
maxDuration: item.options?.maxDuration,
maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined,
idempotencyKey:
(await makeIdempotencyKey(item.options?.idempotencyKey)) ?? batchItemIdempotencyKey,
idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL,
Expand Down Expand Up @@ -1926,7 +1927,7 @@ async function* transformBatchByTaskItemsStream<TTasks extends readonly AnyTask[
tags: item.options?.tags,
maxAttempts: item.options?.maxAttempts,
metadata: item.options?.metadata,
maxDuration: item.options?.maxDuration,
maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined,
idempotencyKey:
(await makeIdempotencyKey(item.options?.idempotencyKey)) ?? batchItemIdempotencyKey,
idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL,
Expand Down Expand Up @@ -1978,7 +1979,7 @@ async function* transformBatchByTaskItemsStreamForWait<TTasks extends readonly A
tags: item.options?.tags,
maxAttempts: item.options?.maxAttempts,
metadata: item.options?.metadata,
maxDuration: item.options?.maxDuration,
maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined,
idempotencyKey:
(await makeIdempotencyKey(item.options?.idempotencyKey)) ?? batchItemIdempotencyKey,
idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL,
Expand Down Expand Up @@ -2030,7 +2031,7 @@ async function* transformSingleTaskBatchItemsStream<TPayload>(
tags: item.options?.tags,
maxAttempts: item.options?.maxAttempts,
metadata: item.options?.metadata,
maxDuration: item.options?.maxDuration,
maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined,
idempotencyKey:
(await makeIdempotencyKey(item.options?.idempotencyKey)) ?? batchItemIdempotencyKey,
idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL,
Expand Down Expand Up @@ -2091,7 +2092,7 @@ async function* transformSingleTaskBatchItemsStreamForWait<TPayload>(
tags: item.options?.tags,
maxAttempts: item.options?.maxAttempts,
metadata: item.options?.metadata,
maxDuration: item.options?.maxDuration,
maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined,
idempotencyKey: finalIdempotencyKey?.toString(),
idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL,
idempotencyKeyOptions,
Expand Down Expand Up @@ -2141,7 +2142,7 @@ async function trigger_internal<TRunTypes extends AnyRunTypes>(
tags: options?.tags,
maxAttempts: options?.maxAttempts,
metadata: options?.metadata,
maxDuration: options?.maxDuration,
maxDuration: options ? resolveMaxComputeSeconds(options) : undefined,
parentRunId: taskContext.ctx?.run.id,
machine: options?.machine,
priority: options?.priority,
Expand Down Expand Up @@ -2225,7 +2226,7 @@ async function batchTrigger_internal<TRunTypes extends AnyRunTypes>(
tags: item.options?.tags,
maxAttempts: item.options?.maxAttempts,
metadata: item.options?.metadata,
maxDuration: item.options?.maxDuration,
maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined,
idempotencyKey: finalIdempotencyKey?.toString(),
idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL,
idempotencyKeyOptions,
Expand Down Expand Up @@ -2398,7 +2399,7 @@ async function triggerAndWait_internal<TIdentifier extends string, TPayload, TOu
tags: options?.tags,
maxAttempts: options?.maxAttempts,
metadata: options?.metadata,
maxDuration: options?.maxDuration,
maxDuration: options ? resolveMaxComputeSeconds(options) : undefined,
resumeParentOnCompletion: true,
parentRunId: ctx.run.id,
idempotencyKey: processedIdempotencyKey?.toString(),
Expand Down Expand Up @@ -2500,7 +2501,7 @@ async function batchTriggerAndWait_internal<TIdentifier extends string, TPayload
tags: item.options?.tags,
maxAttempts: item.options?.maxAttempts,
metadata: item.options?.metadata,
maxDuration: item.options?.maxDuration,
maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined,
idempotencyKey: finalIdempotencyKey?.toString(),
idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL,
idempotencyKeyOptions,
Expand Down
Loading
Loading