Files
codegraph/src/sync
Colby MchenryandClaude Opus 5.5 6162d872be fix(watcher): a deleted link target no longer pins a CPU core on Windows (#2938)
On Windows, libuv reports a watched folder that is being deleted by the
folder's own absolute path (\\?\D:\...) and re-arms the read, which fails
the same way at once: about 70,000 events in half a second until the
stream is closed. The watcher gives each directory link in a project its
own recursive stream, so deleting a link's target outside the project
started that storm. handleDirEvent joined the absolute name onto the
watched folder, got a path that doesn't exist, scheduled a full sync and
nothing else. The stream was never closed, the server held a core until
restart, and the storm kept re-arming the debounce, so no sync ever ran:
the deleted files stayed in the index and later edits never auto-synced.
The project root's stream had the same blind spot.

Fix: handleDirEvent, which both stream callbacks use, now treats an
absolute name as the watched folder itself reporting it is gone. The
first such event on a stream arms one check 200 ms later; the rest of the
burst finds it armed. The check closes a link's stream when the link no
longer leads to the folder it watched (deleted, or pointed elsewhere) and
re-reads the tree, whose full sync drops the link's files; a link that
leads somewhere live is watched anew. A project root that is gone
degrades the watcher with a "project folder was deleted or moved away"
reason, which closes every stream. A normal event pays one
path.isAbsolute check.

Validation (Windows 11, Node 22.22, libuv 1.51):
- Raw probe: fs.watch on a junction whose target is deleted gets 70,009
  events named \\?\<the junction> in 500 ms (499 ms CPU), and none after
  close().
- Real MCP server over a project with a junction libs -> outside, outside
  deleted: main used 3484, 3406, 3391, 3281 ms of CPU per 3 s window and
  kept the linked symbol; an edit afterwards never synced. With the fix:
  296, 0, 0, 79 ms; the linked symbol left the index; the edit synced.
- New watcher tests: a fake fs.watch link storm (10,000 self-named
  events cost no fs call, the stream closes once, a full sync runs, the
  project stays watched), a fake root storm (degrades once, closes the
  stream), and a Windows-gated real junction whose storm must go quiet.
  All 3 fail on main's watcher.ts; watcher.test.ts passes 61/61.

Reported in PR #2487 by @L0garithmic; this reimplements the fix
independently.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 23:53:53 +00:00
..
…