mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-07-21 21:31:12 +02:00
fix(watchers): ignore .git/node_modules in apps watcher, degrade watcher fd errors
The apps-dir watcher recursed into anything an installed app ships; ignore .git and node_modules segments like the workspace watcher does. (The skills watcher already bounds itself with depth: 1.) fs.watch failures (EMFILE/ENOSPC) escape chokidar's error handler as uncaught exceptions from Node watcher internals and killed the main process with the native error dialog. Catch them at the process level and log instead — watching is degradable; other uncaught exceptions keep the default dialog behavior.
This commit is contained in:
parent
5bf743f93d
commit
aa47871e47
2 changed files with 25 additions and 1 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { app, BrowserWindow, desktopCapturer, protocol, net, shell, session, safeStorage, type Session } from "electron";
|
||||
import { app, BrowserWindow, desktopCapturer, dialog, protocol, net, shell, session, safeStorage, type Session } from "electron";
|
||||
import path from "node:path";
|
||||
import {
|
||||
setupIpcHandlers,
|
||||
|
|
@ -74,6 +74,24 @@ const APP_LAUNCHED_AT = Date.now();
|
|||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
// fs.watch failures (EMFILE fd exhaustion, ENOSPC watch limits) surface as
|
||||
// uncaught exceptions from Node's watcher internals, bypassing chokidar's
|
||||
// 'error' handlers. Watching is a degradable feature — log and keep running.
|
||||
// Everything else keeps Electron's default behavior (native error dialog),
|
||||
// which we replicate since registering any listener suppresses it.
|
||||
process.on('uncaughtException', (err) => {
|
||||
const code = (err as NodeJS.ErrnoException | undefined)?.code;
|
||||
if ((code === 'EMFILE' || code === 'ENOSPC') && (err?.stack ?? '').includes('FSWatcher')) {
|
||||
console.error('[Main] file watcher error (non-fatal):', err);
|
||||
return;
|
||||
}
|
||||
console.error('[Main] uncaught exception:', err);
|
||||
dialog.showErrorBox(
|
||||
'A JavaScript error occurred in the main process',
|
||||
err?.stack ?? String(err),
|
||||
);
|
||||
});
|
||||
|
||||
// run this as early in the main process as possible
|
||||
if (started) app.quit();
|
||||
|
||||
|
|
|
|||
|
|
@ -719,6 +719,12 @@ async function startWatcher(): Promise<void> {
|
|||
if (watcher) return;
|
||||
const w = chokidar.watch(APPS_DIR, {
|
||||
ignoreInitial: true,
|
||||
// Installed apps may ship .git/node_modules trees — thousands of files
|
||||
// no consumer renders, at one watch fd per file (chokidar v4, no fsevents).
|
||||
ignored: (watchedPath: string) => {
|
||||
const segments = path.relative(APPS_DIR, watchedPath).split(path.sep);
|
||||
return segments.includes('.git') || segments.includes('node_modules');
|
||||
},
|
||||
awaitWriteFinish: { stabilityThreshold: 180, pollInterval: 50 },
|
||||
});
|
||||
w.on('all', (eventName, absolutePath) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue