跳轉到主要內容
文件運行自動續跑

意外中斷與自動續跑

工作流程跑到一半被打斷怎麼辦?搭配 recovery 與 idempotent,跑斷點續傳、避免重複副作用。

"一次沒跑完怎麼辦"是生產級工作流必須回答的問題。Braidrun 提供兩種處理方案:

  • 默認:安全中斷 — 把 execution 標為 INTERRUPTED,等你看清楚再手動從中間某一步"重試"。
  • 可選:自動續跑 — 你顯式聲明"這條工作流可以續跑 + 哪些步驟冪等"後,平臺自動從中斷點繼續。
中斷到底指什麼

兩類:

  • 平臺側 —— 服務重啟、實例被替換、宿主機故障。這些我們努力避免但不能 100%。
  • 你側 —— 你主動"取消"某次 execution(停在 CANCELLED,不是 INTERRUPTED)。

只有前一類才會進入"自動續跑"流程,CANCELLED 的 execution 不會自動跑。

默認行為:安全中斷

發生平臺側中斷時,平臺:

  1. 把該 execution 狀態標為 INTERRUPTED;
  2. 保留所有已完成 step 的結果、產物、日誌;
  3. 你收到一條站內通知(也會按你的通知配置郵件 / Slack);
  4. 你去執行詳情頁,可以"從失敗那一步重試"—— 平臺複用前面 step 的結果。

這種默認對所有工作流都可用,不需要配置。適合:

  • 工作流含對外副作用(發郵件 / 扣款 / 改數據庫)
  • 生產還不確定"重啟續跑是否安全"時

可選:自動續跑

如果你的工作流是純數據管道(只讀 API + 生成報表),可以開啟自動續跑 —— 中斷髮生後平臺自動從中斷點繼續跑,不需要你手動點。

啟用的兩層 opt-in

要讓自動續跑生效,你需要在 YAML 裡兩層都聲明:

  1. workflow 級: 聲明 recovery.autoResumeOnRestart: true
  2. step 級: 安全重跑的步驟標 idempotent: true

完整示例

yaml
name: daily-asa-digest
version: "1.0.0"

recovery:
  autoResumeOnRestart: true
  policy: RESUME_FROM_LAST_INCOMPLETE
  maxAutoResumeAttempts: 3

steps:
  - id: fetch_asa_data
    type: sub_workflow
    module: dingyue-module-asa-fetch
    idempotent: true           # 只读拉取,可重跑

  - id: build_excel
    type: sub_workflow
    module: dingyue-module-excel-report
    idempotent: true           # 生成文件到产物目录,可重跑

  - id: notify_team
    type: sub_workflow
    module: dingyue-module-slack-deliver
    # 不写 idempotent —— 默认 false,发消息不可重跑

三種 recovery.policy

policy含義適合場景
ABORT不自動恢復,等於回到默認行為測試階段
RESUME_FROM_LAST_INCOMPLETE默認。從第一個非 COMPLETED 的 step 開始重跑。數據管道、只讀 API 聚合、純計算
RESUME_FROM_START整條 workflow 從頭開始重跑數據源可能在中斷期間變化、需要刷新的場景

idempotent 怎麼標

判斷一個 step 是否 idempotent 的黃金標準:

"同樣的輸入跑兩次,會不會產生副作用?"

如果會(對外發消息、扣款、寫訂單),就不要加 idempotent。

Step 性質idempotent
只讀 API 查詢(拉報表、列 App)✓ true
純計算 / 數據轉換✓ true
生成 Markdown / Excel 到產物目錄✓ true(重跑前舊產物會被清理)
LLM 推理(無副作用工具)✓ true(會重新計 tokens,但語義安全)
發郵件 / Telegram / Slack / 飛書✗ false
寫入外部 DB / 改廣告出價 / 下單 / 扣款✗ false
Webhook 出站調用✗ false(除非對方 endpoint 明確去重)
manual_approval✗ false(續跑會再 ping 一次審批人,體驗差)
默認值是 false —— 安全為先

不寫 idempotent 默認是 false。RESUME_FROM_LAST_INCOMPLETE 遇到非冪等 step 會降級為 ABORT —— 不自動跑,留給你手動。

自動續跑不會發生的幾種情況

即使你配好了 recovery,以下幾種 execution 仍然不會自動續跑:

  • 觸發源是 Webhook —— Webhook payload 可能 at-most-once,平臺不知道上游是否會 retry。
  • 觸發源是 Scheduler —— scheduler 會按 cron 下一輪自行 re-fire。
  • 當前停在 manual_approval —— 等審批意味著本來就是阻塞狀態。
  • workflow 定義文件在中斷期間被修改 —— 平臺檢測到 hash mismatch,不確定新版是否兼容。

手動"從某一步重試"(隨時可用)

不管工作流有沒有配 recovery,執行詳情頁始終提供"從失敗步驟重試"按鈕:

  1. 打開一條 INTERRUPTED / FAILED 的 execution;
  2. 點失敗 / 中斷的 step 旁的「從這一步重試」;
  3. 前面已 COMPLETED 的 step 結果會被複用;這一步開始往下重新跑。

即使這一步不是 idempotent,你也可以手動重試 —— 因為這時是你作為人有意識地決定"值得重跑"。

續跑限額

防止系統把同一條 execution 來回重啟"死循環":每條 execution 最多自動續跑 3 次。超過仍然失敗就停下來等你處理。你可以在 recovery.maxAutoResumeAttempts 裡覆蓋(1-20)。

審計

每次自動續跑都會記審計事件:

  • execution.auto_resume — 成功續跑
  • execution.auto_resume.skipped — 按規則不應該續跑,帶 reason

Admin 可以在審計日誌裡按這兩個 event_type 過濾查看。

實戰建議

  • 純數據管道(ASA 日報、RSS 摘要):recovery + idempotent 全開,安心讓它自動續跑。
  • 含外部副作用的(扣款、發消息、下單):不要開 auto resume。中斷了人工決策。
  • 關鍵副作用步驟前加 manual_approval —— 審批本身是中斷續跑的"天然阻塞點"。

下一步