From be9cf10e027ed0fb0fffc4bd242368567bc5a7db Mon Sep 17 00:00:00 2001 From: josh Date: Sun, 13 Sep 2026 19:01:13 -0400 Subject: [PATCH] Wait for container teardown before deleting Komodo deployment entity execute/DestroyDeployment queues the container removal and returns before it actually completes. write/DeleteDeployment refuses while a container still exists for the deployment, so the entity survived every teardown. Poll komodoInspectHealthy between the two calls until it stops reporting a running container (up to 30s), then delete the entity. Co-Authored-By: Claude Opus 4.7 --- src/lib/server/fleet/create.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/lib/server/fleet/create.ts b/src/lib/server/fleet/create.ts index f326080..1c6466d 100644 --- a/src/lib/server/fleet/create.ts +++ b/src/lib/server/fleet/create.ts @@ -8,6 +8,7 @@ import { komodoDeploy, komodoDestroyDeployment, komodoDeleteDeployment, + komodoInspectHealthy, type CreateDeploymentSpec, type DeploymentEnvVar } from '../integrations/komodo.js'; @@ -222,12 +223,25 @@ export async function destroyServer(name: string): Promise const warnings: string[] = []; - // 1 + 2: Komodo teardown. Try both endpoints even if one fails — the - // deployment entity might already be gone while the container is still up. + // 1: stop + remove the container. execute/DestroyDeployment queues the + // teardown; the response comes back before the container is actually gone. const destroyRes = await komodoDestroyDeployment(name); if (!destroyRes.ok) { warnings.push(`DestroyDeployment failed: ${destroyRes.message}`); } + + // 2: wait for the container to actually disappear. Komodo refuses to + // DeleteDeployment while a container still exists for it, so poll the + // health probe until it stops reporting a running state. `ok:false` here + // is the *success* signal — it means the container is no longer inspectable. + const pollDeadline = Date.now() + 30_000; + while (Date.now() < pollDeadline) { + const health = await komodoInspectHealthy(name); + if (!health.ok) break; + await new Promise((resolve) => setTimeout(resolve, 1500)); + } + + // 3: remove the deployment entity itself. const deleteRes = await komodoDeleteDeployment(name); if (!deleteRes.ok) { warnings.push(`DeleteDeployment failed: ${deleteRes.message}`);