# 監控週期

本頁說明 go-web-monitor 何時檢查網站、如何並行處理，以及每輪結果如何寫回設定檔與畫面。

## 觸發時機

| 觸發 | 來源 | 行為 |
|------|------|------|
| 啟動 | `UI.start()`（`internal/service/ui.go:96`） | 介面啟動後立刻執行一輪 `Monitor.Update()` |
| 每分鐘 | `time.NewTicker(1 * time.Minute)` | 固定間隔執行 `Update()`，間隔不可設定 |
| `refresh` 指令 | `handleCommand` | 在背景 goroutine 立刻執行一輪 `Update()` |
| `add <url>` 指令 | `Monitor.Add()` | 只檢查新增的那一個網站 |

結束程式時（`quit` 或 <kbd>Ctrl+C</kbd>）會關閉 quit channel，排程迴圈隨之停止。

## 一輪檢查的流程

```mermaid
sequenceDiagram
    participant U as UI
    participant M as Monitor
    participant W as 目標網站
    participant F as .webMonitor.json
    U->>M: Update()
    par 每個網站一個 goroutine
        M->>W: Check(url)
        W-->>M: model.Website
        M->>M: 更新失敗計數，必要時寄告警
    end
    M->>F: Save()
    U->>U: QueueUpdateDraw(updateUI)
```

1. `Update()`（`internal/service/monitor.go:159`）對監控清單中的每個網址各開一個 goroutine，以 `sync.WaitGroup` 等待全部完成。
2. 每個 goroutine 呼叫 `Check()` 取得狀態碼、耗時與 SSL 剩餘天數（見 [HTTP 探測](/zh/probing)、[SSL 憑證到期](/zh/ssl-expiry)）。
3. 依結果更新該網站的失敗計數，連續第 5 次離線時寄出告警（見 [告警規則](/zh/alerting)）。
4. 全部完成後呼叫 `Save()`，把整份狀態與 SMTP 設定覆寫進 `.webMonitor.json`。
5. 介面以 `QueueUpdateDraw` 重繪表格與 System 面板。

## 耗時上限

一輪的總耗時取決於最慢的網站。單一網站最壞情況是 HEAD 與 GET 各等到 10 秒逾時，加上 SSL 憑證連線；網站之間並行，不會累加。

## 寫回設定檔的時機

| 時機 | 寫入內容 |
|------|---------|
| 每輪 `Update()` 結束 | 全部網站狀態＋SMTP 設定 |
| `add`／`del` 成功後 | 同上 |
| 任何 `smtp <key> <value>` 指令後 | 同上 |

寫入方式是整份覆寫（`util.Save`），程式執行中手動編輯的內容會被覆蓋。
