# 架構

本頁以單張概覽圖說明 go-scheduler 的元件分層與跨元件原則。

## 系統概覽

```mermaid
graph TB
    App[呼叫端] --> Cron[cron 排程器]
    Cron --> Parser[表達式解析器]
    Cron --> Heap[任務最小堆]
    Heap --> Loop[事件迴圈 goroutine]
    Loop -->|無依賴| Direct[goroutine 直接執行]
    Loop -->|有依賴| Queue[Wait 佇列]
    Queue --> Workers[依賴 Worker 池]
    Workers --> Manager[dependManager]
    Direct --> State[任務狀態]
    Manager --> State
```

## 分層

| 層 | 元件 | 檔案 | 職責 |
|---|---|---|---|
| 公開介面 | `cron` | `core/instance.go`、`core/add.go`、`core/remove.go`、`core/task.go` | `New`／`Start`／`Stop`／`Add`／`Remove`／`RemoveAll`／`List` |
| 解析 | `parser` | `core/schedule.go` | 將 spec 轉為 `scheduleResult`（Cron、描述符）或 `delayScheduleResult`（`@every`） |
| 排程 | `taskHeap` | `core/task.go` | 依 `next` 排序的最小堆，事件迴圈只等待堆頂 |
| 執行 | `cron.runAfter` | `core/instance.go` | 無依賴任務：goroutine 執行、超時、panic recover |
| 依賴 | `depend`、`dependManager` | `core/depend.go`、`core/dependManager.go` | 佇列（容量 1024）、Worker 池、前置狀態輪詢與結果更新 |

## 跨元件原則

| 原則 | 實作 |
|---|---|
| 單一事件迴圈擁有最小堆 | `Start` 後的新增、移除、清空都經由 `add`／`remove`／`removeAll` channel 送入迴圈；`Start` 前直接改寫最小堆 |
| 狀態以任務層級鎖保護 | 每個 `task` 持有 `sync.RWMutex`，依賴檢查以讀鎖讀取前置任務 `state` |
| 依賴任務與一般任務分流 | `cron.run` 依 `after` 是否為空決定直接執行或進入 Worker 佇列 |
| Worker 數量有上限 | `runtime.NumCPU()` 大於 2 時取 CPU 數，否則為 2 |
| 關閉不強制中斷 action | `Stop` 等待 WaitGroup 與 Worker 結束，action 本身不接收 context |

## 延伸閱讀

- [任務模型](/zh/core-concepts) — 任務狀態
- [任務依賴](/zh/core-concepts-dependencies) — 依賴判斷規則
- [完整架構文件](https://github.com/pardnchiu/go-scheduler/blob/main/doc/architecture.zh.md) — 各模組詳細圖、資料流與狀態機
