影子模組與灰度轉正
影子 = 同一模組的新版本,以獨立 owner(如 roll_shadow)與線上舊版並存試運行:它收到真實事件的副本、其出站被攔截記帳而非真正發出——在 shadow_diff 裡對比兩個版本的行為,確認無害後 promote 一鍵轉正,dismiss 隨時放棄。模組程式碼零變動,全程運行時 API 驅動:與 load / unload / reload 同類的運維動作,Dashboard / 自訂管理模組直接調用,沒有任何設定項要寫。
{!--< tips >!--}
- 啟動:
await sdk.module.shadow_start("roll", source="路徑/到/v2")——新版程式碼以獨立 owner(預設取路徑名)與舊版並存 - 影子不參與真實分發與依賴圖:同名命令進影子目錄、路由只登記不掛載、
生命週期廣播靜默、
module.call與依賴解析仍指向 v1 - 轉正永遠由人確認:
await sdk.module.promote_shadow("roll"),失敗 自動回滾舊實例繼續服務;dismiss_shadow隨時放棄 {!--< /tips >!--}
快速上手
# v2 代碼:普通模組寫法,零影子感知(任意目錄,如 downloads/roll_v2/)
# 線上機器人裡(Dashboard / 管理模組呼叫),一行啟動灰度:
await sdk.module.shadow_start("roll", source="downloads/roll_v2")
# → 影子以獨立 owner "roll_v2" 與 v1 並存,出站被攔截記帳
# 試運行期間對比行為:
report = sdk.module.shadow_diff("roll")
# {"shadow_owner": "roll_v2", "count": 3, "aligned": [...]}
- v1 實際發送:來自收件箱(transcript)的 bot 時間線
- v2 意向發送:影子帳本(出站閘記錄的"想發什麼")
- 兩者按
trace_id對齊——同一條訊息,兩個版本各自為什麼觸發/沒觸發、 想發什麼/實際發了什麼,一目了然
確認無誤後轉正:
await sdk.module.promote_shadow("roll") # 轉正,失敗自動回滾 v1
await sdk.module.dismiss_shadow("roll") # 或:放棄影子
五道隔離閘
| 閘 | 機制 |
|---|---|
| 事件副本 | 影子處理器收到事件的獨立副本(帶 shadow 標記)——影子的改寫 / 認領 / 停止傳播只作用於副本,不影響原事件鏈 |
| 出站閘門 | 影子的 Send DSL 與 Api 調用全部攔截記賬(成功形狀假回應),不真正發出——影子不會重複回覆 |
| 存儲覆蓋層 | 影子的 KV 寫入進入記憶體覆蓋層並丟棄落庫;讀取先查覆蓋層、未命中透傳真庫(灰度對著真實數據跑);刪除記墓碑 |
| 路由屏蔽 | 影子的 HTTP/WS/SSE 路由只登記不掛載;同名命令進入影子命令目錄、平台事件方法注入禁止 |
| 生命週期靜默 | 影子不廣播自身的生命週期事件、不參與生態依賴圖(module.call 與依賴解析仍指向 v1,避免半成品被依賴) |
配置繼承:影子預設繼承原模組的配置節(否則灰度失真),轉正後配置原地生效。
誠實邊界(無法攔阻的)
- 走框架的發送 / API / KV 存儲 / 統一 HTTP 客戶端全部可以攔阻;
模塊繞過框架裸起
aiohttp、開線程寫外部系統——框架攔不住 - ORM 讀寫不在覆蓋層語義內(按行 overlay 無法在 SQL 層乾淨實現)—— 影子期間建議避免依賴 ORM 寫隔離
- 影子源為本地路徑:新版代碼以路徑導入、獨立 owner 裝載;同一 PyPI 包
在同解釋器內受
sys.modules單鍵限制,無法新舊兩版本並存 - 泄漏審計器(
sdk.module.audit)可見影子資源歸屬;繞過框架的副作用 至少不會無聲
轉正與回滾
promote 流程:快照當前版本(含級聯依賴者)→ 完全卸載 → 以影子名稱註冊
加載 → 任一步失敗自動回滾、舊實例繼續服務(盡力而為語意:on_unload 已
執行的副作用不可撤銷,回滾後舊實例處於已收尾態)。轉正成功的影子資源被
回收、綁定解除;原模組配置節原地生效。
持久化提醒:promote 是運行時切換——重啟後仍以 v2 運行,需要將新版本
持久化安裝(pip install -U 新版本 / 替換插件檔案)。運行時切換不會
替你完成套件管理。
相關文件
- 所有權(owner)系統——影子以獨立 owner 隔離的機制基礎
- 互動會話——
trace_id與收件箱(diff 對齊的資料來源) - 作用域(scope)——事件准入與出站控制面