mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-11-06 17:27:31 +00:00
feat(update): 更新进度走 EventBus + SSE(穿越进程重启的通知通道)
## 为什么必须走事件总线(用户口径:为什么不走 eventbus)
升级是**长耗时且会让进程消失**的动作。此前进度只往 log.Printf 写,
WebUI 要看得自己轮询 /kernel/update —— 而轮询在重启瞬间必然断线,
断线那一刻恰恰是用户最需要知道"升到哪一步/失败了/已回滚"的时刻。
EventBus 是内核既有的发布订阅机制(同步投递、handler panic 隔离),
用它不需要新造一条通知通道。
## 三个新事件类型
update_check 检查结果(只读,不改动)
update_progress 升级步骤:verify/backup/replace/restart/rollback/done/failed
update_result 最终结果(含回滚轨迹)
## ★ 顺序约束:先发事件,再动作
升级尾部几步(replace → restart)会让进程消失。顺序一反,最后几步的
事件永远发不出去。所以每个 publish* 都紧贴在其描述的动作**之前**。
## 直接 import events,不搞接口垫层
第一版我写了 EventPublisher 接口 + map[string]interface{} payload 想
"避免依赖",那是自欺欺人:events 包**不依赖任何内部包**(已验证),
import 它不会成环;而垫层会把事件降级成无类型 map,丢掉编译期检查。
已回退该设计,改为直接传 *events.Bus。
## SDK 补 EventBus() getter
PluginSDK 原先只有 Publish/Subscribe,没有暴露总线对象。而长流程
(升级闭环)需要把总线本身传下去持续发事件 —— 只给 Publish 的话,
每个调用点都要手动转发一遍。
## SSE 通路(守卫判据逼出来的正确修法)
TestEveryPublishedEventHasAnOutwardPath 抓到三个新事件"有发布者但无对外
通路"——症状是「发了、没报错、客户端收不到」。修法不是加白名单豁免,
而是真的接进 SSE:三者都进 sseEventRing(不只是实时推送),
断线重连要能补到**最终结论**(update_result),否则用户重连后只看到
"开始升级"而没有结局。
## 调用点
· pluginmgr(kernel_update):p.sdk.EventBus() → DoUpgradeBus
· webui(/kernel/update):h.sdk.EventBus() → runKernelUpgrade(pkg, bus)
· CLI:bus=nil,退化成纯 printf(CLI 没有总线)
This commit is contained in:
@ -73,6 +73,54 @@ const (
|
||||
// 订阅者(webui SSE)据此按**真实块 ID** 精确高亮,不再猜。
|
||||
EventMemoryAccess EventType = "memory_access"
|
||||
|
||||
// ── 更新子系统(internal/update)的事件 ──
|
||||
//
|
||||
// 为什么不走"工具返回值 + WebUI 轮询":
|
||||
// 升级是**长耗时且会重启进程**的动作。轮询在重启瞬间必然断,
|
||||
// 而断线时用户最需要知道"升级到哪一步了/失败了/已回滚"。
|
||||
// 事件总线是内核既有的发布订阅机制(同步投递、handler panic 隔离),
|
||||
// 用它不需要新造一条通知通道。
|
||||
|
||||
// EventUpdateCheck 发布一次「更新检查」结果(内核或插件)。
|
||||
//
|
||||
// 语义:只读检查,不改动任何东西。WebUI 据此刷新版本徽标。
|
||||
//
|
||||
// payload 约定:
|
||||
//
|
||||
// scope: "kernel" | "plugin"
|
||||
// name: 插件名(scope=plugin 时有值;kernel 时为空)
|
||||
// current: 本地版本
|
||||
// latest: 远端最新版本(查不到时为空)
|
||||
// has_update: bool
|
||||
// reason: 查不到的原因(可空)
|
||||
EventUpdateCheck EventType = "update_check"
|
||||
|
||||
// EventUpdateProgress 发布升级过程中的一个步骤。
|
||||
//
|
||||
// 语义:进度通知。升级会让进程消失,所以每一步都必须**先发事件再动作** ——
|
||||
// 顺序反了的话,最后几步的事件永远发不出去(进程已经没了)。
|
||||
//
|
||||
// payload 约定:
|
||||
//
|
||||
// scope: "kernel" | "plugin"
|
||||
// name: 插件名(scope=plugin 时有值)
|
||||
// step: "verify" | "backup" | "replace" | "restart" | "verify_version"
|
||||
// | "rollback" | "done" | "failed"
|
||||
// detail: 该步的人读说明
|
||||
EventUpdateProgress EventType = "update_progress"
|
||||
|
||||
// EventUpdateResult 发布升级的最终结果(成功或失败,含回滚轨迹)。
|
||||
//
|
||||
// payload 约定:
|
||||
//
|
||||
// scope: "kernel" | "plugin"
|
||||
// name: 插件名(scope=plugin 时有值)
|
||||
// ok: bool
|
||||
// from / to: 版本轨迹(回滚时 to 是回滚后的版本)
|
||||
// rolled_back: bool
|
||||
// error: 失败原因(成功时为空)
|
||||
EventUpdateResult EventType = "update_result"
|
||||
|
||||
EventAll EventType = "*"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user