fix(ui): clarify optimistic instance close

Keep the tab-close fix optimistic by removing the instance from local state immediately, but make the backend workspace deletion explicitly fire-and-forget instead of exposing a misleading async stop contract.

Remove stale awaits from call sites so callers no longer imply that stopInstance waits for backend teardown. If backend deletion fails after the tab is closed, surface the failure through the existing localized toast notification system while still logging the underlying error.

Validation: npm run typecheck --workspace @codenomad/ui; npm run build --workspace @codenomad/ui; git diff --check.
This commit is contained in:
Shantur Rathore 2026-06-15 09:36:42 +01:00
parent bbfc2ace22
commit 86ac87a314
12 changed files with 20 additions and 5 deletions

View file

@ -389,7 +389,7 @@ const App: Component = () => {
if (!confirmed) return
await stopInstance(instanceId)
stopInstance(instanceId)
}
async function handleNewSession(instanceId: string) {

View file

@ -67,7 +67,7 @@ const SessionPicker: Component<SessionPickerProps> = (props) => {
}
async function handleCancel() {
await stopInstance(props.instanceId)
stopInstance(props.instanceId)
props.onClose()
}

View file

@ -12,6 +12,7 @@ export const appMessages = {
"app.stopInstance.title": "Instanz stoppen",
"app.stopInstance.confirmLabel": "Stoppen",
"app.stopInstance.cancelLabel": "Weiterlaufen lassen",
"app.stopInstance.toast.error": "Arbeitsbereich konnte nicht gestoppt werden.",
"emptyState.logoAlt": "CodeNomad Logo",
"emptyState.brandTitle": "CodeNomad",

View file

@ -12,6 +12,7 @@ export const appMessages = {
"app.stopInstance.title": "Stop instance",
"app.stopInstance.confirmLabel": "Stop",
"app.stopInstance.cancelLabel": "Keep running",
"app.stopInstance.toast.error": "Failed to stop workspace.",
"emptyState.logoAlt": "CodeNomad logo",
"emptyState.brandTitle": "CodeNomad",

View file

@ -12,6 +12,7 @@ export const appMessages = {
"app.stopInstance.title": "Detener instancia",
"app.stopInstance.confirmLabel": "Detener",
"app.stopInstance.cancelLabel": "Seguir ejecutándose",
"app.stopInstance.toast.error": "No se pudo detener el workspace.",
"emptyState.logoAlt": "Logo de CodeNomad",
"emptyState.brandTitle": "CodeNomad",

View file

@ -12,6 +12,7 @@ export const appMessages = {
"app.stopInstance.title": "Arrêter l'instance",
"app.stopInstance.confirmLabel": "Arrêter",
"app.stopInstance.cancelLabel": "Laisser tourner",
"app.stopInstance.toast.error": "Impossible d'arrêter l'espace de travail.",
"emptyState.logoAlt": "Logo CodeNomad",
"emptyState.brandTitle": "CodeNomad",

View file

@ -12,6 +12,7 @@ export const appMessages = {
"app.stopInstance.title": "עצור מופע",
"app.stopInstance.confirmLabel": "עצור",
"app.stopInstance.cancelLabel": "המשך להריץ",
"app.stopInstance.toast.error": "עצירת סביבת העבודה נכשלה.",
"emptyState.logoAlt": "לוגו CodeNomad",
"emptyState.brandTitle": "CodeNomad",

View file

@ -12,6 +12,7 @@ export const appMessages = {
"app.stopInstance.title": "インスタンスを停止",
"app.stopInstance.confirmLabel": "停止",
"app.stopInstance.cancelLabel": "実行を続ける",
"app.stopInstance.toast.error": "ワークスペースの停止に失敗しました。",
"emptyState.logoAlt": "CodeNomad ロゴ",
"emptyState.brandTitle": "CodeNomad",

View file

@ -12,6 +12,7 @@ export const appMessages = {
"app.stopInstance.title": "उदाहरण रोक्नुहोस्",
"app.stopInstance.confirmLabel": "रोक्नुहोस्",
"app.stopInstance.cancelLabel": "चालु राख्नुहोस्",
"app.stopInstance.toast.error": "कार्यस्थान रोक्न असफल भयो।",
"emptyState.logoAlt": "CodeNomad लोगो",
"emptyState.brandTitle": "CodeNomad",

View file

@ -12,6 +12,7 @@ export const appMessages = {
"app.stopInstance.title": "Остановить экземпляр",
"app.stopInstance.confirmLabel": "Остановить",
"app.stopInstance.cancelLabel": "Оставить запущенным",
"app.stopInstance.toast.error": "Не удалось остановить рабочее пространство.",
"emptyState.logoAlt": "Логотип CodeNomad",
"emptyState.brandTitle": "CodeNomad",

View file

@ -12,6 +12,7 @@ export const appMessages = {
"app.stopInstance.title": "停止实例",
"app.stopInstance.confirmLabel": "停止",
"app.stopInstance.cancelLabel": "继续运行",
"app.stopInstance.toast.error": "无法停止工作区。",
"emptyState.logoAlt": "CodeNomad 徽标",
"emptyState.brandTitle": "CodeNomad",

View file

@ -54,6 +54,8 @@ import { mergeInstanceMetadata, clearInstanceMetadata } from "./instance-metadat
import { showWorkspaceLaunchError } from "./launch-errors"
import { activeSidecarToken } from "./sidecars"
import { buildV2RequestLocations, type V2Location } from "./request-locations"
import { showToastNotification } from "../lib/notifications"
import { tGlobal } from "../lib/i18n"
const log = getLogger("api")
@ -715,15 +717,19 @@ function updateProjectNameForFolder(folder: string, projectName: string): void {
}
}
async function stopInstance(id: string) {
function stopInstance(id: string) {
const instance = instances().get(id)
if (!instance) return
releaseInstanceResources(id)
removeInstance(id)
serverApi.deleteWorkspace(id).catch((error) => {
void serverApi.deleteWorkspace(id).catch((error) => {
log.error("Failed to stop workspace", error)
showToastNotification({
message: tGlobal("app.stopInstance.toast.error"),
variant: "error",
})
})
}
@ -1348,7 +1354,7 @@ async function acknowledgeDisconnectedInstance(): Promise<void> {
}
try {
await stopInstance(pending.id)
stopInstance(pending.id)
} catch (error) {
log.error("Failed to stop disconnected instance", error)
} finally {