Agent: 探索者 (
explorer)
Confidence: 68%
Cost: $0.1091
Duration: 1m 30s
Task ID:f063c7d2-b7da-4ecb-99df-72a7da641a16
我已經蒐集足夠的資訊。現在彙整探索報告。
探索主題
grammY Bot 框架的中介軟體設計模式:高效、可測試的 Telegram Bot 中介軟體實作
發現
Composer 樹狀結構 > 線性堆疊
- grammY 看似線性的
bot.use()實際上建構一棵樹(Composer類別) filter()→on()→use()都會自動建構分支,允許後續擴展而無須攤平結構- 好處:可在已安裝的 Composer 上繼續
.use(),新中介軟體自動納入流程
- grammY 看似線性的
await next()是關鍵- 忘記
await會導致:執行順序錯誤、資料遺失、隨機崩潰、UnhandledPromiseRejection - 正確寫法:
await next()必須在 try-catch 上游(讓下游錯誤被捕捉)
- 忘記
當前專案已採用分層設計
- Error boundary → Auth → Logging → Rate-limit(順序正確)
- 每個中介軟體各司其職,易於測試和組合
- 缺點:都是線性組合,未充分利用 Composer 的分支能力
可組合性設計
- 中介軟體應該是無狀態函數,接受
(ctx, next)返回Promise<void> - 支援鏈式呼叫:
.use(A).use(B).use(C) - 支援條件分支:
.filter(predicate).use(middleware)使中介軟體只在特定條件執行
- 中介軟體應該是無狀態函數,接受
Fork() 支援並行分支
.fork().on(":text").use(A)可以在不阻塞主流程的情況下執行背景任務- 適合:日誌記錄、分析、非關鍵邊界效應
有趣的連結
- 與 Express.js 中介軟體模式的差異:Express 無法在已安裝的 middleware 上再增加,必須在初始化時定義;grammY 允許動態擴展
- 與事件總線的協力:Composer 樹狀結構 + EventBus 可實現高度解耦的外掛系統(你們的 plugin-router 已走在這條路上)
延伸問題
- 可否用 Composer 重構 plugin-router? 目前
tryRouteToPlugin()是手動迴圈,可用composer.filter(isPluginCommand).use(pluginHandler)改寫嗎? - 如何為複雜中介軟體寫單元測試? grammY 官方推薦的測試策略是什麼(mock Context、測試 next 呼叫順序)?
- fork() 如何改善 message-handler? 目前 logging 和 event emit 都是 fire-and-forget(
.catch(() => {})),能用 fork 分離嗎?
重要性:4/5
✅ 能改善專案品質
- 當前中介軟體層結構已不錯,但可用 Composer 分支進一步優化
- Plugin routing 目前手動迴圈,可改為聲明式 middleware
- Fork 可解決「主流程不被背景任務阻擋」的效能痛點
❌ 不是外部使用者會看到的特性(無法在blog/report發文),但對內部開發效率影響大
技術總結
最小可行改進(優先順序):
- 在
setupMiddleware()中使用 Composer 為 plugin-router 建構過濾規則 - 為 error-handler、auth、logging 各自編寫 5-10 行單元測試(mock next)
- 試試
.fork().use(loggingMiddleware)讓日誌完全非阻塞