Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/node/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1878,6 +1878,32 @@ export class Config {
return null;
}

/**
* Watch providers.jsonc for external edits. Fires callback (debounced 300 ms)
* on any create/modify/delete event. Returns a cleanup function.
*
* We watch the parent directory rather than the file directly so that
* creates (first-time manual edit) are also detected on all platforms.
*/
watchProvidersFile(callback: () => void): () => void {
const filename = path.basename(this.providersFile);
let debounceTimer: ReturnType<typeof setTimeout> | null = null;

const watcher = fs.watch(this.rootDir, (_eventType, changedFilename) => {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Guard providers watcher when mux home is missing

watchProvidersFile() calls fs.watch(this.rootDir, ...) unconditionally, but Config does not guarantee rootDir exists before ProviderService is constructed. On first run (or when MUX_ROOT points to a not-yet-created directory), fs.watch throws ENOENT synchronously, which aborts ProviderService construction and can crash startup before recovery logic runs.

Useful? React with 👍 / 👎.

if (changedFilename !== filename) return;
if (debounceTimer) clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
debounceTimer = null;
callback();
}, 300);
});

return () => {
if (debounceTimer) clearTimeout(debounceTimer);
watcher.close();
};
}

/**
* Save providers configuration to JSONC file
* @param config The providers configuration to save
Expand Down
2 changes: 2 additions & 0 deletions src/node/services/providerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ export class ProviderService {
// The provider config subscription may have many concurrent listeners (e.g. multiple windows).
// Avoid noisy MaxListenersExceededWarning for normal usage.
this.emitter.setMaxListeners(50);
// Notify subscribers when providers.jsonc is edited externally (e.g. manual edits).
this.config.watchProvidersFile(() => this.notifyConfigChanged());
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Retain and dispose providers file watcher

The constructor starts a filesystem watch via watchProvidersFile(...) but drops the returned cleanup function. Because FSWatcher is ref'ed by default, each ProviderService instance now keeps a live watcher for the process lifetime, which can leak handles in tests/one-shot CLI flows and make transient service instances unable to fully tear down.

Useful? React with 👍 / 👎.

}

/**
Expand Down
Loading