diff --git a/apps/desktop/src/lib/trpc/routers/projects/projects.ts b/apps/desktop/src/lib/trpc/routers/projects/projects.ts index a13dd998237..d60d9582c23 100644 --- a/apps/desktop/src/lib/trpc/routers/projects/projects.ts +++ b/apps/desktop/src/lib/trpc/routers/projects/projects.ts @@ -22,6 +22,7 @@ import { publicProcedure, router } from "../.."; import { activateProject, getBranchWorkspace, + selectNextActiveWorkspace, setLastActiveWorkspace, touchWorkspace, } from "../workspaces/utils/db-helpers"; @@ -941,48 +942,49 @@ export const createProjectsRouter = (getWindow: () => BrowserWindow | null) => { .where(eq(workspaces.projectId, input.id)) .all(); - let totalFailed = 0; - const registry = getWorkspaceRuntimeRegistry(); - for (const workspace of projectWorkspaces) { - const terminal = registry.getForWorkspaceId(workspace.id).terminal; - const terminalResult = await terminal.killByWorkspaceId(workspace.id); - totalFailed += terminalResult.failed; - } - const closedWorkspaceIds = projectWorkspaces.map((w) => w.id); + // Must run before the async terminal kill so queries exclude + // these workspaces while terminals are still shutting down. if (closedWorkspaceIds.length > 0) { localDb - .delete(workspaces) + .update(workspaces) + .set({ deletingAt: Date.now() }) .where(inArray(workspaces.id, closedWorkspaceIds)) .run(); } - // Hide the project by setting tabOrder to null localDb .update(projects) .set({ tabOrder: null }) .where(eq(projects.id, input.id)) .run(); - // Update active workspace if it was in this project const currentSettings = localDb.select().from(settings).get(); if ( currentSettings?.lastActiveWorkspaceId && closedWorkspaceIds.includes(currentSettings.lastActiveWorkspaceId) ) { - const remainingWorkspaces = localDb - .select() - .from(workspaces) - .orderBy(desc(workspaces.lastOpenedAt)) - .all(); + setLastActiveWorkspace(selectNextActiveWorkspace()); + } + + const registry = getWorkspaceRuntimeRegistry(); + const terminalResults = await Promise.all( + projectWorkspaces.map((workspace) => + registry + .getForWorkspaceId(workspace.id) + .terminal.killByWorkspaceId(workspace.id), + ), + ); + const totalFailed = terminalResults.reduce( + (sum, r) => sum + r.failed, + 0, + ); + if (closedWorkspaceIds.length > 0) { localDb - .update(settings) - .set({ - lastActiveWorkspaceId: remainingWorkspaces[0]?.id ?? null, - }) - .where(eq(settings.id, 1)) + .delete(workspaces) + .where(inArray(workspaces.id, closedWorkspaceIds)) .run(); } diff --git a/apps/desktop/src/lib/trpc/routers/workspaces/procedures/delete.ts b/apps/desktop/src/lib/trpc/routers/workspaces/procedures/delete.ts index a38421e137c..040d429d1b3 100644 --- a/apps/desktop/src/lib/trpc/routers/workspaces/procedures/delete.ts +++ b/apps/desktop/src/lib/trpc/routers/workspaces/procedures/delete.ts @@ -310,13 +310,17 @@ export const createDeleteProcedures = () => { throw new Error("Workspace not found"); } + // Must run before the async terminal kill so queries exclude + // this workspace while terminals are still shutting down. + markWorkspaceAsDeleting(input.id); + updateActiveWorkspaceIfRemoved(input.id); + const terminalResult = await getWorkspaceRuntimeRegistry() .getForWorkspaceId(input.id) .terminal.killByWorkspaceId(input.id); deleteWorkspace(input.id); hideProjectIfNoWorkspaces(workspace.projectId); - updateActiveWorkspaceIfRemoved(input.id); const terminalWarning = terminalResult.failed > 0