跳至主要內容

排程 Workflow

在 Workflow 中宣告 schedule 欄位,Mastra 便會按你指定的 cron 觸發該 Workflow。同一個 Workflow 仍可透過 workflow.start() 直接呼叫;排程觸發和手動執行共用同一個執行路徑。

快速開始
快速開始 的直接連結

以下 Workflow 會在紐約時間每天上午 9 時執行。像註冊其他 Workflow 一樣,在 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 啟動時,排程器會直接讀取 Workflow 上的 schedule

schedule 會帶來甚麼變化
what-schedule-changes 的直接連結

宣告了 schedule 的 Workflow 會自動升級至 evented execution engine。公開 API(workflow.start()workflow.startAsync()streamLegacy()resume())維持不變;EventedWorkflow extends Workflow,並以相同簽名覆寫每個方法。從程式碼的角度來看,排程觸發與手動執行並無分別。

這項升級有一個實際影響:evented 執行需要支援並行更新的儲存適配器,例如 @mastra/libsql。如果你的適配器不支援,createRun() 會擲出清晰的錯誤,並指出 schedule 欄位。請更換適配器或移除排程。

單一排程
單一排程 的直接連結

如要讓 Workflow 按單一頻率觸發,請向 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 表達式。建立 Workflow 時會進行驗證。
  • timezone(選填):IANA 時區,例如 America/New_York。預設為主機的本地時區。在生產環境中請明確設定此欄位,避免觸發時間取決於伺服器的地區設定。
  • inputData(選填):每次觸發時作為 Workflow 輸入傳入的 payload。
  • initialState(選填):該次執行的初始狀態。
  • requestContext(選填):附加至該次執行的請求上下文。
  • metadata(選填):與排程資料列一同持久保存的任意 metadata。

多個排程
多個排程 的直接連結

傳入陣列,即可按多個不同頻率觸發同一個 Workflow。每個項目都需要一個唯一且穩定的 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 將排程顯示為頂層區域,而非 Workflow 內的分頁:

  • 所有排程:開啟 /workflows/schedules,查看跨 Workflow 的清單。每一列會顯示 Workflow id、cron、下次觸發時間,以及最近一次執行的狀態,讓你一眼便能判斷「是否有項目發生故障?」。
  • 按 Workflow 篩選:加上 ?workflowId=<id>,將清單限定為單一 Workflow,例如 /workflows/schedules?workflowId=daily-report
  • 排程詳情:選取任何一列以開啟 /workflows/schedules/:scheduleId。頁面會顯示排程 metadata、PauseResume 控制項,以及完整的觸發記錄。

當 Workflow 至少有一個排程時,其標題列會顯示 Schedules 操作:

  • 如只有一個排程相符,該操作會直接連結至其詳情頁面。
  • 如有多個排程,該操作會連結至 /workflows/schedules?workflowId=<id> 的 Workflow 篩選清單。
  • 如沒有排程,該操作會隱藏。

觸發記錄
觸發記錄 的直接連結

每次觸發都會記錄一個觸發資料列,當中包含執行 id、排定時間、實際觸發時間和發佈狀態。排程詳情頁面會將每次觸發與對應的 Workflow 執行連結,並顯示:

  • 以徽章顯示執行狀態(runningsuccessfailedsuspendedcanceled)。
  • 執行的開始時間和持續時間。
  • 前往 /workflows/:workflowId/graph/:runId 完整執行圖表檢視的連結。
  • 如果觸發的執行記錄因觸發發佈與執行快照之間的競態而尚未寫入,則顯示 pending 徽章。
  • 如果排程器完全無法將執行加入隊列,則顯示 publish failed 徽章及發佈錯誤。

處於非終止狀態的觸發會使面板每五秒輪詢一次,直至其到達終止狀態。清單採用分頁,因此長期執行的排程不會預先載入數千個資料列。

在運行時暫停排程
在運行時暫停排程 的直接連結

當排程 Workflow 在生產環境中錯誤觸發時,你無需重新部署或手動編輯資料庫。可透過 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 中開啟排程詳情頁面,然後在標題列選取 PauseResume

以下是幾項值得留意的規則:

  • 暫停狀態會持久保存。狀態會寫入 schedules 資料表,並在程序重新啟動和重新部署後保留。即使你變更 crontimezone 或其他欄位,宣告式設定的 upsert 亦不會覆寫用戶設定的狀態。
  • 恢復時會從當前時間重新計算 nextFireAt。暫停了一星期的排程,不會在恢復時立即觸發積壓的七次執行,而會在下一個正常的 cron 時點觸發。
  • 使用 resumeSchedule 或 Studio 中的 Resume 按鈕解除暫停。編輯 Workflow 的 schedule 設定不會解除已暫停資料列的暫停狀態。
  • 暫停和恢復操作均具冪等性。對已暫停的排程呼叫暫停不會產生任何效果。
  • 此操作層級的覆寫控制現有排程。請在程式碼中編寫宣告式排程。宣告式排程透過 createWorkflowschedule 欄位在程式碼中建立、刪除和編輯。如要改為在運行時以命令式方式建立排程,請使用統一的 mastra.schedules 服務,並傳入 workflowId

底層 HTTP 路由為 POST /api/schedules/:scheduleId/pausePOST /api/schedules/:scheduleId/resume。兩者均需要 schedules:write 權限。

變更後重新部署
變更後重新部署 的直接連結

當你變更 schedule 設定並重新部署時,Mastra 會比較現有排程資料列與新設定的差異:

  • 如果 crontimezone 有變,便會重新計算 nextFireAt
  • 如果只有 inputDatainitialStatemetadata 有變,便會就地修補該資料列,並保留下次觸發時間。
  • 用戶設定的狀態(例如透過 client.pauseSchedule 暫停)和觸發記錄永遠不會被覆寫。

從 Workflow 的 schedule 陣列移除排程項目後,下次啟動時便會刪除其資料列。

部署拓撲
部署拓撲 的直接連結

內置排程器使用 setInterval 的 tick 迴圈輪詢 schedules 資料表,並取得到期資料列的處理權。它透過程序內的 pubsub 分派 Workflow 執行,並假設主機程序會長時間運行。

Fly Machines、Railway、Render、AWS ECS、GKE 或你自己的伺服器等部署目標,會在 cron tick 之間維持 Mastra 程序運行。排程無需額外設定即可運作。對於生產環境部署,你可以將排程器作為專用 worker 程序運行,使其與 API 層分隔。

Serverless 平台
Serverless 平台 的直接連結

Vercel、Netlify、AWS Lambda 和 Cloudflare Workers 等 Functions-as-a-Service 平台會在每次請求後關閉程序。由於 tick 迴圈不會進行第二次 tick,目前在這些平台上,以程式碼宣告的排程不會透過內置排程器觸發。

在這些平台上,請改用 @mastra/inngest。Inngest 原生支援 serverless,並會代你保存 cron 狀態。

Inngest Workflow
Inngest Workflow 的直接連結

本頁所述的 schedule 欄位會驅動 Mastra 的內置排程器。如果你使用 @mastra/inngest,排程 Workflow 會透過 createFunction 上 Inngest 自己的 cron 欄位設定,並改由 Inngest 的排程器觸發。

實際影響如下:

  • Inngest 排程不會出現在 Studio 的 /workflows/schedules 檢視中。
  • Inngest Workflow 的標題列不會顯示 Schedules 操作。
  • client.pauseScheduleclient.resumeSchedule 無法控制 Inngest 排程。

請從 Inngest dashboard 管理 Inngest 排程。如想由 Mastra 端對端管理排程,請使用 Mastra 排程。