跳到主要内容
非官方简体中文翻译,内容版权归 Mastra 所有,遵循 Apache-2.0 许可。

Scheduled workflows

在工作流上声明 schedule 字段,Mastra 就会按你指定的 cron 触发它。同一工作流仍可直接通过 workflow.start() 调用,定时触发和手动运行共享同一条执行路径。

快速开始
快速开始的直接链接

以下工作流每天纽约时间上午 9 点运行。像注册其他工作流一样在 Mastra 上注册它,调度器会自动发现。

src/mastra/workflows/daily-report.ts
import { createWorkflow, createStep } from '@mastra/core/workflows'
import { z } from 'zod'

const sendReport = createStep({
id: 'send-report',
inputSchema: z.object({ userId: z.string() }),
outputSchema: z.object({ ok: z.boolean() }),
execute: async ({ inputData }) => {
// ...send the report for inputData.userId
return { ok: true }
},
})

export const dailyReport = createWorkflow({
id: 'daily-report',
inputSchema: z.object({ userId: z.string() }),
outputSchema: z.object({ ok: z.boolean() }),
schedule: {
cron: '0 9 * * *',
timezone: 'America/New_York',
inputData: { userId: 'system' },
},
})
.then(sendReport)
.commit()

不会发生单独的"注册计划"调用。Mastra 启动时,调度器直接从工作流读取 schedule。

执行引擎
执行引擎的直接链接

声明 schedule 不会改变工作流的运行方式。定时触发在运行调度器的主机上进程内运行,与 workflow.start() 或 HTTP 触发的运行方式相同。声明 schedule 的工作流直接运行无需额外的存储或 worker 设置。

拆分 worker 的部署是例外。当 MASTRA_WORKERS 环境变量设为任何值(包括 false)时,createWorkflow 会在事件驱动执行引擎上构建定时工作流,以便部署中的每个进程都以相同方式运行它们。此时定时触发在编排 worker 上运行,Mastra 会在创建工作流时向控制台记录一条警告。公共 API(workflow.start()、workflow.startAsync()、resume())不变。

事件驱动运行需要能够原子应用并发更新的存储适配器,例如 @mastra/libsql 或 @mastra/pg。使用其他适配器时,createRun() 会抛出错误并列出支持的适配器。

只有环境变量会触发切换,因为 createWorkflow 在 Mastra 读取其 workers 选项之前运行。如果你改为通过 workers 选项拆分 worker,请为你的定时工作流从 @mastra/core/workflows/evented 导入 createWorkflow。

单一计划
单一计划的直接链接

对于只在一个节奏上触发的工作流,向 schedule 传入一个对象:

src/mastra/workflows/daily-report.ts
const dailyReport = createWorkflow({
id: 'daily-report',
schedule: {
cron: '0 9 * * *',
timezone: 'America/New_York',
inputData: { userId: 'system' },
},
// ...
})

字段说明:

  • cron(必填):5、6 或 7 段式 cron 表达式。在工作流构建时验证。
  • timezone(可选):IANA 时区,例如 America/New_York。默认使用主机的本地时区。在生产环境中请显式设置,以免触发时间依赖服务器区域设置。
  • inputData(可选):每次触发时作为工作流输入传递的负载。
  • initialState(可选):运行的初始状态。
  • requestContext(可选):附加到运行的请求上下文。
  • metadata(可选):与计划行一起持久化的任意元数据。

多个计划
多个计划的直接链接

传入数组以在多个节奏上触发同一工作流。每个条目需要一个唯一且稳定的 id:

src/mastra/workflows/status-check.ts
const statusCheck = createWorkflow({
id: 'status-check',
schedule: [
{ id: 'morning', cron: '0 9 * * *', inputData: { window: 'morning' } },
{ id: 'evening', cron: '0 18 * * *', inputData: { window: 'evening' } },
],
// ...
})

每个条目都会创建独立的计划行,并按各自的 cron 触发,同时在 Studio 的 Schedules 视图中单独显示。

在 Studio 中查看计划
在 Studio 中查看计划的直接链接

Studio 将计划作为顶层区域呈现,而不是工作流内部的标签页:

  • 所有计划:打开 /workflows/schedules 查看跨工作流列表。每行显示工作流 id、cron、下次触发时间以及最近一次运行的状态。该列表让你一眼回答"有什么出问题了吗?"。
  • 按工作流筛选:在列表后追加 ?workflowId=<id> 将范围限定为单个工作流,例如 /workflows/schedules?workflowId=daily-report。
  • 计划详情:选择任意行打开 /workflows/schedules/:scheduleId。页面显示计划元数据和 Pause / Resume 控件,随后是完整的触发历史。

当工作流至少有一个计划时,其头部会包含 Schedules 操作:

  • 当只有一个匹配的计划时,该操作直接链接到其详情页。
  • 多个计划时:该操作链接到按工作流筛选的列表 /workflows/schedules?workflowId=<id>。
  • 没有计划时:该操作隐藏。

触发历史
触发历史的直接链接

每次触发都会记录一行触发记录,包含 run id、计划时间、实际触发时间和发布状态。计划详情页会将每次触发与对应的工作流运行关联,并显示:

  • 运行状态(running、success、failed、suspended、canceled)徽章。
  • 运行的开始时间和持续时间。
  • 指向运行完整图视图的链接 /workflows/:workflowId/graph/:runId。
  • 当触发已发布但运行记录尚未写入(由于触发发布与运行快照之间的竞态)时,显示 pending 徽章。
  • 当调度器根本无法将运行入队时,显示 publish failed 徽章及发布错误。

处于非终态的触发会使面板每五秒轮询一次,直到达到终态。列表支持分页,因此长期运行的计划不会一次加载数千行。

在运行时暂停计划
在运行时暂停计划的直接链接

当定时工作流在生产环境中误触发时,你不必重新部署或手动编辑数据库。可以从 SDK 暂停它:

import { MastraClient } from '@mastra/client-js'

const client = new MastraClient({ baseUrl: 'http://localhost:4111' })

// Schedule ids are derived from the workflow id: `wf_<workflowId>` for a
// single declarative schedule, or `wf_<workflowId>__<scheduleId>` when you
// declare multiple schedules per workflow as an array.
await client.pauseSchedule('wf_daily-report')
// ...investigate, ship a fix, then:
await client.resumeSchedule('wf_daily-report')

在 Studio 中,打开计划详情页并在头部选择 Pause 或 Resume。

需要了解的一些规则:

  • 暂停是持久的。状态写入 schedules 表,并在进程重启和重新部署后保留。声明式配置的 upsert 永远不会覆盖用户设置的状态,即使你更改了 cron、timezone 或其他字段。
  • 恢复会从当前时间重新计算 nextFireAt。暂停一周的计划在恢复时不会立即触发七次积压运行。它会在下一个常规 cron 时刻触发。
  • 使用 resumeSchedule 或 Studio 中的 Resume 按钮取消暂停。编辑工作流的 schedule 配置不会取消暂停已暂停的行。
  • 暂停和恢复是幂等的。对已暂停的计划调用暂停是无操作。
  • 此运维覆盖控制的是现有计划。请在代码中声明计划。声明式计划通过 createWorkflow 上的 schedule 字段在代码中创建、删除和编辑。如需在运行时以命令式方式创建计划,请使用统一的 mastra.schedules 服务并传入 workflowId。

底层 HTTP 路由是 POST /api/schedules/:scheduleId/pause 和 POST /api/schedules/:scheduleId/resume。两者都需要 schedules:write 权限。

重新部署并更改配置
重新部署并更改配置的直接链接

当你更改 schedule 配置并重新部署时,Mastra 会将现有计划行与新配置进行 diff:

  • 如果 cron 或 timezone 发生变化,nextFireAt 会重新计算。没有未来触发时间的节奏会使计划完成。重新计算后仍可触发的节奏会重新激活已完成的计划。
  • 如果仅 inputData、initialState 或 metadata 发生变化,行会就地修补,下次触发时间保持不变。
  • 用户设置的状态(例如通过 client.pauseSchedule 暂停)和触发历史永远不会被覆盖,除非上述节奏变化需要更新状态。

从工作流的 schedule 数组中移除某个计划条目,会在下次启动时删除其行。

部署拓扑
部署拓扑的直接链接

内置调度器使用 setInterval tick 循环轮询 schedules 表并认领到期行。它通过进程内 pubsub 分发工作流运行。它假定有一个长期运行的主机进程。

长期运行的主机(推荐)
长期运行的主机(推荐)的直接链接

Fly Machines、Railway、Render、AWS ECS、GKE 或你自己的服务器等部署目标会在 cron tick 之间保持 Mastra 进程存活。mastra build 生成的服务器会自动启动调度器,因此计划无需额外设置即可工作。

如果你使用服务器适配器运行 Mastra,请在服务器开始监听后调用 mastra.startWorkers()。适配器不会启动调度器,不调用此方法计划就永远不会触发。参见启动后台 worker。

对于生产部署,你可以将调度器作为专用 worker 进程运行,将其与 API 层隔离。

Serverless 平台
Serverless 平台的直接链接

Vercel、Netlify、AWS Lambda 和 Cloudflare Workers 等函数即服务平台在每个请求后关闭进程,因此 tick 循环无法获得第二次 tick,目前代码中声明的计划不会随内置调度器触发。直接运行仍然有效:从 HTTP 路由调用 run.start() 会像其他工作流一样在进程内运行声明了 schedule 的工作流。

要在这些平台上实现 cron 触发,请改用 @mastra/inngest。Inngest 原生于 serverless,并为你持有 cron 状态。

Inngest workflows
Inngest workflows的直接链接

本页记录的 schedule 字段驱动 Mastra 的内置调度器。如果你使用 @mastra/inngest,定时工作流通过 Inngest 自己的 createFunction 上的 cron 字段配置,并由 Inngest 的调度器触发。

实际影响:

  • Inngest 计划不会出现在 Studio 的 /workflows/schedules 视图中。
  • 工作流头部的 Schedules 操作不会对 Inngest 工作流显示。
  • client.pauseSchedule 和 client.resumeSchedule 不会控制 Inngest 计划。

请从 Inngest 控制台管理 Inngest 计划。当你希望 Mastra 端到端拥有调度能力时,请使用 Mastra 计划。

相关内容
相关内容的直接链接