perf(dashboard): replace blocking pgrep execSync with async execFile
Two sync hot paths were stalling the dashboard event loop on a periodic timer: 1. `pgrep -f vitest` ran via `execSync` in `getVitestProcessIds` (`/api/system-stats`, `/api/kill-vitest`) and `killVitestProcesses` (TUI memory-pressure check). On a busy machine pgrep walking the process table can take 100ms+; execSync blocks the entire Node event loop for that duration, so every concurrent dashboard request hangs while pgrep runs. The TUI variant fired on every memory-pressure tick (~2s when over threshold), the dashboard variant fired on every system-stats poll (5s while the modal is open). Both now use execFile with a callback wrapped in a Promise. 2. `discoverDashboardPiExtensions` (called from 3 /api/settings/pi- extensions routes) did 6+ blocking existsSync/readFileSync calls per invocation across legacy and fusion settings paths. Converted to fs.promises.readFile/access and parallelized via Promise.all. Behavior preserved: - TUI memory-pressure detection still works (sync os.totalmem path unchanged); auto-kill still fires on threshold breach. - The `lastAutoKillAt` 30s re-fire gate is set before the async kill starts, so concurrent ticks can't trigger duplicate kills. - system-stats still polls every 5s while the modal is open and still returns vitestProcessCount. - All 7 system-stats / kill-vitest tests pass; all 6 settings/pi- extensions tests pass. Test mocks updated for the (err, stdout, stderr) callback signature. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
10
.changeset/dashboard-async-pgrep-and-fs.md
Normal file
10
.changeset/dashboard-async-pgrep-and-fs.md
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
Fix periodic dashboard event-loop stalls caused by synchronous shell-outs and filesystem reads on hot request paths.
|
||||
|
||||
Two distinct sources, both replaced with async equivalents:
|
||||
|
||||
- **`pgrep -f vitest`** ran via `execSync` in `getVitestProcessIds` (`/api/system-stats`, `/api/kill-vitest`) and `killVitestProcesses` (TUI memory-pressure check). On a busy machine `pgrep` walking the process table can take 100ms+; `execSync` blocks the entire Node event loop for that duration, so every concurrent dashboard request hangs while pgrep runs. The TUI variant fired on every memory-pressure tick (every 2s when over threshold), the dashboard variant fired on every system-stats poll (every 5s while the modal is open). Both now use `execFile` with a callback wrapped in a Promise.
|
||||
- **`discoverDashboardPiExtensions`** (called from 3 `/api/settings/pi-extensions` routes) did 6+ blocking `existsSync`/`readFileSync` calls per invocation across legacy and fusion settings paths. Converted to `fs.promises.readFile`/`access` and parallelized via `Promise.all`.
|
||||
Reference in New Issue
Block a user