fix: serialize sidecar cleanup in batch delete to avoid requestId collision

Multiple concurrent sidecar.deleteSession() calls used
requestId: delete-session-\ which collides when two
fire in the same millisecond. The second overwrites the first in
the pending map, causing the first promise to never resolve and
Promise.allSettled to hang indefinitely — producing Electron's
'reply was never sent' error.

Run cleanup sequentially instead. Also add .catch() to rm() calls
for robustness.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
David Kaya
2026-04-15 08:42:55 +02:00
co-authored by Copilot
parent c22bd32f97
commit 1f49436d8a
+10 -10
View File
@@ -1166,23 +1166,23 @@ export class AryxAppService extends EventEmitter<AppServiceEvents> {
const workspace = await this.loadWorkspace();
const idsToDelete = new Set(sessionIds);
// Collect cleanup work before mutating the array
const cleanupTasks: Promise<void>[] = [];
// Run cleanup sequentially to avoid requestId collisions in sidecar dispatch
for (const session of workspace.sessions) {
if (!idsToDelete.has(session.id)) continue;
const scratchpadDirectory = this.resolveScratchpadSessionDirectory(session);
if (scratchpadDirectory) {
cleanupTasks.push(rm(scratchpadDirectory, { recursive: true, force: true }));
await rm(scratchpadDirectory, { recursive: true, force: true }).catch(() => {
// Best-effort — directory may not exist or be locked
});
}
cleanupTasks.push(
this.sidecar.deleteSession(session.id).then(() => undefined).catch(() => {
// Best-effort — don't fail the deletion if SDK cleanup fails
}),
);
}
await Promise.allSettled(cleanupTasks);
try {
await this.sidecar.deleteSession(session.id);
} catch {
// Best-effort — don't fail the deletion if SDK cleanup fails
}
}
workspace.sessions = workspace.sessions.filter((s) => !idsToDelete.has(s.id));