Skip to content

Bound watcher IPC backlog with targeted subscription recovery - #3582

Open
salemsayed wants to merge 1 commit into
get-bb:mainfrom
salemsayed:codex/fix-watcher-ipc-backpressure
Open

salemsayed wants to merge 1 commit into
get-bb:mainfrom
salemsayed:codex/fix-watcher-ipc-backpressure

Conversation

@salemsayed

@salemsayed salemsayed commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Human comments

What was wrong

The watcher child sends every event batch without tracking outstanding IPC writes. When the daemon stops reading, serialized messages accumulate without a bound. A real forked-process reproduction on latest upstream c3067feab shows median child RSS growth of 196.79 MiB for 500,000 updates on Node 22. This confirms an outgoing-IPC defect, but does not establish it as the sole cause of the original reported watcher OOM. The earlier root-scope fixes in #2336 address a different allocation source. Investigation, reproducible commands, raw measurements, and browser proof.

What changed

  • Bound outstanding event messages using a conservative 4 MiB serialized-size estimate, released by Node's send callbacks. Avoid serializing a batch that would exceed the budget.
  • Request existing subscription-scoped recovery once for each overloaded subscription, suppressing further events until removal. The consumer refreshes and resubscribes; other roots and control messages continue. Ordinary event paths, types, and order remain unchanged.
  • Handle synchronous/asynchronous channel failures through the existing child restart path.
  • Add sender tests, real native-watcher recovery tests, an opt-in before/after IPC benchmark, debugging guidance, and committed verification evidence. Most added lines are raw benchmark data and tests.

No server/daemon wire, public SDK, or CLI contract changes; no HOST_DAEMON_PROTOCOL_VERSION bump is needed. This bounds outgoing event retention, not native watcher memory or total RSS. Under overload, detailed events are replaced by conservative refreshes.

How you verified

  • Both new native integration tests fail with the exact upstream child entry and pass with the fix: oversized 4,000-file rescan, automatic refresh/resubscription of only the affected root, updates during recovery, new events on both roots, and heartbeat continuity without a child restart.
  • Watcher suite: 60 passed on Node 22.19.0, 24.19.0, and 26.7.0, including the opt-in IPC benchmark; watcher typecheck passed on Node 22. Node 26 used direct Vitest after an unrelated SQLite native-module prerequisite exited 137; full-app verification used Node 22.
  • Same-workload IPC benchmark, three repetitions per size/runtime: Node 22 median RSS growth 196.79 → 5.41 MiB for 500,000 updates. Only two event batches plus one recovery request remain outstanding instead of 500 batches. Raw Node 24/26 measurements are included.
  • Existing recovery stress benchmark: 57 and 100 roots, idle and controlled CPU load, one warmup plus three measured runs each. One targeted resubscription, two affected refreshes, zero unaffected refreshes, zero child restarts in every run.
  • Turbo host workspace suite: 164 passed. Turbo host daemon suite: 620 passed. Host daemon dependency build/typechecks passed. Existing optional tests were skipped. The report records temporary-directory and Git-configuration isolation needed on this machine.
  • Full pnpm start:worktree --dryrun: 45 tasks passed, repeated successfully with 44 cache hits. Built source server/daemon health and real Chromium Diff-panel updates passed for create, edit, rename, delete, and reload in a fresh disposable instance. Screenshots are included.
  • Changed files pass formatting and git diff --check. Production services were untouched. macOS/Windows native watchers and long-duration production workloads were not tested.

Upstream CI also passed on this PR: all six test shards, build/typecheck/lint, Linux and macOS package smoke checks, contributor approval, and version gates. CI run. The workflow skipped iOS flows and its separate Node-compatibility matrix.

Main commands:

BB_WATCHER_IPC_BENCHMARK=1 pnpm exec turbo run test typecheck --filter=@bb/host-watcher --env-mode=loose
pnpm exec turbo run test typecheck build --filter=@bb/host-daemon
pnpm exec turbo run test --filter=@bb/host-workspace
pnpm start:worktree --dryrun

AGENT GENERATED

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.

1 participant