MySQL TaskStore command_executions 實作前確認
1. 文件目的
本文件整理 command_executions 是否要納入 MySQL TaskStore 下一批實作前,必須先確認的資料來源、欄位、索引、寫入策略、測試範圍與停止線。
本文件只做實作前確認,不直接新增 table、不執行 DDL、不連真實 DB、不修改 ITaskStore public method 簽章,也不修改 TaskExecutionRecord / TaskNodeExecutionRecord public constructor 或 property。
2. 目前已完成狀態
| 項目 | 狀態 | 說明 |
|---|---|---|
task_executions |
已完成 | 已完成 Save / FindById / ListRecent 與真實 DB manual-only 驗證。 |
node_executions |
已完成 | 已完成 schema、SQL builder、fake gateway、schema precheck、manual-only xUnit 入口與真實 DB 寫入 / 查詢 / cleanup 驗證。 |
TaskNodeExecutionRecord |
已存在 | 可提供 NodeId、DeviceId、CommandName、Status、RetryCount、DataSummary、MetadataSummary,但沒有 RawRequest / RawResponse / AdapterTimeTakenMs。 |
WorkflowNodeExecutionSnapshot |
已存在 | 可提供 RawRequestSummary、RawResponseSummary、AdapterTimeTakenMs、DataSummary、MetadataSummary,但目前只在 Workflow callback 當下使用。 |
LogEntry |
已存在 | 已承接 TaskId、NodeId、DeviceId、CommandName、RawRequestSummary、RawResponseSummary、AdapterTimeTakenMs、ErrorCode、Message。 |
MySqlTaskStore |
已完成 Task / Node | 目前負責任務主檔與節點摘要,不負責完整 log sink。 |
3. 為什麼不能直接照 node_executions 做
node_executions 可以直接由 TaskExecutionRecord.NodeRecords 寫入,資料來源已穩定。
command_executions 不同,因為它如果只寫 TaskNodeExecutionRecord.CommandName,會跟 node_executions 幾乎重複,沒有真正保存命令診斷價值;但如果要保存 RawRequest / RawResponse,現有 TaskNodeExecutionRecord 又沒有這些欄位。
因此 command_executions 的第一個決策不是「先建表」,而是先決定資料來源。
4. 資料來源候選
| 來源 | 可取得內容 | 優點 | 風險 / 限制 | 建議 |
|---|---|---|---|---|
TaskNodeExecutionRecord |
TaskId、NodeId、DeviceId、CommandName、Status、RetryCount、DataSummary、MetadataSummary | MySqlTaskStore.Save 已可直接取得,不需改資料流 |
沒有 RawRequest / RawResponse / AdapterTimeTakenMs,命令表會與 node table 重複 | 不建議作為完整 command_executions 第一版來源。 |
WorkflowNodeExecutionSnapshot |
RawRequestSummary、RawResponseSummary、AdapterTimeTakenMs、DataSummary、MetadataSummary | 最接近 Adapter 命令完成瞬間,診斷資訊最完整 | 目前 TaskStore 拿不到;若要保存需新增資料流或擴充任務紀錄模型 | 建議作為命令明細的主要資料來源,但需先確認是否可調整資料模型。 |
LogEntry |
RawRequestSummary、RawResponseSummary、AdapterTimeTakenMs、Message、ErrorCode | 已是 Log 流,符合診斷資料定位 | 屬 ILogWriter 職責,不應塞進 MySqlTaskStore.Save |
若目標是保存 Raw 診斷,建議走 DB LogWriter / TraceStore。 |
5. 建議決策
建議不要把 command_executions 直接塞入目前 MySqlTaskStore.Save(record)。
原因:
TaskStore的責任是任務主檔與節點摘要,不是完整命令診斷流。- RawRequest / RawResponse 可能包含敏感資訊或大量 payload,需要遮蔽與長度限制。
- 一個 Workflow node 未來可能執行多個 Adapter command,不能假設 node 與 command 永遠一對一。
- 若為了命令明細修改
TaskNodeExecutionRecord或TaskExecutionRecordpublic model,屬於停止線,必須先確認。
建議採兩段式:
| 階段 | 目標 | 做法 |
|---|---|---|
| 第一段 | 固定 command_executions 欄位草案與資料來源 |
先完成本文件與後續設計,不寫程式。 |
| 第二段 | 若需要 Raw 診斷,先設計 DB LogWriter / TraceStore | 從 LogEntry 或 Workflow snapshot 承接,不污染 TaskStore。 |
6. 若仍要建立 command_executions,建議 table 定位
command_executions 應定位為「Adapter / Device command 執行明細」,不是任務主檔,也不是一般 log table。
| Table | 職責 |
|---|---|
task_executions |
任務主檔與狀態摘要。 |
node_executions |
Workflow 節點歷程摘要。 |
command_executions |
設備命令執行明細,包含裝置、命令、耗時、Raw 摘要與錯誤摘要。 |
task_log_traces |
詳細 log / trace,建議由 DB LogWriter / TraceStore 管理。 |
7. 欄位草案
以下只是欄位草案,尚未同意前不得建立 table。
| 欄位 | 型別 | 必填 | 建議來源 | 說明 |
|---|---|---|---|---|
task_id |
varchar(64) |
是 | WorkflowNodeExecutionSnapshot.TaskId 或 LogEntry.TaskId |
任務識別碼。 |
sequence_no |
int |
是 | 寫入端產生 | 任務內命令順序,由 1 開始。 |
node_id |
varchar(64) |
是 | Snapshot / LogEntry | Workflow 節點識別碼。 |
node_name |
varchar(128) |
否 | Snapshot / LogEntry | Workflow 節點名稱。 |
device_id |
varchar(64) |
否 | Snapshot / LogEntry | 設備識別碼。 |
command_name |
varchar(128) |
否 | Snapshot / LogEntry | Adapter 命令名稱。 |
status |
varchar(32) |
是 | Snapshot / LogEntry | 命令結果狀態。 |
retry_count |
int |
是 | Snapshot / LogEntry | 節點執行時的 retry count。 |
executed_at |
datetime |
是 | Log timestamp 或寫入當下 | 第一版若無 command start/end,只記錄完成或寫入時間。 |
node_time_taken_ms |
int |
否 | Snapshot / LogEntry | 節點整體耗時。 |
adapter_time_taken_ms |
int |
否 | Snapshot / LogEntry | Adapter 命令耗時。 |
error_code |
varchar(64) |
否 | Snapshot / LogEntry | 命令失敗錯誤代碼。 |
message |
varchar(255) |
否 | Snapshot / LogEntry | 命令結果訊息摘要。 |
data_summary |
text |
否 | Snapshot / LogEntry | Adapter Data 摘要。 |
raw_request_summary |
text |
否 | Snapshot / LogEntry | RawRequest 安全摘要,不保存未遮蔽完整 payload。 |
raw_response_summary |
text |
否 | Snapshot / LogEntry | RawResponse 安全摘要,不保存未遮蔽完整 payload。 |
metadata_summary |
text |
否 | Snapshot / LogEntry | Metadata 摘要。 |
created_at |
datetime |
是 | 寫入當下 | 紀錄建立時間。 |
8. 主鍵與索引草案
建議第一版使用:
PRIMARY KEY (task_id, sequence_no)
建議索引:
| Index | Columns | 用途 |
|---|---|---|
idx_command_executions_task_id |
task_id |
查詢指定任務命令明細。 |
idx_command_executions_node_id |
node_id |
查詢特定節點的命令紀錄。 |
idx_command_executions_device |
device_id |
查詢設備命令歷程。 |
idx_command_executions_command |
command_name |
查詢特定命令歷程。 |
idx_command_executions_status |
status |
查詢失敗命令。 |
idx_command_executions_executed_at |
executed_at |
依時間排序與清理資料。 |
9. 寫入策略草案
在資料來源確認前,不建議實作。
若未來確認由 Workflow snapshot 或 LogEntry 寫入,建議:
- 每個 command 事件產生一筆
command_executions。 sequence_no在同一task_id內遞增。- 寫入失敗不可影響 Workflow 執行結果,但必須記錄錯誤。
- RawRequest / RawResponse 必須先經過摘要、遮蔽與長度限制。
- 若與
task_executions/node_executions同 transaction,需先確認是否接受命令明細寫入失敗導致整筆 task save 失敗。
10. 第一版不建議做的事
| 項目 | 不建議原因 |
|---|---|
直接由 TaskNodeExecutionRecord 寫 command_executions |
只能重複 node 摘要,無法保存 Raw 診斷。 |
為了 RawRequest / RawResponse 直接改 TaskNodeExecutionRecord public constructor |
會改 public contract,需先確認。 |
把 command_executions 跟 node_executions 一起塞入 MySqlTaskStore.Save |
職責可能過大,且一個 node 未來可能多 command。 |
| 保存完整 RawRequest / RawResponse | 可能包含敏感資訊或超大 payload。 |
| 一般 CI 執行真實 DB command 寫入測試 | 真實 DB 寫入必須 manual-only gate。 |
自動建立 command_executions table |
DDL / ALTER TABLE 屬高風險操作,需另行確認。 |
11. 測試策略建議
11.1 設計階段測試
| 測試 | 目的 |
|---|---|
| schema class parse 測試 | 確認欄位、主鍵、索引與 comment 可由 C# class 解析。 |
| SQL generator 測試 | 確認 MySQL 5.6.2 建表 SQL 可產生。 |
| payload sanitizer 測試 | 確認 RawRequest / RawResponse 摘要會遮蔽敏感資訊並截斷長度。 |
11.2 實作階段測試
需先決定資料來源後才能寫測試:
| 資料來源 | 測試方向 |
|---|---|
| Workflow snapshot | 驗證 snapshot 可轉 command row,且不遺失 Raw summary / AdapterTimeTakenMs。 |
| LogEntry | 驗證 DB LogWriter / TraceStore 可寫入 command row,且不影響 FileLogWriter / ConsoleLogWriter。 |
| TaskStore | 只有在使用者接受模型調整後,才測 MySqlTaskStore.Save 是否保存 command rows。 |
11.3 manual-only 真實 DB 驗證
若後續完成第一版實作,真實 DB 驗證仍需另列節點:
- 確認測試 DB,不使用正式 DB。
- 確認
command_executionstable、index、comment 已存在。 - 明確開啟 manual-only gate。
- 寫入至少兩筆 command rows,包含成功與失敗各一筆。
- 查回
task_id下的 command rows。 - 驗證 RawRequest / RawResponse 已遮蔽與截斷。
- cleanup 只清除本次
manual-taskstore-poc-前綴資料。
12. 必須停下確認的事項
以下任一項出現時,Codex 必須停下,不得自動執行:
- 修改
ITaskStorepublic method 簽章。 - 修改
TaskExecutionRecord/TaskNodeExecutionRecordpublic constructor 或 property。 - 新增正式
command_executionstable 或執行 DDL。 - 對真實 DB 執行未經確認的
INSERT、UPDATE、DELETE。 - 把真實 DB 測試加入一般 CI。
- 保存或輸出 password、完整 connection string、Token。
- 保存未遮蔽完整 RawRequest / RawResponse。
- 導入 WebApi、ServiceHost、背景服務或正式 DB apply 啟動流程。
- 新增或更換資料庫套件。
13. 建議結論
command_executions 建議先不要直接實作進 MySqlTaskStore.Save。
較安全的下一步是先做「DB LogWriter / TraceStore 邊界設計」,確認 RawRequest / RawResponse 應由 Log 流保存,還是要擴充 TaskStore 模型。
若使用者確認仍要先做 command_executions,建議下一份文件先整理「command_executions 資料來源決策表」,在三個方案中選一個:
TaskNodeExecutionRecord簡版命令表,不保存 Raw 診斷。WorkflowNodeExecutionSnapshot命令明細表,需新增資料流。LogEntry/ DB LogWriter 命令明細表,與 TaskStore 分離。
本次建議採第 3 種方向優先分析,避免把詳細診斷資料塞進 TaskStore。