forked from molecule-ai/molecule-core
Both restart paths (interactive Restart handler + auto-restart's stopForRestart) used to log-and-continue on cpProv.Stop failure. After PR #2500 made CPProvisioner.Stop surface CP non-2xx as an error, those paths became the actual leak generator: every transient CP/AWS hiccup = one orphan EC2 alongside the freshly provisioned one. The 13 zombie workspace EC2s on demo-prep staging traced to this exact path. Adds cpStopWithRetry helper with bounded exponential backoff (3 attempts, 1s/2s/4s). Different policy from workspace_crud.go's Delete handler: Delete returns 500 to the client on Stop failure (loud-fail-and-block — user asked to destroy, silent leak unacceptable), whereas Restart's contract is "make the workspace alive again" — refusing to reprovision strands the user with a dead workspace. So this helper retries to absorb transient failures, then on exhaustion emits a structured `LEAK-SUSPECT` log line for the (forthcoming) CP-side workspace orphan reconciler to correlate. Caller proceeds to reprovision regardless. ctx-cancel exits the retry early without sleeping the backoff (matters during shutdown drain); the cancel path emits a distinct log line and deliberately does NOT emit LEAK-SUSPECT — operator-cancel and retry-exhaustion are different signals and conflating them would noise up the orphan-reconciler queue with workspaces we never had a chance to retry. Tests: 5 behavior tests covering every branch (no-op, first-try success, eventual success, exhaustion, ctx-cancel) + 1 AST gate that pins the helper-only invariant (any future inline `h.cpProv.Stop(...)` in workspace_restart.go fires the gate, mutation-tested). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| cmd/server | ||
| internal | ||
| migrations | ||
| pkg/provisionhook | ||
| .ci-force | ||
| .gitignore | ||
| .golangci.yaml | ||
| Dockerfile | ||
| Dockerfile.tenant | ||
| entrypoint-tenant.sh | ||
| go.mod | ||
| go.sum | ||