62 lines
3.2 KiB
Markdown
62 lines
3.2 KiB
Markdown
## Context
|
||
|
||
round-3 後主流程已穩定,但仍有 3 類技術債:
|
||
- Resource 快取在同一 process 內同時保存 DataFrame 與完整 records 複本,導致記憶體放大。
|
||
- Resource 與 Realtime Equipment 的 Oracle 查詢存在跨服務重複字串,日後修改容易偏移。
|
||
- 部分服務邊界型別註記與魔術數字未系統化,維護成本偏高。
|
||
|
||
約束條件:
|
||
- `resource` / `wip` 維持全表快取策略,不改資料來源與刷新頻率。
|
||
- 對外 API 欄位與前端行為不變。
|
||
- 保持單一 port 架構與既有運維契約。
|
||
|
||
## Goals / Non-Goals
|
||
|
||
**Goals:**
|
||
- 降低 Resource 快取在 process 內的重複資料表示,保留查詢輸出相容性。
|
||
- 讓跨服務 Oracle 查詢片段由單一來源維護。
|
||
- 讓關鍵 service/cache 模組具備一致的型別註記與具名常數。
|
||
|
||
**Non-Goals:**
|
||
- 不改動資料庫 schema 或 SQL 查詢結果欄位。
|
||
- 不重寫整體 cache 架構(Redis + process cache 維持)。
|
||
- 不引入新基礎設施或外部依賴。
|
||
|
||
## Decisions
|
||
|
||
1. Resource derived index 改為「row-position index」而非保存完整 records 複本
|
||
- 現況:index 中保留 `records` 與多組 bucket records,與 DataFrame 內容重複。
|
||
- 決策:index 只保留 row positions(整數索引)與必要 metadata;需要輸出 dict 時由 DataFrame 按需轉換。
|
||
- 取捨:單次輸出會增加少量轉換成本,但可顯著降低常駐記憶體重複。
|
||
|
||
2. 建立共用 Oracle 查詢常數模組
|
||
- 現況:`resource_cache.py`、`realtime_equipment_cache.py` 各自維護 base SQL。
|
||
- 決策:抽出 `services/sql_fragments.py`(或等效模組)管理共用 query 文本與 table/view 名稱。
|
||
- 取捨:增加一層間接引用,但查詢語意一致性與變更可控性更高。
|
||
|
||
3. 型別與常數治理採「先核心邊界,後擴散」
|
||
- 現況:部分函式已使用 `Optional` / PEP604 混搭,且魔術數字散落於 cache/service。
|
||
- 決策:先統一這輪觸及檔案中的型別風格與高頻常數(TTL、size、window、limits)。
|
||
- 取捨:不追求一次全專案清零,以避免大範圍 noise;先建立可持續擴展基線。
|
||
|
||
## Risks / Trade-offs
|
||
|
||
- [Risk] row-position index 與 DataFrame 版本不同步 → Mitigation:每次 cache invalidate 時同步重建 index,並保留版本檢查。
|
||
- [Risk] 惰性轉換導致查詢端 latency 波動 → Mitigation:保留 process cache,並對高頻路徑做小批量輸出優化。
|
||
- [Risk] SQL 共用常數抽離造成引用錯誤 → Mitigation:補齊單元測試,驗證 query 文本與既有欄位契約一致。
|
||
- [Risk] 型別/常數清理引發行為改變 → Mitigation:僅做等價重構,保留原值並用回歸測試覆蓋。
|
||
|
||
## Migration Plan
|
||
|
||
1. 先重構 Resource index 表示,確保 API 輸出不變。
|
||
2. 抽離 SQL 共用片段並替換兩個快取服務引用。
|
||
3. 清理該範圍型別與常數,補測試。
|
||
4. 更新 README / README.mdj 與 OpenSpec tasks,跑 backend/fronted 目標測試集。
|
||
|
||
Rollback:
|
||
- 若出現相容性問題,可回退至原 index records 表示與舊 SQL 內嵌寫法(單檔回退即可)。
|
||
|
||
## Open Questions
|
||
|
||
- 是否要在下一輪把相同治理擴展到 `wip_service.py` 的其餘常數與型別(本輪先限定 residual 範圍)。
|