Skip to content

1.4.0

Choose a tag to compare

@SuCriss SuCriss released this 18 Sep 08:15
· 16 commits to main since this release

dsh-version-update 1.4.0

面板的读路径不再能装东西,回滚本身可以再回滚,静默策略每次开机都保证查一次。

新增

  • 每次开机保证查一次,auto 不再靠运气。 checkAt 只是一个墙钟时刻:机器在那个时刻没开机就整天错过,而一个生命周期里从不包含那个时刻的宿主(短会话、睡过去的笔记本)是每天错过——mode: 'auto' 因此在任何不常开的机器上都形同虚设。调度器现在在启动后 60 秒(STARTUP_CHECK_MS)挂一个一次性检查。只在 mode: 'auto' 下挂:off 和 notify 是用户在说"告诉我,别动手",两者都不需要一个后台 registry 读取。mode 在定时器触发时重读,而不是沿用挂载时的值——延迟期间改主意是被尊重的,切走 auto 连一次 registry 往返都不付。policyChanged 也会重新挂载它:打开 auto 本身就是用户在要求无人值守安装,而面板那次 acting read 是在旧 mode 下跑完的,没有这一条,一个在 off 下启动、之后切到 auto 的宿主会一直等到下一个 checkAt——没配置就是永远不查。

修复

  • 一个 GET 能替换整棵安装树。 GET /check 会喂给自动更新决策,于是任何打到该 URL 的请求——浏览器预取、第二个标签页、任何遍历 loopback 路由族的本机进程——都能启动一次静默安装并重写 551 MB 文件;而面板自己那个显式「检查」按钮反倒被保证永不安装,方向是反的。该路由现在只观察:刷新调度器的事实以便「上次检查」保持诚实,永不安装、也永不泊车。动手的那次读取搬到了新的 POST /check/auto,由面板在打开时调用一次——正是这个挂载点,让一个没有 checkAt 的静默 mode: 'auto' 可达。
  • 一次回滚会把自己撤销。 恢复之后的那次刷新用的是裸读,会喂给自动决策——于是 mode: 'auto' 下,回滚到旧版本几秒后就被静默装回刚刚滚离的那个版本,而页面还显示着旧的那个。那次刷新现在走观察。
  • 读一次快照卡会卡住整个宿主。 listSnapshots 为每个条目跑一遍 inventory()——整棵树的递归 lstat——再用 JSON.stringify 和 meta.json 逐项比对。本机这棵安装树(26 513 文件 / 551 MB)一次 inventory 实测 1.578 s,而面板每次检查都读这个列表,于是几个快照就能把事件循环堵上数秒。校验现在分两级:列表与裁剪只读元数据(meta.json 自洽且声明版本与目录名相符),而两条不可撤销的路径——恢复、以及复用既有快照——仍然跑完整的 inventory 比对。这样做是可靠的,因为一个快照只有在拷贝完成之后才会被 rename 成版本名;撕裂的拷贝住在 .tmp-* 下,永远不是版本名。
  • 一次恢复是不可逆的。 恢复把快照拷到安装上,被它替换的版本就此消失。restoreSnapshotAsync 现在把让开的那棵树收养为那个版本的快照(adoptSnapshot)——同卷 rename,不是拷贝,所以额外代价是一次 inventory 走查(1.6 s),而不是整棵树拷贝实测的 87.91 s。因此回滚可以被再回滚。当被替换的版本已经有一份完好快照时收养被跳过,且收养自己的裁剪会被告知保护这次恢复要去的那个版本。
  • 恢复路径把自己的成功报成失败。 一次恢复要拷整棵树——本机实测 87.91 s——而面板给每个请求 15 s 就中止。面板现在点名正在恢复的版本(正在恢复 <版本>),并把那一个请求的预算提到 10 分钟。
  • 被拒绝的操作没有任何反馈。 面板只在 state.status === 'error' 时渲染 state.error,而一次被拒的恢复、一次失败的快照删除、一次被拒绝的策略保存都会让状态停在 ready——于是完全看不到任何提示。现在任何 error 都会渲染。
  • 只有字节校验不过的快照会卡死整个修复。 repairTree 挑最新的候选恢复一次;一个通过了元数据校验却没过字节校验的快照,此前会带着整个修复一起失败,而不会去试下一个候选。现在它按从新到旧走完候选直到有一个恢复成功,且一次成功的修复不再把失败的候选折进它的健康结论。

变更

  • 新端点 POST /api/dsh-version-update/check/auto——唯一能让更新策略动手的检查。GET /check 与 POST /check/run 现在都只观察。三者仍都会刷新 lastCheck。
  • POST /snapshots/restore 的结果可能带 backup(被收养为快照的那个版本)和 backupError(收养为什么失败;恢复本身仍然成功)。
  • 快照行现在渲染宿主一直在发的负载体积(entry.bytes)。

移除

  • 死导出 CHANNELS——全仓库零引用。

测试

246 用例通过,tsc --checkJs 干净。

Full Changelog: v1.3.0...v1.4.0