forked from molecule-ai/molecule-core
Merge pull request #2848 from Molecule-AI/feat/2799-phase3-pause-1777961500
feat(handlers): migrate Pause loop to StopWorkspaceAuto — #2799 Phase 3 (closes #2799)
This commit is contained in:
commit
d10c1a1a36
@ -894,6 +894,32 @@ func TestRunRestartCycle_UsesProvisionWorkspaceAutoSync(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestPauseHandler_UsesStopWorkspaceAuto — Phase 3 of #2799 source-level
|
||||
// pin. Pause's per-workspace stop call must route through
|
||||
// StopWorkspaceAuto so SaaS tenants terminate the EC2 instead of leaking
|
||||
// it (same drift class as the team-collapse leak #2813 and the
|
||||
// workspace-delete leak #2814 closed by PR #2824).
|
||||
//
|
||||
// Pause-specific bookkeeping (mark paused, clear keys, broadcast)
|
||||
// stays in the Pause handler — only the "stop the running workload"
|
||||
// step delegates to the dispatcher. This pin asserts the dispatcher
|
||||
// is called from the Pause loop with `ws.id`.
|
||||
func TestPauseHandler_UsesStopWorkspaceAuto(t *testing.T) {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("getwd: %v", err)
|
||||
}
|
||||
src, err := os.ReadFile(filepath.Join(wd, "workspace_restart.go"))
|
||||
if err != nil {
|
||||
t.Fatalf("read workspace_restart.go: %v", err)
|
||||
}
|
||||
stripped := stripGoComments(src)
|
||||
if !bytes.Contains(stripped, []byte("h.StopWorkspaceAuto(ctx, ws.id)")) {
|
||||
t.Errorf("workspace_restart.go must call StopWorkspaceAuto from the Pause loop with `ws.id` — current code does not. " +
|
||||
"Phase 3 of #2799 migrated this site; do not regress to the inline `if h.provisioner != nil { Stop }` dispatch.")
|
||||
}
|
||||
}
|
||||
|
||||
// stripGoComments removes // line comments and /* */ block comments
|
||||
// from Go source. Imperfect (doesn't handle comments-inside-strings)
|
||||
// but adequate for the source-level pin tests in this file — none of
|
||||
|
||||
@ -613,10 +613,18 @@ func (h *WorkspaceHandler) Pause(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// Stop containers and mark all as paused
|
||||
// Stop containers and mark all as paused. StopWorkspaceAuto routes
|
||||
// to whichever backend is wired (CP for SaaS, Docker for self-hosted)
|
||||
// — pre-2026-05-05 this site inlined `if h.provisioner != nil { Stop }`,
|
||||
// which silently leaked EC2s on every SaaS Pause (same drift class as
|
||||
// the team-collapse leak #2813 and the workspace-delete leak #2814,
|
||||
// both closed by PR #2824). StopWorkspaceAuto returns nil on no-backend
|
||||
// (no-op), so the Pause-specific bookkeeping (mark paused, clear keys,
|
||||
// broadcast) still fires regardless of whether anything was actually
|
||||
// stopped — matches the pre-fix behavior on misconfigured deployments.
|
||||
for _, ws := range toPause {
|
||||
if h.provisioner != nil {
|
||||
h.provisioner.Stop(ctx, ws.id)
|
||||
if err := h.StopWorkspaceAuto(ctx, ws.id); err != nil {
|
||||
log.Printf("Pause: stop %s failed: %v — orphan sweeper will reconcile", ws.id, err)
|
||||
}
|
||||
db.DB.ExecContext(ctx,
|
||||
`UPDATE workspaces SET status = $1, url = '', updated_at = now() WHERE id = $2`, models.StatusPaused, ws.id)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user