Feat/restore fs events refresh - #433
Conversation
|
已修复 PR #433 的 CI 类型校验失败。 根因
async function sessionCwdOf(...): Promise<string>而 const cwd = sessionCwdOf(ctx, sessionId, ...)所以在 GitHub 合并
修复把 async function attachFsEvents(
ctx: Context,
hub: FsWatchHub,
ws: WebSocket,
req: SidebarHttpRequest,
): Promise<void> {
...
const cwd = await sessionCwdOf(ctx, sessionId, url.searchParams.get('cwd') ?? undefined)
...
}路由调用处本来就用 验证已用临时分支把
|
文件树自 v0.12.2 起不再自动刷新,只能靠手动刷新按钮。外部文件变化 (git clone、编辑器增删文件、构建产物)在点击刷新前对侧边栏不可见。 按仓库管理员在 omdsh-dev#196 的建议、以 omdsh-dev#137 的契约为主线,恢复被动事件驱动的 文件树自动刷新: - host 使用 `node:fs` 原生 `fs.watch` 实现 reference-counted hub,不新增依赖。 - 客户端通过 `/sidebar/ws/fs-events` 发送 `watch/unwatch`,host 推送 `{type:'change', path}`,客户端只 revalidate 变更目录,无轮询、无整树闪烁。 - 断线使用指数退避重连,重建后对可见目录做一次无闪烁 revalidate。 Windows 上如果按每个可见目录分别打开 `fs.watch` 句柄,会因子目录 (`obj`、`bin` 等)仍被 watch 而阻止父目录改名/移动。本实现改为对会话 cwd 使用单个递归 `fs.watch` 根句柄,再将递归事件映射回客户端实际 watch 的目录,避免 Windows 的句柄阻塞问题。 同时忽略 `.git`、`node_modules`、`dist`、`build`、`.next`、`out`、 `coverage`、`.cache`、`.config`、`.vscode`、`.idea`、`.vs`、`.svn`、 `.hg`、`AppData`、`.venv`、`venv`、`__pycache__`、`obj`、`Temp`、`tmp` 等不需要随时刷新的目录;这些目录仍可手动刷新。 - `src/index.ts`:`FsWatchHub`、`/sidebar/ws/fs-events` upgrade route、 `attachFsEvents`、teardown。 - `src/client/FileTree.tsx`:无闪烁 revalidate、可见目录跟踪、自动刷新 socket、指数退避重连;手动刷新也改为原位 revalidate,不再清空整棵树。 - `tests/file-tree-refresh.spec.tsx`:折叠目录后刷新再重新展开必须拿到 新数据,不能读陈旧缓存。 - `pnpm typecheck` - `pnpm build` - `pnpm vitest run tests/file-tree-refresh.spec.tsx`
## 背景 子代理审查提交 e4a47a2 后发现的 P2 问题,影响自动刷新在某些路径/平台 下失效或出现句柄泄漏、越权监听风险。 ## 修复 - 忽略目录改为按“工作区相对路径”判断:会话 cwd 自身不会被祖先路径中的 tmp/temp/build/dist 等词误伤,避免整个工作区自动刷新被关闭。 - Windows 递归 watcher 不再吞掉 `.git`/`node_modules` 等忽略目录本身的 创建/删除/重命名事件,父目录仍能刷新;只过滤这些目录内部的深层事件。 - watch 路径先经 `ensureWorkspacePath` realpath 校验,拒绝通过符号链接 逃逸到会话工作区外的目录。 - 非 Windows 逐目录 watcher 出错后保留订阅状态并自动重试,目录重建后 自动刷新可恢复;同时修正 `dispose()` 后仍可创建新 watcher 的句柄泄漏。 ## 回归测试 - 新增 `tests/fs-watch-hub.spec.ts`: - 直接目录变更通知 - 忽略目录自身不订阅 - 忽略目录创建仍刷新父级 - watch/unwatch 引用计数 - dispose 后不再新建 watcher - 更新 `tests/smoke.spec.ts`:注册路由断言加入 `/sidebar/ws/fs-events`。 ## 验证 - `pnpm typecheck` - `pnpm build` - `pnpm vitest run tests/fs-watch-hub.spec.ts tests/file-tree-refresh.spec.tsx`
67483f1 to
a4562db
Compare
|
@Menghuan1918 PR #433 已完成与最新 冲突处理方式采用 rebase 到最新 main(非 merge),冲突在原提交内解决,PR 历史仍为 3 个提交:
与 #469 的关系#469 新增的 关于 #344 的两个核心验收点两条均已在代码落地:
在 #344 方案之上的增强:按目录 验证
|
背景
文件树只能靠手动刷新按钮。外部文件变化(git clone、编辑器增删文件、构建产物)在点击刷新前对侧边栏不可见。
方案
按仓库管理员在 #196 的建议、以 #137 的契约为主线,恢复被动事件驱动的
文件树自动刷新:
node:fs原生fs.watch实现 reference-counted hub,不新增依赖。/sidebar/ws/fs-events发送watch/unwatch,host 推送{type:'change', path},客户端只 revalidate 变更目录,无轮询、无整树闪烁。契约增强:Windows 单根递归 watcher
Windows 上如果按每个可见目录分别打开
fs.watch句柄,会因子目录(
obj、bin等)仍被 watch 而阻止父目录改名/移动。本实现改为对会话cwd 使用单个递归
fs.watch根句柄,再将递归事件映射回客户端实际 watch的目录,避免 Windows 的句柄阻塞问题。
同时忽略
.git、node_modules、dist、build、.next、out、coverage、.cache、.config、.vscode、.idea、.vs、.svn、.hg、AppData、.venv、venv、__pycache__、obj、Temp、tmp等不需要随时刷新的目录;这些目录仍可手动刷新。改动
src/index.ts:FsWatchHub、/sidebar/ws/fs-eventsupgrade route、attachFsEvents、teardown。src/client/FileTree.tsx:无闪烁 revalidate、可见目录跟踪、自动刷新 socket、指数退避重连;手动刷新也改为原位 revalidate,不再清空整棵树。tests/file-tree-refresh.spec.tsx:折叠目录后刷新再重新展开必须拿到 新数据,不能读陈旧缓存。测试
pnpm typecheckpnpm buildpnpm vitest run tests/file-tree-refresh.spec.tsx