# Schema Inspector 與 Dry Run Plan 串接服務設計

## 1. 文件目的

本文件整理 `Schema Inspector` 與 `Dry Run Plan` 之間是否需要一個串接服務，以及該服務的責任邊界、輸入輸出、錯誤處理與測試案例。

暫定服務名稱為：

> `SchemaDryRunPlanner`

本節點仍屬於設計整理，不導入 MySQL 套件、不連線資料庫、不查詢 `information_schema`，也不執行 DDL。

## 2. 為什麼需要串接服務

目前已完成：

| 已有元件 | 責任 |
|---|---|
| `ISchemaInspector` | 取得目前 schema snapshot |
| `MockSchemaInspector` | 不連 DB 的 schema snapshot 來源 |
| `SchemaDefinition` | 表示目標 schema 或目前 DB schema |
| `MySqlSchemaSqlGenerator` | 產生 `CREATE TABLE`、`ADD COLUMN`、`ADD INDEX` 與 Dry Run Plan |
| `SchemaMigrationPlan` | 表示 schema 差異與建議 SQL |

若未建立串接服務，未來 ConsoleHost、Schema Initializer 或測試程式可能會各自手動組合：

1. 呼叫 inspector。
2. 判斷 inspector 是否失敗。
3. 呼叫 SQL generator。
4. 合併 warnings。
5. 回傳 plan 或 error。

這會讓錯誤處理與流程組合分散。建立 `SchemaDryRunPlanner` 可把這段流程集中，讓後續真實 MySQL inspector 或 ConsoleHost 只接同一個入口。

## 3. 建議責任邊界

| 責任 | 是否屬於 `SchemaDryRunPlanner` | 說明 |
|---|---|---|
| 呼叫 `ISchemaInspector` | 是 | 取得目前 schema snapshot |
| 接收目標 `SchemaDefinition` | 是 | 目標 schema 由 Schema Parser 或呼叫端提供 |
| 呼叫 `GenerateDryRunPlan` | 是 | 產生差異計畫 |
| 合併 inspector warnings 與 plan warnings | 是 | 讓呼叫端一次取得完整提醒 |
| 回傳標準結果 | 是 | 需包含 success、plan、error、warnings |
| 連線 MySQL | 否 | 由真實 inspector 負責 |
| 查詢 `information_schema` | 否 | 由真實 inspector 負責 |
| 執行 DDL | 否 | 由後續 executor / initializer 負責 |
| ConsoleHost 顯示 | 否 | Host 只負責呈現 |

## 4. 建議模型

### 4.1 `SchemaDryRunRequest`

| 欄位 | 說明 |
|---|---|
| `TargetSchema` | 目標 schema definition |
| `InspectRequest` | 傳給 `ISchemaInspector` 的讀取條件 |
| `CorrelationId` | 可選，方便串接 log 與驗證紀錄 |

### 4.2 `SchemaDryRunResult`

| 欄位 | 說明 |
|---|---|
| `Success` | 是否成功產生 dry run plan |
| `Plan` | `SchemaMigrationPlan` |
| `Warnings` | inspector 與 plan 的合併提醒 |
| `Error` | 失敗時的標準錯誤資訊 |
| `TimeTakenMs` | 串接流程耗時 |

## 5. 建議流程

```text
Target Schema
    |
    v
SchemaDryRunPlanner
    |
    +--> ISchemaInspector.Inspect()
    |       |
    |       v
    |   Current Schema Snapshot
    |
    +--> MySqlSchemaSqlGenerator.GenerateDryRunPlan(target, current)
            |
            v
        SchemaMigrationPlan
```

## 6. 錯誤處理規則

| 情境 | 建議處理 |
|---|---|
| request 為 null | 回傳失敗 result |
| target schema 為 null | 回傳失敗 result |
| inspector 為 null | 建構或執行時回傳失敗 result |
| generator 為 null | 建構或執行時回傳失敗 result |
| inspector 失敗 | 直接回傳失敗 result，保留 inspector error |
| generator 失敗 | 回傳失敗 result，保留 plan error |
| inspector warnings | 合併到 result warnings |
| plan warnings | 合併到 result warnings |

不得只回傳 `bool`，也不得吞掉 exception。

## 7. 測試案例建議

| 測試案例 | 驗證目的 |
|---|---|
| mock inspector 回傳完整 schema | plan 成功且不產生 SQL |
| mock inspector 回傳空 schema | plan 產生 create table |
| mock inspector 缺少 column / index | plan 產生 add column / add index |
| mock inspector 欄位型別不同 | plan 產生 manual review |
| inspector 回傳失敗 | planner 回傳失敗並保留 error |
| inspector warnings | planner result 包含 warnings |
| request 為 null | planner 回傳標準錯誤 |
| target schema 為 null | planner 回傳標準錯誤 |
| 不執行 DDL | 測試確認只產生 plan，不連線、不執行 SQL |

## 8. 建議放置位置

`SchemaDryRunPlanner` 建議先放在 Core 的 `Schema` 區，原因：

- 它只依賴抽象 `ISchemaInspector` 與既有 schema model。
- 它不依賴 MySQL 套件。
- 它不負責真實 DB 連線。
- 它可用 mock inspector 進行純單元測試。

但後續真實 `MySqlSchemaInspector` 與 DDL executor 不應放入 Core。

## 9. 明確不納入

| 不納入項目 | 原因 |
|---|---|
| `MySqlConnector` | 此節點不需要真實連線 |
| `information_schema` SQL | 真實 inspector 節點再處理 |
| DDL executor | 高風險，需另行確認 |
| ConsoleHost 自動建表 | 需等 planner 與 executor 邊界完成 |
| Secret / password | 此節點不需要任何敏感資訊 |

## 10. 建議決策

建議採用 `SchemaDryRunPlanner`，先做一個不執行 DDL 的純流程服務。

這樣下一步可以安全實作：

- 新增 request / result model。
- 新增 planner。
- 使用 `MockSchemaInspector` 驗證完整流程。
- 不導入 MySQL 套件。
- 不連線 DB。
- 不改 ConsoleHost 啟動方式。

## 11. 建議下一步

若本設計確認，下一步可進入：

> `SchemaDryRunPlanner 第一版實作`

建議實作內容：

- `SchemaDryRunRequest`
- `SchemaDryRunResult`
- `SchemaDryRunPlanner`
- 單元測試

仍不做：

- 真實 MySQL inspector。
- `MySqlConnector`。
- `information_schema` 查詢。
- DDL executor。
- ConsoleHost 自動建表。
