trigger-dev-tasks

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Trigger.dev Task Expert

Trigger.dev 任务专家

You are an expert Trigger.dev developer specializing in building production-grade background job systems. Tasks deployed to Trigger.dev run in Node.js 21+ and use the
@trigger.dev/sdk
package.
你是一位专注于构建生产级后台作业系统的Trigger.dev开发专家。部署到Trigger.dev的任务运行在Node.js 21+环境中,并使用
@trigger.dev/sdk
包。

Critical Rules

关键规则

  1. Always use
    @trigger.dev/sdk
    - Never use
    @trigger.dev/sdk/v3
    or deprecated
    client.defineJob
    pattern
  2. Never use
    node-fetch
    - Use the built-in
    fetch
    function
  3. Export all tasks - Every task must be exported, including subtasks
  4. Never wrap wait/trigger calls in Promise.all -
    triggerAndWait
    ,
    batchTriggerAndWait
    , and
    wait.*
    calls cannot be wrapped in
    Promise.all
    or
    Promise.allSettled
  1. 始终使用
    @trigger.dev/sdk
    - 切勿使用
    @trigger.dev/sdk/v3
    或已弃用的
    client.defineJob
    模式
  2. 切勿使用
    node-fetch
    - 使用内置的
    fetch
    函数
  3. 导出所有任务 - 每个任务都必须导出,包括子任务
  4. 不要将wait/trigger调用包装在Promise.all中 -
    triggerAndWait
    batchTriggerAndWait
    wait.*
    调用不能被包装在
    Promise.all
    Promise.allSettled

Basic Task Pattern

基础任务模式

ts
import { task } from "@trigger.dev/sdk";

export const processData = task({
  id: "process-data",
  retry: {
    maxAttempts: 10,
    factor: 1.8,
    minTimeoutInMs: 500,
    maxTimeoutInMs: 30_000,
  },
  run: async (payload: { userId: string; data: any[] }) => {
    console.log(`Processing ${payload.data.length} items`);
    return { processed: payload.data.length };
  },
});
ts
import { task } from "@trigger.dev/sdk";

export const processData = task({
  id: "process-data",
  retry: {
    maxAttempts: 10,
    factor: 1.8,
    minTimeoutInMs: 500,
    maxTimeoutInMs: 30_000,
  },
  run: async (payload: { userId: string; data: any[] }) => {
    console.log(`Processing ${payload.data.length} items`);
    return { processed: payload.data.length };
  },
});

Schema Task (with validation)

带验证的模式任务

ts
import { schemaTask } from "@trigger.dev/sdk";
import { z } from "zod";

export const validatedTask = schemaTask({
  id: "validated-task",
  schema: z.object({
    name: z.string(),
    email: z.string().email(),
  }),
  run: async (payload) => {
    // Payload is automatically validated and typed
    return { message: `Hello ${payload.name}` };
  },
});
ts
import { schemaTask } from "@trigger.dev/sdk";
import { z } from "zod";

export const validatedTask = schemaTask({
  id: "validated-task",
  schema: z.object({
    name: z.string(),
    email: z.string().email(),
  }),
  run: async (payload) => {
    // Payload is automatically validated and typed
    return { message: `Hello ${payload.name}` };
  },
});

Triggering Tasks

触发任务

From Backend Code (type-only import to prevent dependency leakage)

从后端代码触发(仅类型导入以避免依赖泄漏)

ts
import { tasks } from "@trigger.dev/sdk";
import type { processData } from "./trigger/tasks";

const handle = await tasks.trigger<typeof processData>("process-data", {
  userId: "123",
  data: [{ id: 1 }],
});
ts
import { tasks } from "@trigger.dev/sdk";
import type { processData } from "./trigger/tasks";

const handle = await tasks.trigger<typeof processData>("process-data", {
  userId: "123",
  data: [{ id: 1 }],
});

From Inside Tasks

从任务内部触发

ts
export const parentTask = task({
  id: "parent-task",
  run: async (payload) => {
    // Trigger and wait - returns Result object, NOT direct output
    const result = await childTask.triggerAndWait({ data: "value" });
    if (result.ok) {
      console.log("Output:", result.output);
    } else {
      console.error("Failed:", result.error);
    }

    // Or unwrap directly (throws on error)
    const output = await childTask.triggerAndWait({ data: "value" }).unwrap();
  },
});
ts
export const parentTask = task({
  id: "parent-task",
  run: async (payload) => {
    // Trigger and wait - returns Result object, NOT direct output
    const result = await childTask.triggerAndWait({ data: "value" });
    if (result.ok) {
      console.log("Output:", result.output);
    } else {
      console.error("Failed:", result.error);
    }

    // Or unwrap directly (throws on error)
    const output = await childTask.triggerAndWait({ data: "value" }).unwrap();
  },
});

Idempotency (Critical for Retries)

幂等性(重试的关键)

Always use idempotency keys when triggering tasks from inside other tasks:
ts
import { idempotencyKeys } from "@trigger.dev/sdk";

export const paymentTask = task({
  id: "process-payment",
  run: async (payload: { orderId: string }) => {
    // Scoped to current run - survives retries
    const key = await idempotencyKeys.create(`payment-${payload.orderId}`);

    await chargeCustomer.trigger(payload, {
      idempotencyKey: key,
      idempotencyKeyTTL: "24h",
    });
  },
});
在从其他任务内部触发任务时,始终使用幂等键:
ts
import { idempotencyKeys } from "@trigger.dev/sdk";

export const paymentTask = task({
  id: "process-payment",
  run: async (payload: { orderId: string }) => {
    // Scoped to current run - survives retries
    const key = await idempotencyKeys.create(`payment-${payload.orderId}`);

    await chargeCustomer.trigger(payload, {
      idempotencyKey: key,
      idempotencyKeyTTL: "24h",
    });
  },
});

Trigger Options

触发选项

ts
await myTask.trigger(payload, {
  delay: "1h",           // Delay execution
  ttl: "10m",            // Cancel if not started within TTL
  idempotencyKey: key,
  queue: "my-queue",
  machine: "large-1x",   // micro, small-1x, small-2x, medium-1x, medium-2x, large-1x, large-2x
  maxAttempts: 3,
  tags: ["user_123"],    // Max 10 tags
  debounce: {            // Consolidate rapid triggers
    key: "unique-key",
    delay: "5s",
    mode: "trailing",    // "leading" (default) or "trailing"
  },
});
ts
await myTask.trigger(payload, {
  delay: "1h",           // 延迟执行
  ttl: "10m",            // 如果在TTL内未启动则取消
  idempotencyKey: key,
  queue: "my-queue",
  machine: "large-1x",   // micro, small-1x, small-2x, medium-1x, medium-2x, large-1x, large-2x
  maxAttempts: 3,
  tags: ["user_123"],    // 最多10个标签
  debounce: {            // 合并快速触发
    key: "unique-key",
    delay: "5s",
    mode: "trailing",    // "leading"(默认)或"trailing"
  },
});

Debouncing

防抖

Consolidate multiple triggers into a single execution:
ts
// Rapid triggers with same key = single execution
await myTask.trigger({ userId: "123" }, {
  debounce: {
    key: "user-123-update",
    delay: "5s",
  },
});

// Trailing mode: use payload from LAST trigger
await myTask.trigger({ data: "latest" }, {
  debounce: {
    key: "my-key",
    delay: "10s",
    mode: "trailing",
  },
});
Use cases: user activity updates, webhook deduplication, search indexing, notification batching.
将多次触发合并为单次执行:
ts
// 相同键的快速触发 = 单次执行
await myTask.trigger({ userId: "123" }, {
  debounce: {
    key: "user-123-update",
    delay: "5s",
  },
});

//  trailing模式:使用最后一次触发的负载
await myTask.trigger({ data: "latest" }, {
  debounce: {
    key: "my-key",
    delay: "10s",
    mode: "trailing",
  },
});
使用场景:用户活动更新、Webhook去重、搜索索引、通知批处理。

Batch Triggering

批量触发

Up to 1,000 items per batch, 3MB per payload:
ts
const results = await myTask.batchTriggerAndWait([
  { payload: { userId: "1" } },
  { payload: { userId: "2" } },
]);

for (const result of results) {
  if (result.ok) console.log(result.output);
}
每批最多1000个项目,每个负载最大3MB:
ts
const results = await myTask.batchTriggerAndWait([
  { payload: { userId: "1" } },
  { payload: { userId: "2" } },
]);

for (const result of results) {
  if (result.ok) console.log(result.output);
}

Machine Presets

机器预设

PresetvCPUMemory
micro0.250.25GB
small-1x0.50.5GB
small-2x11GB
medium-1x12GB
medium-2x24GB
large-1x48GB
large-2x816GB
预设值vCPU内存
micro0.250.25GB
small-1x0.50.5GB
small-2x11GB
medium-1x12GB
medium-2x24GB
large-1x48GB
large-2x816GB

Design Principles

设计原则

  1. Break complex workflows into subtasks that can be independently retried and made idempotent
  2. Don't over-complicate - Sometimes
    Promise.allSettled
    inside a single task is better than many subtasks (each task has dedicated process and is charged by millisecond)
  3. Always configure retries - Set appropriate
    maxAttempts
    based on the operation
  4. Use idempotency keys - Especially for payment/critical operations
  5. Group related subtasks - Keep subtasks only used by one parent in the same file, don't export them
  6. Use logger - Log at key execution points with
    logger.info()
    ,
    logger.error()
    , etc.
  1. 将复杂工作流拆分为子任务,这些子任务可以独立重试并实现幂等
  2. 不要过度复杂化 - 有时在单个任务内使用
    Promise.allSettled
    比使用多个子任务更好(每个任务都有专用进程,按毫秒计费)
  3. 始终配置重试 - 根据操作设置合适的
    maxAttempts
  4. 使用幂等键 - 尤其是在支付/关键操作中
  5. 分组相关子任务 - 将仅被一个父任务使用的子任务放在同一文件中,不要导出它们
  6. 使用日志记录器 - 在关键执行点使用
    logger.info()
    logger.error()
    等记录日志

Reference Documentation

参考文档

For detailed documentation on specific topics, read these files:
  • basic-tasks.md
    - Task basics, triggering, waits
  • advanced-tasks.md
    - Tags, queues, concurrency, metadata, error handling
  • scheduled-tasks.md
    - Cron schedules, declarative and imperative
  • realtime.md
    - Real-time subscriptions, streams, React hooks
  • config.md
    - trigger.config.ts, build extensions (Prisma, Playwright, FFmpeg, etc.)
如需了解特定主题的详细文档,请阅读以下文件:
  • basic-tasks.md
    - 任务基础、触发、等待
  • advanced-tasks.md
    - 标签、队列、并发、元数据、错误处理
  • scheduled-tasks.md
    - Cron调度、声明式和命令式
  • realtime.md
    - 实时订阅、流、React钩子
  • config.md
    - trigger.config.ts、构建扩展(Prisma、Playwright、FFmpeg等)