Skip to content

perf(builder): watch bounded source-tree roots instead of one watcher per file - #115

Draft
arifsisman wants to merge 1 commit into
native-federation:mainfrom
arifsisman:fix/bounded-federation-watch-roots
Draft

perf(builder): watch bounded source-tree roots instead of one watcher per file#115
arifsisman wants to merge 1 commit into
native-federation:mainfrom
arifsisman:fix/bounded-federation-watch-roots

Conversation

@arifsisman

Copy link
Copy Markdown
Contributor

Follow-up to #96.

Problem

The widened watch list from #96 registers one fs watcher per tracked federation source — ~1,900 watchers on the same real Nx workspace the original fix was measured on. Per-file watchers don't scale:

  • macOS FSEvents replays and throttles under thousands of streams (this is the same OS behaviour family that motivated the stale-event filter in fix(builder): watch the files the federation build actually tracked #96 — fewer streams attacks it at the root).
  • Every platform pays a file descriptor per watcher.
  • Each syncNfFileWatcher pass re-diffs the full file list.

Change

federationWatchPaths(files, workspaceRoot) collapses the tracked files into the few top-level workspace source trees that contain them (libs, apps, ...), and both builders watch those roots recursively instead. On the measured workspace: files=~1900 collapses to roots=2 (logged at verbose level).

Because a directory watch surfaces every event under its root, relevance moves to where events arrive:

  • build builder: an event only reaches the dirty buffer if the path is a tracked federation source or under a linked dir, and its mtime actually advanced (the fix(builder): watch the files the federation build actually tracked #96 stale-event filter). Irrelevant events return immediately.
  • remote builder: the same predicate (project root ∪ linked dirs ∪ tracked sources, then mtime) is passed into createDebouncedChangeWatcher, so irrelevant events never enter pendingPaths.

Safety rails: files outside the workspace, at the workspace root itself, or under dot dirs / node_modules / build outputs stay as single-file watches; nested candidates deduplicate to their parent tree.

Verification

  • Five new unit tests for federationWatchPaths (collapse, out-of-workspace, excluded top-levels, root-level file, parent/child dedup); typecheck, lint (0 errors, warning count unchanged) and vitest (16 files / 116 tests) pass.
  • Validated in daily use on the same Nx + Angular 22 workspace as fix(builder): watch the files the federation build actually tracked #96 (applied via patch-package): shared-mapping edits still rebuild within ~1s, idle dev server stays quiet, watcher count flat as the workspace grows.

… per file

Follow-up to native-federation#96. The widened watch list registered one fs watcher per
tracked federation source — ~1,900 watchers on a real Nx workspace.
Per-file watchers do not scale: macOS FSEvents replays and throttles
under that many streams, and every platform pays a file descriptor per
watcher.

federationWatchPaths() collapses the tracked files into the few
top-level workspace source trees that contain them (libs, apps, ...)
and both builders watch those roots recursively instead. Because a
directory watch surfaces every event under the root, relevance is now
filtered where events arrive: only tracked federation sources,
project-root files and linked-dir edits pass, and only when their
mtime actually advanced (the native-federation#96 stale-event filter). Irrelevant
events no longer reach the dirty buffer at all.

Files outside the workspace, at the workspace root, or under dot dirs,
node_modules and build outputs stay as single-file watches; nested
candidates deduplicate to their parent tree. Covered by five new unit
tests; validated on the same Nx + Angular 22 workspace as native-federation#96
(files=~1900 collapses to roots=2).
@arifsisman

Copy link
Copy Markdown
Contributor Author

Note on the red verify check: the failing step is pnpm audit, and it is not caused by this PR — this branch touches four source files and no dependency or lockfile.

Two advisories (brace-expansion GHSA-rgw5-rvv9-x895 and fast-uri GHSA-7p8r-x3mc-p8w7) were published after main's last green run, so main and every open PR fail the same step right now. Reproduced on a clean main checkout with no changes applied:

2 vulnerabilities found
Severity: 2 high

#116 fixes it via the existing overrides block (one patch bump each, no direct dependency changes). Once that lands, re-running this check should go green.

@Aukevanoost

Copy link
Copy Markdown
Contributor

Might be superseded by #112

@Aukevanoost

Copy link
Copy Markdown
Contributor

I'd love to hear your feedback on how it performs: https://github.com/native-federation/angular-adapter/releases/tag/v22.1.0-RC1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants