Commit 0aef1ef
fix(core): reduce daemon inotify watch count by upgrading watchexec (#34329)
## Current Behavior
The daemon's file watcher uses watchexec 3.0.1 which hardcodes
`RecursiveMode::Recursive` when registering inotify watches. This means
**every** directory gets an inotify watch — including all of
`node_modules`, `.git`, and other ignored trees.
On a typical workspace with a large `node_modules`, this can consume
thousands of inotify watches, eating kernel memory and CPU. The
`WatchFilterer` only filters **events** after watches are already
registered — the watches themselves are never prevented.
## Expected Behavior
Only non-ignored directories (workspace source code) get inotify
watches. Ignored directories like `node_modules`, `.git`, `.nx/cache`,
`.nx/workspace-data`, and `.yarn/cache` are skipped entirely at the
watch registration level.
This dramatically reduces:
- **inotify watch count** (from thousands to hundreds)
- **Memory usage** (each watch consumes kernel memory)
- **CPU overhead** (fewer watches = less kernel bookkeeping)
### How it works
- Upgraded watchexec 3.0.1 → 8.0.1 which supports
`WatchedPath::non_recursive()`
- Added `create_watch_walker()` using `ignore::WalkBuilder` (same
pattern as `walker.rs`) to enumerate only non-ignored directories
- Each directory is watched with `NonRecursive` mode — like putting
security cameras only in the rooms you care about instead of every room
in the building
- New directories created at runtime are dynamically added to the watch
set via the `on_action` handler
- Event-level filtering via `WatchFilterer` is unchanged — same behavior
for gitignore/nxignore patterns
### macOS Support for Dynamic Directory Registration
The initial implementation worked on Linux and Windows but failed tests
on macOS because macOS FSEvents doesn't always provide the same
`FileEventKind` tags as Linux inotify or Windows ReadDirectoryChangesW.
**Three changes to support macOS:**
1. **watcher.rs**: On macOS, check all events for directory creation
(not just events with specific FileEventKind tags) and verify via
filesystem
2. **types.rs**: Filter directory events from JavaScript callbacks on
macOS (similar to Windows behavior)
3. **watch_filterer.rs**: Allow macOS directory events (`Create(Folder)`
and `Modify(Metadata)`) through the filter so the action handler can
register them
All changes use `#[cfg(target_os = "macos")]` for compile-time
conditional compilation, so Linux/Windows behavior is completely
unchanged and there's zero runtime overhead.
### Additional notes
- Pinned `serde` to `<1.0.220` because serde 1.0.220+ moved `__private`
to `serde_core`, breaking `swc_common 0.31.22`
- No TypeScript changes — the napi interface is identical
- `watch_filterer.rs`, `types.rs`, `utils.rs` required no changes (APIs
are compatible)
## Related Issue(s)
Fixes #33781
Fixes nrwl/nx-console#2468
<!-- No specific issue linked yet -->
---------
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <[email protected]>1 parent 693f751 commit 0aef1ef
13 files changed
Lines changed: 1996 additions & 1309 deletions
File tree
- e2e/nx/src
- packages/nx
- src
- internal-testing-utils
- native
- pseudo_terminal
- tasks/hashers
- tests
- utils
- watch
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
14 | | - | |
| 14 | + | |
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| |||
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
28 | 36 | | |
29 | 37 | | |
30 | 38 | | |
| |||
155 | 163 | | |
156 | 164 | | |
157 | 165 | | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
158 | 186 | | |
159 | 187 | | |
160 | 188 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
65 | 65 | | |
66 | 66 | | |
67 | 67 | | |
68 | | - | |
| 68 | + | |
69 | 69 | | |
70 | 70 | | |
71 | 71 | | |
| |||
81 | 81 | | |
82 | 82 | | |
83 | 83 | | |
84 | | - | |
| 84 | + | |
85 | 85 | | |
86 | 86 | | |
87 | 87 | | |
88 | 88 | | |
89 | 89 | | |
90 | 90 | | |
91 | | - | |
92 | | - | |
93 | | - | |
94 | | - | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
95 | 95 | | |
96 | | - | |
| 96 | + | |
97 | 97 | | |
98 | 98 | | |
99 | 99 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
67 | 67 | | |
68 | 68 | | |
69 | 69 | | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
70 | 75 | | |
71 | 76 | | |
72 | 77 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
166 | 166 | | |
167 | 167 | | |
168 | 168 | | |
169 | | - | |
170 | | - | |
171 | | - | |
172 | | - | |
| 169 | + | |
| 170 | + | |
173 | 171 | | |
174 | 172 | | |
175 | 173 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
315 | 315 | | |
316 | 316 | | |
317 | 317 | | |
| 318 | + | |
318 | 319 | | |
319 | 320 | | |
320 | | - | |
| 321 | + | |
321 | 322 | | |
322 | 323 | | |
323 | 324 | | |
324 | | - | |
| 325 | + | |
325 | 326 | | |
326 | 327 | | |
327 | 328 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
76 | 76 | | |
77 | 77 | | |
78 | 78 | | |
79 | | - | |
80 | | - | |
| 79 | + | |
| 80 | + | |
81 | 81 | | |
82 | 82 | | |
83 | 83 | | |
| |||
0 commit comments