3.7 KiB
3.7 KiB
local search query 每次重建索引导致大工作区搜索卡顿
状态:done Owner:04-tree-domain / 03-rust-web 发现日期:2026-05-27 来源:Sidex 全项目 review / 本地搜索性能审查
现象
在 local-first 工作区中,侧边栏搜索输入虽然有前端 debounce,但后端每次 query 都会重建并写入整个 local search index。大工作区下,连续输入会触发多次递归扫描、读取 Markdown、写 .mnote/index/search-index.json,导致搜索和主界面卡顿。
证据
rust/crates/mnote-web/src/routes/local_search_index.rsquery_local_search_index()第一步调用rebuild_local_search_index(...)。rebuild_local_search_index()递归collect_markdown_documents(...)后写入 index。
- 前端
sidebar-tree-runtime.js的搜索渲染 debounce 不能避免后端每次 query 全盘 rebuild。 - 同文件已经存在
refresh_local_search_index_for_path(...)增量更新入口,说明 watcher/单文件刷新方向已有基础,但 query path 没有复用它。
Sidex / VSCode 对照
Sidex / VSCode 搜索路径不会把每次 query 等价为全盘同步 rebuild:
- quick access/search 使用 throttle、cache state 和 cancellation token。
- Rust search crate 有 max_results、ignore-aware、binary skip 和并行扫描。
- watcher 变化应驱动增量缓存更新,query 只消费当前 cache 或启动后台 refresh。
MNote 不需要照搬 VSCode 搜索 UI,但应采用同一原则:query path 不做强制全量重建。
期望行为
- query 优先读取已有 index。
- index 缺失、版本不匹配、rootUri/workspaceId 不匹配时,才同步 rebuild。
- index 过期但仍可读时,query 返回旧 index 结果,并后台触发 refresh。
- watcher/path event 继续调用
refresh_local_search_index_for_path(...)做增量更新。 - 连续输入时,旧 query 可以被取消或自然过期,不能排队多次全盘扫描。
建议修复切片
- 新增
load_or_rebuild_local_search_index(root_path, root_uri, workspace_id):- 先
read_local_search_index(root_path)。 - 若 version/rootUri/workspaceId 匹配,直接返回 index。
- 不匹配或缺失时才调用
rebuild_local_search_index(...)。
- 先
- 将
query_local_search_index()改为调用load_or_rebuild_local_search_index(...)。 - 保留显式 refresh API 调用
refresh_local_search_index(...)。 - 加单测:
- 首次 query 会创建 index。
- 第二次 query 不改写 index
built_at。 - refresh 后 query 能读到新内容。
- 单文件
refresh_local_search_index_for_path(...)后 query 命中更新内容。
- 后续中期再做后台 refresh、取消令牌和搜索 worker。
验收
cargo test --manifest-path rust/Cargo.toml -p mnote-web local_search_index -- --nocapture通过。- 连续两次相同 query 时,第二次不会调用 full rebuild,不更新
built_at。 - 侧边栏连续输入 5 个字符时,不出现 5 次全盘 rebuild。
- 大目录 smoke 中搜索响应不阻塞 FileTree 展开。
修复记录
- 2026-05-27:新增
load_or_rebuild_local_search_index(...),query_local_search_index(...)优先读取已有匹配 version/rootUri/workspaceId 的索引;只有索引缺失、无效或 root/workspace 不匹配时才 full rebuild。 - 2026-05-27:新增回归测试
local_search_query_reads_existing_index_without_rebuilding,验证 query 不会看到未 refresh 的磁盘新内容,增量 refresh 后才命中新内容。 - 验证:
cargo test --manifest-path rust/Cargo.toml -p mnote-web local_search_index -- --nocapture,4 passed。
非目标
- 不在本缺陷单实现全文搜索排序重构。
- 不引入新的搜索 UI。
- 不实现全局后台 index worker;这是后续性能设计项。