TaskTraceStore 介面命名與 DTO 位置盤點
本文件承接 TaskTraceStore public 查詢介面實作前確認 與 第三階段執行儀表板,整理程式 repo 目前的命名、Result 風格、MySQL infrastructure 分層與 sync / async 慣例。
本文件只做盤點與建議,不新增 public interface、不新增 DTO、不修改 ITaskStore / ILogWriter、不修改資料庫欄位、不連真實 DB,也不導入 WebApi / ServiceHost / WinForms Debug Tool。
盤點範圍
| 項目 | 盤點結果 |
| 程式 repo | Hongsen-tw/hs-device-control-template |
| 主要分支 | poc/nmodbus-tcp |
| 盤點日期 | 2026-06-03 |
| 盤點方式 | 讀取 Core、Tasks、Logging、Infrastructure.MySql 與對應測試檔。 |
Core Result 與 Error 風格
| 檔案 / 類型 | 目前設計 | 對 3A 的影響 |
HS.DeviceControl.Core.Common.Result | 非泛型 sealed class,包含 Success、Message、Error,用 Ok() / Fail() 建立結果。 | 先前草案的 Result<TaskTraceQueryResult> 不能直接使用;若要新增泛型 Result,會影響 public contract,需另行確認。 |
HS.DeviceControl.Core.Common.ErrorInfo | 錯誤資訊包含 Code、Message、ExceptionType、StackTrace。 | Trace 查詢失敗應維持使用 ErrorInfo,避免只回傳 bool 或未整理例外。 |
HS.DeviceControl.Core.Common.ErrorCodes | 目前已有 workflow、device、config、schema 類錯誤碼,尚未有 trace query 錯誤碼。 | 若要新增 TraceQuery... 錯誤碼,會修改 public constant,需在實作前確認。 |
| Schema 類 result | 既有 SchemaDryRunResult、SchemaInitializerResult、SchemaInspectResult 等專用 result 類型。 | 3A 可以採用專用 TaskTraceQueryResult,內含 Success、Items、Error、TimeTakenMs,比新增泛型 Result 更保守。 |
既有 Store 與 Logging 契約
| 類型 | 目前職責 | 對 3A 的建議 |
ITaskStore | 任務執行摘要的 Save、FindById、ListRecent。 | 不應混入 trace 查詢,避免 TaskStore 同時承擔大量診斷資料 read-side。 |
InMemoryTaskStore | 記憶體版任務摘要 store。 | 可作為同步介面與測試替身的風格參考。 |
ILogWriter | 只負責 Write(LogEntry entry)。 | 不應增加查詢方法,否則 write-side / read-side 會混在一起。 |
LogEntry | Workflow 節點與 Adapter data 的診斷摘要。 | Trace 查詢 item 應對應 task_log_traces 欄位,但不應直接重用 LogEntry,因為 LogEntry 是寫入模型。 |
MySQL Infrastructure 命名慣例
| 現有類型 | 命名與分層慣例 |
MySqlTaskStore | public store class,實作 Core 的 ITaskStore。 |
IMySqlTaskStoreGateway | internal gateway interface,用於隔離 MySQL 連線與 fake gateway 測試。 |
MySqlTaskStoreSqlBuilder | internal SQL builder,負責參數化 SQL。 |
MySqlTaskStoreOptions | public options,保存 host、port、database、user、password、table、timeout、ssl mode。 |
MySqlLogWriter | public writer class,實作 Core 的 ILogWriter。 |
IMySqlLogWriterGateway | internal gateway interface,fake gateway 測試沿用此入口。 |
MySqlLogWriterSqlBuilder | internal SQL builder,寫入 task_log_traces。 |
MySqlLogTraceRecord | internal row / command model,不外露給 Core。 |
MySqlTaskLogTraceSchema | internal schema class,已定義 task_log_traces 欄位、索引與 comment。 |
3A 建議沿用「public read-side store + internal gateway + SQL builder + row mapper + options validator」的分層,不建議把查詢 SQL 放在 ConsoleHost、測試或文件工具中。
sync / async 盤點
目前 MySQL infrastructure 的主要 store / writer 都是同步介面:
| 類型 | 方法型態 |
ITaskStore | void Save(...)、TaskExecutionRecord FindById(...)、IReadOnlyList<TaskExecutionRecord> ListRecent(...) |
MySqlTaskStore | 同步呼叫 ExecuteNonQueryBatch、QuerySingle、QueryList |
ILogWriter | void Write(LogEntry entry) |
MySqlLogWriter | 同步呼叫 gateway 寫入 |
3A 第一版建議採同步方法,先與現有 MySQL infrastructure 一致;未來若進入 WebApi / ServiceHost,再另外評估 async public contract。
建議命名與放置位置
| 項目 | 建議 | 理由 |
| Core 查詢介面 | ITaskTraceStore | 延續 ITaskStore 語意,但職責清楚分成 trace read-side。 |
| Core namespace | HS.DeviceControl.Core.Logging | Trace 來源是 LogEntry / task_log_traces,放在 Logging 比放在 Tasks 更能避免與任務主檔混淆。 |
| Request DTO | TaskTraceQueryRequest | 表示查詢條件,不承擔 SQL 或 MySQL 細節。 |
| Result DTO | TaskTraceQueryResult | 建議使用專用 result 形狀,避免此階段新增泛型 Result<T>。 |
| Item DTO | TaskTraceItem | 表示已遮罩、可回傳給 Debug Tool / API 的 trace row。 |
| MySQL 實作 | MySqlTaskTraceStore | 放在 HS.DeviceControl.Infrastructure.MySql.Logging,查詢 task_log_traces。 |
| MySQL options | MySqlTaskTraceStoreOptions | 不直接重用 MySqlLogWriterOptions,避免查詢能力被寫入器命名綁住。 |
| MySQL internal helper | IMySqlTaskTraceStoreGateway、MySqlTaskTraceStoreSqlBuilder、MySqlTaskTraceRowMapper | 延續現有 fake gateway 與 SQL builder 測試方式。 |
建議 public method 草案
以下只是下一步實作前確認的建議,不代表已同意新增 public method:
TaskTraceQueryResult Query(TaskTraceQueryRequest request);
不建議本階段直接使用:
Result<TaskTraceQueryResult> Query(TaskTraceQueryRequest request);
原因是目前 Core 沒有泛型 Result<T>,若為 3A 新增泛型 Result,會變成另一個 public contract 決策,超出 Trace 查詢第一版的必要範圍。
建議 DTO 欄位
TaskTraceQueryRequest
| 欄位 | 建議 |
TaskId | 可選;若空白,需至少提供時間範圍或其他篩選條件。 |
NodeId | 可選。 |
DeviceId | 可選。 |
CommandName | 可選。 |
Level | 可選。 |
Status | 可選。 |
ErrorCode | 可選。 |
CreatedFrom / CreatedTo | 可選;CreatedTo 不可早於 CreatedFrom。 |
Limit | 預設 100,最大 500。 |
Offset | 預設 0,不可小於 0。 |
SortDescending | 預設 true,第一版只允許依 created_at 排序。 |
TaskTraceQueryResult
| 欄位 | 建議 |
Success | 是否查詢成功。 |
Items | 查回的 trace 清單。 |
Limit / Offset | 回傳本次查詢分頁資訊。 |
HasMore | 建議用 Limit + 1 判斷,不在第一版做昂貴 COUNT(*)。 |
Error | 失敗時使用 ErrorInfo。 |
TimeTakenMs | 查詢耗時。 |
TaskTraceItem
建議對應 task_log_traces 已存在欄位:
TraceIdTaskIdNodeIdNodeNameDeviceIdCommandNameLevelStatusRetryCountTimeTakenMsAdapterTimeTakenMsErrorCodeMessageDataSummaryRawRequestSummaryRawResponseSummaryMetadataSummaryCreatedAt
需要確認的 public contract 決策
| 決策 | 建議 | 是否需要使用者確認 |
新增 ITaskTraceStore | 建議新增 | 需要。 |
DTO 放在 Core.Logging | 建議採用 | 需要。 |
採同步 Query(...) | 建議採用 | 需要,因為會固定 public method 簽章。 |
TaskTraceQueryResult 專用 result | 建議採用 | 需要。 |
新增 ErrorCodes.TraceQuery... | 建議採用,但可延後 | 需要,因為會修改 public constant。 |
TotalCount | 第一版不做 | 需要確認。 |
| 無條件查詢 | 不允許 | 建議定案。 |
下一步建議
建議下一步進入「ITaskTraceStore 第一版 public contract 確認」,先由使用者確認以下 5 點,再開始程式實作:
- 允許新增
ITaskTraceStore。 - 允許在
HS.DeviceControl.Core.Logging新增TaskTraceQueryRequest、TaskTraceQueryResult、TaskTraceItem。 - 第一版採同步
Query(TaskTraceQueryRequest request)。 - 第一版不做
TotalCount,改用HasMore。 - 第一版不允許無條件全表查詢。
確認後再進入 fake gateway 查詢實作;未確認前不新增 public contract。