文件

架構

本頁說明 go-scheduler 如何解析排程、分派任務、追蹤依賴,以及在停止時完成收尾。

系統總覽

graph TB
    App[應用程式] --> Cron[cron 排程器]
    Cron --> Parser[Cron 解析器]
    Cron --> Heap[任務最小堆]
    Cron --> Depend[依賴子系統]
    Depend --> Workers[依賴 Worker]
    Heap --> Runner[任務執行器]
    Workers --> Runner
    Runner --> State[任務狀態更新]

排程器生命週期

core.New 建立排程器,初始化時區、logger、channel、最小堆、解析器與依賴管理器。當 Config.Locationnil 時,排程器使用 time.Local。logger 優先寫入 syslog;syslog 無法使用時,回退至 stderr。

排程器執行期間重複呼叫 Start 不會重複啟動。Start 會啟動依賴 Worker,為已註冊任務計算第一次觸發時間,接著進入事件迴圈。事件迴圈以 timer 等待最小堆中最近的任務;timer 觸發後,排程器取出到期任務、分派執行,並在仍有下一次觸發時間時重新放回堆中。

AddRemoveRemoveAll 可以在排程器執行期間呼叫,此時透過 channel 安全地更新事件迴圈;在 Start 之前則直接更新最小堆。Stop 會停止事件迴圈與依賴 Worker,並回傳一個在所有進行中任務結束後才取消的 context。

排程流程

  1. Add 解析五欄位 Cron、描述符或 @every 間隔。
  2. 任務取得單調遞增的 int64 ID,並加入最小堆。
  3. Start 依設定的時區計算下一次觸發時間。
  4. 事件迴圈取出最近到期的任務。
  5. 沒有依賴的任務直接執行;有依賴的任務加入依賴佇列。
  6. 任務結果將狀態更新為完成或失敗。
  7. 週期任務取得新的觸發時間,再次加入最小堆。

依賴子系統

具有依賴的任務會保存一組 Wait。依賴 Worker 透過管理器檢查每個前置任務:

前置任務狀態 Wait.State 後續任務行為
已完成 任一 繼續檢查其他前置任務。
失敗 Stop 依賴檢查失敗,後續任務不執行。
失敗 Skip 略過該失敗前置任務,繼續等待其他任務。
等待中或執行中 任一 持續等待完成或逾時。
不存在 任一 回傳找不到依賴任務的錯誤。

依賴子系統至少啟動兩個 Worker;當主機 CPU 數量大於兩個時,Worker 數量會擴充至 runtime.NumCPU()。依賴檢查使用 context 控制逾時;當等待時間為零時,Worker 佇列使用一分鐘的預設值。

排程資料結構

排程器使用按照 task.next 排序的 taskHeap 最小堆,因此事件迴圈只需要等待堆頂項目。解析結果實作共用的 schedule 介面。Cron 排程會逐分鐘向前搜尋符合時間;@every 排程則以目前時間加上固定間隔計算下一次觸發時間。

Cron 欄位支援 *、單一數值、範圍、逗號分隔列表與 */n 步進格式。任務加入前,解析器會依照各欄位允許的範圍驗證輸入。

執行與失敗處理

每個任務都會記錄 pending、running、completed 或 failed 狀態。任務動作可以是 func()func() error;啟用依賴的任務必須回傳 error,才能傳遞失敗結果。設定執行時限後,任務會在 deadline 下執行,逾時時呼叫 onDelay。回傳錯誤與捕捉到的 panic 都會被視為任務失敗。

請參閱核心概念了解排程與依賴行為,並參閱 API 參考了解可呼叫的方法。

EN