# 09 故障排除手冊

主要讀者：平台維護者、系統維運、值班工程師。

```mermaid
flowchart TD
  A[測試未完成或結果不可信] --> B{主要症狀？}
  B -->|沒有新 Run 或持續執行中| C[查觸發器、環境與執行日誌]
  B -->|初始化或案例異常| D[查資料準備、Step 錯誤與相依結果]
  B -->|沒收到報告或通過率可疑| E[查 Run 範圍、案例數及通知條件]
  C --> F[維護者初判並交對應人員]
  D --> F
  E --> F
  F --> G[確認環境安全後決定是否重跑整個 Plan]
  G --> H[保留原 Run 並核對新結果]
```

## 1 共用唯讀診斷

夜間採固定時間強制關閉，包含初始化失敗、中斷及卡住情境。值班時先在剩餘時間內保存線索，不能為除錯、寄報告或等待上傳延後關閉；早晨環境重新啟用後再追查。確切關閉時間與資源清單由環境設定提供。

先取得 `triggerNum`、`planNum`、`envNum`、`runNum` 及事件時間。以平台查詢結果或核准的唯讀資料庫連線診斷，不直接重新初始化資料、不修改 Run 為成功、不清除未知的 cache。

### 1-1 執行紀錄查詢

下列 SQL 使用 psql 變數 `run_num`。狀態值因層級不同而不同：Run 的 `3` 是完成，Case 的 `3` 是通過，Step 的 `3` 是錯誤。

```sql
BEGIN READ ONLY;
SET LOCAL statement_timeout = '10s';
SELECT run_num, plan_num, trigger_num, env_num, run_status,
       expected_suite_count, expected_case_count,
       run_start_time, run_end_time
FROM qa.qa_c008
WHERE run_num = :'run_num'::bigint;

SELECT s.run_suite_num, s.suite_num, c.run_case_num, c.case_num,
       c.case_status, c.case_start_time, c.case_end_time
FROM qa.qa_c009 s
JOIN qa.qa_c010 c ON c.run_suite_num = s.run_suite_num
WHERE s.run_num = :'run_num'::bigint
ORDER BY s.run_suite_num, c.run_case_num;

SELECT c.run_case_num, d.run_step_num, d.step_num,
       d.step_order, d.step_type, d.step_status,
       d.step_start_time, d.step_end_time
FROM qa.qa_c009 s
JOIN qa.qa_c010 c ON c.run_suite_num = s.run_suite_num
JOIN qa.qa_c011 d ON d.run_case_num = c.run_case_num
WHERE s.run_num = :'run_num'::bigint
ORDER BY c.run_case_num, d.step_order, d.run_step_num;
ROLLBACK;
```

錯誤詳情可進一步查 `runLog`、`stepError`、`stepResult` 與 `postProcResp`。請求、回應及設定可能含敏感資訊，交班前遮罩。不要整份貼上 Environment 設定或認證日誌。

### 1-2 觸發器及環境重疊查詢

`trigger_num` 與 `env_num` 由事件紀錄提供。

```sql
BEGIN READ ONLY;
SET LOCAL statement_timeout = '10s';
SELECT trigger_num, plan_num, env_num, is_enabled,
       cron, last_run_time, next_run_time, notice_group_code
FROM qa.qa_c007
WHERE trigger_num = :'trigger_num'::bigint;

SELECT run_num, trigger_num, plan_num, run_status,
       run_start_time, run_end_time
FROM qa.qa_c008
WHERE env_num = :'env_num'::bigint
ORDER BY run_start_time DESC
LIMIT 30;
ROLLBACK;
```

只看到不同的 `envNum` 不代表實際資料來源隔離；須由維護者核對真正共用的服務與資料。資料模型與欄位定義見[資料模型](04_DATA_MODEL_AND_STORAGE.md)及[資料字典](05_DATA_DICTIONARY.md)。

### 1-3 日誌搜尋

`LOG_FILE` 是本次事件已取得的日誌檔。先按時間及 Run 範圍縮小，再查以下訊息。

```bash
rg -n 'launchScheduledPlan|asyncExecuteTaskHandle triggerNum|作業打架|排程失敗|cronText不得為空' "$LOG_FILE"
rg -n 'truncateAndInitDataByInTable|truncateTable start|initDataFromInTable start|test plan execute fail' "$LOG_FILE"
rg -n 'compareResultReportWorker|uploadJacoco|sendReport start|sendReport end|sendReportAsync error' "$LOG_FILE"
```

`sendReport end` 不能證明 Email 已送達，因管理端寄信流程仍可能捕捉錯誤。初始化的結束訊息也不能證明每張表成功，須檢查其間的錯誤與實際資料。

### 1-4 夜間保存與早晨核對

| 時段 | 操作要求 |
| :--- | :--- |
| 夜間截止前 | 持續保存 Run／Case／Step 識別值、最後進度、錯誤與關閉事件至關閉後仍可讀的儲存；臨近截止只補充可在剩餘時間內完成的線索，不啟動重跑 |
| 固定截止時間 | 仍強制關閉，不等待完整診斷、Email 或上傳。儲存機制不能只依賴關閉前最後一次 flush；現有持久保存實作仍須驗證 |
| 早晨重新啟用後 | 先查原 Run、關閉時間與最後已保存步驟，核對共用資料及外部操作狀態。Run 可能仍為 RUNNING；不誤認原程序還活著，也不直接改成通過 |
| 決定恢復 | 維護者初判並協調修正，確認環境安全後才決定重跑整個 Plan；新 Run 與原 Run 都保留 |

下列「5 分鐘」是診斷時間上限；若距固定關閉時間不足 5 分鐘，以關閉截止為準。

## 2 沒有新 Run、執行停滯或 EKS 狀態不明

| 項目 | 操作 |
| :--- | :--- |
| 症狀 | 到期沒有新 Run、Run 長時間 RUNNING、早晨環境無法使用，或日誌出現「作業打架」 |
| 快速診斷 | 使用 1-1／1-2 查最新 Run 與觸發器；比對 `isEnabled`、`nextRunTime`、執行來源及 Northstar 日誌；由環境窗口查實際 EKS 資源與服務就緒狀態 |
| 第 0～1 分鐘 | 區分「尚未受理」和「已建立 Run 後停住」；記下最後一個已保存的 Step 與時間 |
| 第 1～3 分鐘 | 確認同環境是否還有人或其他工作使用；核對執行來源是否匹配、服務是否可連線。排程重複 Trigger 被略過不表示已排隊 |
| 第 3～5 分鐘 | 夜間停止新增人工重跑要求，在截止前保存最後線索，固定時間照常強制關閉；早晨啟用後核對原 Run、關閉事件與外部操作，未確認前不重置共用資料 |
| 復原驗證 | 早晨能查原 Run 與關閉前最後線索；仍為 RUNNING 的紀錄可和關閉事件對照，不能假設已寫 INTERRUPTED；確認環境可用與原操作狀態後，由維護者決定補跑，新 Run 不覆蓋舊 Run |
| 升級條件 | 無法確認外部操作是否停止、同環境多個 Run 同時初始化、確切關閉設定不明、持久線索缺漏或多個計畫受影響，升級平台維護者及環境維運窗口 |

### 2-1 現況限制

| 檢查點 | 必須注意 |
| :--- | :--- |
| 防重複範圍 | 排程使用 Trigger 級 cache；不是資料來源級或環境級互斥，也不是持久化佇列 |
| 下次排程 | 執行前就更新下次時間；更新時間出錯的處置需查日誌，不可單憑時間已更新認定跑過 |
| 即時執行 | 不更新排程時間，但沒有相同的排程 cache 保護流程 |
| EKS | 正常完成自動關閉；初始化失敗、中斷、卡住也到固定時間強制關閉。保留線索供早晨啟用後查核；確切時間及實際保存機制待核對 |
| 停機錯過排程 | 需求為人工決定是否補跑；程式查詢到期工作，部署恢復行為須另驗證 |

## 3 初始化不完整、案例錯誤或相依跳過異常

| 項目 | 操作 |
| :--- | :--- |
| 症狀 | 初始化日誌有錯但後續案例仍執行、Case ERROR、前置案例本次通過卻被跳過，或前置 ERROR 後仍執行 |
| 快速診斷 | 查初始化前後錯誤、Environment 是否有 `dataSources`、核定的初始化／排除範圍；以 1-1 SQL 只取本次 Run 的 Case／Step 結果 |
| 第 0～1 分鐘 | 保存 Run 與第一個錯誤位置；分辨資料準備錯誤、斷言不符及請求例外 |
| 第 1～3 分鐘 | 核對固定資料是否事先備妥；若是相依問題，逐一比對本次前置案例的結果及是否選入 Plan，避免混用歷史結果 |
| 第 3～5 分鐘 | 夜間先保存初始化錯誤及最後進度，固定時間強制關閉。早晨由案例／資料準備者與平台工程師核對原 Run、修正基準及狀態傳遞；維護者確認安全後才決定重跑 |
| 復原驗證 | 初始化所需資料齊全、受影響 Case 的預期與實際一致；本次相依判斷正確，新舊 Run 均保留；重驗 UAT-01～03 |
| 升級條件 | 初始化清空範圍超出預期、白天資料受影響、無法辨識已執行的寫入步驟、跨次相依結果混入，立即升級平台工程師與資料庫／受測系統負責人 |

### 3-1 不可只依結束狀態判斷

| 現況 | 診斷方式 |
| :--- | :--- |
| 無 `dataSources` 會略過初始化 | 核對該 Plan 是否需要初始化，不能當成資料已驗證就緒 |
| 單表初始化、終止連線及序列設定部分錯誤只寫 log | 查看完整錯誤區間及必要資料，不以初始化方法返回成功取代檢查 |
| 相依查詢未限制本次 Run，且只判斷 FAILED | 對照本次 Run 的前置結果；ERROR、無結果及歷史結果都列入差異調查 |
| Case ERROR 可能仍使 Run FINISHED | 查案例與步驟，不只查 Run 狀態 |
| DEPENDENT_FAILED 分支未寫結束時間 | 不以案例缺結束時間直接判定仍在執行 |

## 4 報告未寄送、通過率可疑或結果缺漏

| 項目 | 操作 |
| :--- | :--- |
| 症狀 | Run FINISHED 但未收到 Email、報告顯示 100% 但沒有案例，或報告和預計案例數不同 |
| 快速診斷 | 查單次 Run 的一般 Case 結果、`expectedCaseCount`、通知群組及寄信日誌；確認是否系統身分或指定 `needsSendReport=Y` |
| 第 0～1 分鐘 | 先開平台結果；確認 Run 是否中斷及是否真的有執行案例，不以沒有 Email 判為沒執行 |
| 第 1～3 分鐘 | 核對報告只屬於該 `runNum`；一般 Case 才計入案例統計，hooks 與一般案例分開；比較 PASSED、FAILED、ERROR、DEPENDENT_FAILED 與未執行數 |
| 第 3～5 分鐘 | 保存通知或結果寫入失敗線索，不能為重寄或上傳延後固定關閉。早晨由平台／通知維運窗口追查；若只是通知失敗，不重跑測試 |
| 復原驗證 | 平台結果可查、報告案例分母正確、收件對象符合設定；報告與原 Run 對應；重驗 UAT-02／05 |
| 升級條件 | Run 與結果階層關聯斷裂、跨 Run 混入、報告洩漏認證資訊或無法區分未執行，升級平台工程師與維護者 |

### 4-1 報告解讀規則

| 項目 | 解讀 |
| :--- | :--- |
| FINISHED | 主流程結束；不是全過、寄信成功或環境已關閉 |
| 寄送條件 | 正常流程後，系統身分執行或該次指定寄信；中斷路徑不保證寄報告 |
| 分母 | 以 Run 已保存的一般案例紀錄統計，不含 hooks；仍需和預計選案數比對 |
| 零案例 | 現況通過率計算會回 100%，不能據此宣稱執行成功；須標示無案例並追查選案與結果 |
| 結果缺漏 | 平台 API 或結果寫入失敗不等於「沒有失敗案例」，不可補成綠燈 |

## 5 復原交班

| 必要紀錄 | 內容 |
| :--- | :--- |
| 受影響範圍 | Plan、Trigger、Environment、Run 與時間；是否影響白天共用資料 |
| 處置與原因 | 已確認的錯誤來源、修正內容、固定與實際關閉時間、持久線索位置，以及早晨仍待核對的資料／操作狀態 |
| 人工重跑 | 維護者決定、完整 Plan 範圍、新 Run 及原 Run 對應；不覆寫舊結果 |
| 最終證據 | 步驟與案例結果、報告狀態、環境可用性及仍未完成事項 |

依[驗收文件](06_UAT_AND_VERIFICATION.md)重驗受影響案例。固定強制關閉政策已確認；實際截止時間、資源清單及線索保存機制仍須核對部署設定。本手冊提供診斷與交班步驟，不以臨時手動命令替代環境既有關閉控制。
