Files
mnote/bugs/04-tree-domain/process/4-25-tree-command-create-delete-reload-latency-v1.md
T
2026-05-13 22:43:16 +08:00

5.2 KiB
Raw Blame History

4-25 [process][bug] 树命令新建/删除后强制刷新导致卡顿 v1

更新时间:2026-05-13

分类归属:

  • 04-tree-domain/process
  • 关联缺陷:bugs/05-editor-mainline/process/5-11-mindmap-ghost-assets-and-tree-command-latency-v1.md

用户反馈:

  • “删除页面和新建页面都很慢,不知道为什么这么卡。”

1. 问题定义

当前页面树/文件树的新建页面、删除页面等命令,在服务端命令成功后仍会触发整页刷新或完整树刷新。用户感知是:新建和删除并不是局部更新,而是卡一下、等整套页面壳或树壳重新加载。

这属于 tree command -> projection update -> UI apply 链路问题,应归到 04-tree-domain,而不是只作为编辑器 UI 问题处理。

2. 真实现象

用户反馈:

  1. 新建页面慢。
  2. 删除页面慢。
  3. 卡顿与同轮 mindmap 文件树重复增长一起出现,怀疑树刷新链路被频繁触发。

期望结果:

  1. tree.node.create 成功后,树 UI 局部插入新节点并进入重命名/导航状态。
  2. tree.node.archive 成功后,树 UI 局部移除节点或移动到回收站 projection。
  3. 只有 delta 无法应用、projection 缺失、SSE 断线或数据不一致时,才进入 resync/reload fallback。
  4. 普通新建/删除不应默认整页 reload。

3. 证据

3.1 Rust tree shell 有硬刷新路径

rust/crates/mnote-web/src/routes/tree.rs:2976:2986

  • scheduleRefresh() 在 80ms 后执行 window.location.reload()
  • 如果带 renameRowId,则通过 window.location.assign(url.toString()) 重新加载。

调用点:

  • 文件树删除:rust/crates/mnote-web/src/routes/tree.rs:2791:2824
  • 新建页面:rust/crates/mnote-web/src/routes/tree.rs:4309:4340
  • 重命名:rust/crates/mnote-web/src/routes/tree.rs:4373:4406
  • 移动:rust/crates/mnote-web/src/routes/tree.rs:4448:4502

这条路径会让 tree shell 命令体验明显慢于纯 delta / reducer 更新。

3.2 主页面已有 tree live controller,但命令后仍刷新

主页面已经监听 tree live

  • rust/crates/mnote-web/src/ssr/pages/layout.rs:3881:3917 处理 tree:snapshot / tree:delta / tree:resync
  • rust/crates/mnote-web/src/ssr/pages/layout.rs:3939:4050 启动 /api/tree/events EventSource

也就是说,命令完成后理论上可以由 delta/resync 更新 projection;当前硬 reload 与 live projection 机制重复。

3.3 命令本身已有 delta hint

Bridge runtime 对树命令生成 stream delta hint

  • tree.node.createrust/crates/bridge-runtime/src/lib.rs:9545:9592
  • tree.node.archiverust/crates/bridge-runtime/src/lib.rs:9655:9702

当前前端没有把这些结果作为默认局部更新来源,而是在 tree shell 中继续 reload。

3.4 React Sidebar 路径也存在重刷链

子代理只读调查发现 React Sidebar 路径也存在重刷:

  • 新建页面:wolai-frontend/src/components/sidebar/sidebar.tsx:1799:1847 附近在 command 后 await refreshTree() 再跳转。
  • 删除页面:wolai-frontend/src/components/sidebar/sidebar.tsx:2148 附近删除后等待 command、refreshTree()、广播文档变化/跳转。
  • Next API 的 api/tree/commands create/delete 还会执行 workspace/default scaffold、bridge mutation、artifact 记录等多段流程。

这说明卡顿不只来自单个 reload,而是命令后刷新链路偏重。

4. 当前判断

当前慢的核心不是“Convex 一定慢”,而是树命令执行后缺少轻量本地 apply:

  1. 命令 result / delta hint 已经具备局部更新信息。
  2. UI 仍经常走 refreshTree()window.location.reload() 或 full snapshot。
  3. resync_required 类事件会触发完整 workspace snapshot,结构性变化越多,越容易造成卡顿。

5. 建议验证

修复前先补一条计时 smoke

  1. 登录真实测试账号。
  2. 新建 TEST-TREE-LATENCY-<timestamp> 页面。
  3. 记录 POST /api/tree/commands 响应耗时。
  4. 记录下一次 tree:delta / tree:resync 到达耗时。
  5. 断言过程中是否发生 window.location.reload() 或顶层 navigation。
  6. 删除该测试页面,重复同样计时。
  7. 输出新建/删除从点击到 DOM 稳定的总耗时。

6. 建议修复方向

  1. tree.node.create 成功后直接用 command result 插入本地节点,并只在后台等待 live delta 校准。
  2. tree.node.archive 成功后直接从当前 projection 移除节点,并只在后台等待 live delta 校准。
  3. scheduleRefresh() 改成显式 fallback,只有 reducer 无法应用时才调用。
  4. React Sidebar 的 refreshTree() 应去重、节流,并避免与 SSE/full snapshot 同时触发。
  5. smoke 增加无 reload 断言和耗时阈值。

7. 流转条件

当前状态:process

只有满足以下条件后才能移动到 bugs/04-tree-domain/done/

  1. 新建页面普通路径不再默认整页 reload。
  2. 删除页面普通路径不再默认整页 reload。
  3. command result / tree delta 能局部更新页面树与文件树 projection。
  4. fallback reload 只在明确异常条件下触发,并有可观测标记。
  5. smoke 记录新建/删除耗时,并通过无 reload 断言。