5.8 KiB
5.8 KiB
前後端改進建議
依「影響使用者 / 維護成本 / 風險」排序。細節背景見先前健康檢查;架構導覽見 docs/architecture.md。
後端:立刻值得修的問題
1. Job dedupe:改寫草稿全域互擋
generate-rewrite-draft 的 DedupeKeys 為空,但 buildDedupeKey 仍用 type|scope 產 key → 所有 scope=persona 的改寫 job 共用一把 lease。
- 檔案:
internal/model/job/usecase/usecase.go、helpers.go - 建議:
DedupeKeys: []string{"scope_id"},或空 keys 時回傳""不啟用 lease - 補 test
2. CreateRun 失敗路徑用裸 Update
lease 失敗時 runs.Update 直接改 status,違反 guarded 規則。
- 改
UpdateIfStatus(pending → cancelled)
3. ClaimNext lock 失敗立刻 re-enqueue
可能 tight loop 打 Redis。應 delay / 檢查狀態後再入列,FindByID 失敗不要 silent drop。
4. Worker 忽略 Heartbeat 錯誤
_ = step.Heartbeat(ctx) 在 lock 過期後仍繼續跑。失敗應中止 step。
5. Refresh token 並發
先發新 token 再 blacklist 舊的 → 並發 refresh 可能雙活。應用原子輪替(Lua / 先 blacklist 再 issue,或 refresh family)。
後端:結構與可維護性
| 議題 | 建議 |
|---|---|
| ServiceContext 過胖 | 依域拆 bootstrap(auth/job/content/publish),減少單檔 400+ 行 DI |
| 每個 worker process 註冊全部 handler | 只 register 該 workerType 需要的 step;啟動時 assert template↔handler |
| ghost worker 在 compose | 已清理一輪;新增 template 時同步 dev-all / docker-compose |
列表 API 用 limit |
新 API 一律 page/pageSize;舊的雙讀後 deprecate |
time.Now().UnixNano() 散落 |
統一 clock.NowUnixNano() 利於測試 |
| Secrets key 可空 | prod config validate:HAIXUN_SECRETS_KEY 必填 |
| copy_mission 半殘 | 見 post-project-plan:過渡期只留 inspire;完整 pipeline 勿再接,走 Post Project |
| 測試 | Job 較完整;auth refresh、ClaimNext race、logic 層幾乎無測 — 優先補 P0 |
錯誤處理慣例
- 好:
errs.For(code.X).…+response.Write - 差:
_, _ = FailRun/UpdateProgress吞錯誤 → 可觀測性差,長任務尤其危險
不建議做的事
- 為了 template-monorepo 相容引入 OAuth/OTP/Zitadel 重依賴
- 在 provider adapter 裡讀 Mongo / setting
- 裸
Update蓋 job / publish_queue 狀態
前端:可明顯變好的地方
1. 登入態對 5xx 過於暴力
AuthContext.reloadMember 任何錯誤都 clearTokens()。gateway 短暫 502 會踢登出。
建議:僅 401 / refresh 失敗清 token;5xx 顯示「後端暫時無法連線」。
2. 巨型頁面
| 檔案 | 約略行數 | 建議 |
|---|---|---|
PatrolPage.tsx |
~1900 | 拆 list / graph / scan / outreach 子元件 + hooks |
MissionsPage.tsx |
~1200 | 若走 Post Project 直接換 wizard,勿再膨脹 |
OwnPostsHub.tsx |
~750 | 拆 formula / reply / list |
好處:可測、可讀、島民/自動化也較好掛 data-islander-*。
3. Hash 路由的限制
- 無巢狀 path、難做 deep link(例如
#patrol/topic/xyz) - 中長期可考慮 React Router,或至少支援
page + query狀態
4. 過時 UI / 死 client
| 項目 | 建議 |
|---|---|
GapsPage |
對齊 threads-automation-gap-plan 真實進度,或改「已完成 checklist」 |
haixun.ts 未呼叫方法 |
定期刪(inventory API client 等) |
extensionSync 固定 reject |
文件與 UI 標「已停用」;重啟時勿再 postMessage JWT |
| jobLabels 幽靈 type | 隨 ghost template 刪 |
5. 設計系統(已做得不錯)
- 繼續只用
--hx-*/ semantic Tailwind;勿引入 MUI/Ant - 共用
ui.tsx(Button 必須有 children) - 大頁面新功能優先組 Card / Field / Badge,不要另寫色票
6. API 層
client.ts 的 refresh single-flight、502 retry 是好的。可再:
- 對
ApiError做isUnauthorized/isUnavailablehelper,頁面統一處理 - 長輪詢(jobs 3s)考慮 visibility API:分頁隱藏時降頻
7. 測試
目前幾乎無前端 test。最低投資:
client.tsrefresh + 502 retryAuthContext5xx 不登出- 純函式:
jobStatus、formatnano 轉換
8. AGENTS 寫了但未存在的功能
- Islander agent runtime(
web/src/lib/islander)文件超前,程式沒有
→ 實作或從 AGENTS 刪除描述,避免後續 agent 按空文件改碼
產品債(架構外但影響體感)
- Flow A 過渡態:Missions 用 inspire + content_ops + drafts,舊 copy_mission CRUD 已移除/不可用;應盡快 Post Project 或明確標「精簡模式」。
- Extension 同步關閉:海巡 dev crawl 若依賴 browser session,需新安全協議(short-lived code,勿 JWT postMessage)。
- Publish inventory refill job 無 handler:policy API 可留,refill job 勿再 enqueue(應已清)。
建議迭代順序(若只做改進、不做大功能)
Sprint A 正確性
rewrite dedupe、CreateRun guarded cancel、ClaimNext、Heartbeat、AuthContext 5xx
Sprint B 可理解性
拆 PatrolPage / Missions 邊界、GapsPage 對齊、AGENTS 修路徑與 auth matrix
Sprint C 可觀測
worker 錯誤上報、job stranded reaper、prod secrets validate
Sprint D 產品
Post Project(取代 Flow A)或凍結 Missions 只修 bug
自我檢查清單(PR 前)
後端:
- 列表是否
page/pageSize+ pagination - Job 狀態是否 guarded
- 長任務是否處理 Heartbeat 錯誤
- 錯誤是否
errs.For(code.X) - 時間是否 unix nano UTC
前端:
- 是否只用 semantic token
- Button 是否有中文動詞 children
- 是否經
api/clientenvelope - 錯誤是否區分 401 vs 5xx
make web-build通過