Skip to content

Commit 093b02e

Browse files
committed
Fix deploy delete fallback verification
1 parent c9a38e4 commit 093b02e

2 files changed

Lines changed: 76 additions & 3 deletions

File tree

cmd/aima/tooldeps_deploy.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ func buildDeployDeps(ac *appContext, deps *mcp.ToolDeps,
474474
deletedAt := time.Now()
475475
tombstoneKeys := []string{name}
476476
seenKeys := map[string]struct{}{normalizeDeletedDeploymentKey(name): {}}
477+
verificationQueries := []string{name}
477478
rememberKey := func(key string) {
478479
norm := normalizeDeletedDeploymentKey(key)
479480
if norm == "" {
@@ -485,6 +486,18 @@ func buildDeployDeps(ac *appContext, deps *mcp.ToolDeps,
485486
seenKeys[norm] = struct{}{}
486487
tombstoneKeys = append(tombstoneKeys, key)
487488
}
489+
rememberVerificationQuery := func(key string) {
490+
norm := normalizeDeletedDeploymentKey(key)
491+
if norm == "" {
492+
return
493+
}
494+
for _, existing := range verificationQueries {
495+
if normalizeDeletedDeploymentKey(existing) == norm {
496+
return
497+
}
498+
}
499+
verificationQueries = append(verificationQueries, key)
500+
}
488501

489502
for _, match := range matches {
490503
if match.Runtime == nil || match.Status == nil {
@@ -494,11 +507,16 @@ func buildDeployDeps(ac *appContext, deps *mcp.ToolDeps,
494507
return fmt.Errorf("delete deployment %q on %s: %w", match.Status.Name, match.Runtime.Name(), err)
495508
}
496509
rememberKey(match.Status.Name)
497-
rememberKey(deploymentModelKey(match.Status))
510+
modelKey := deploymentModelKey(match.Status)
511+
rememberKey(modelKey)
512+
rememberVerificationQuery(match.Status.Name)
513+
rememberVerificationQuery(modelKey)
498514
}
499515

500-
if remaining := findMatchingDeployments(ctx, name, nil, rt, nativeRt, dockerRt); len(remaining) > 0 {
501-
return fmt.Errorf("delete deployment %q: deployment still active after delete (%s)", name, summarizeMatchedDeployments(remaining))
516+
for _, query := range verificationQueries {
517+
if remaining := findMatchingDeployments(ctx, query, nil, rt, nativeRt, dockerRt); len(remaining) > 0 {
518+
return fmt.Errorf("delete deployment %q: deployment still active after delete (%s)", name, summarizeMatchedDeployments(remaining))
519+
}
502520
}
503521

504522
for _, key := range tombstoneKeys {

cmd/aima/uat_chain_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,61 @@ func TestDeployDeleteFallsBackFromModelNameToResolvedDeploymentName(t *testing.T
260260
}
261261
}
262262

263+
func TestDeployDeleteFallbackFailsWhenResolvedDeploymentStillActive(t *testing.T) {
264+
ctx := context.Background()
265+
db, err := state.Open(ctx, ":memory:")
266+
if err != nil {
267+
t.Fatalf("Open: %v", err)
268+
}
269+
defer db.Close()
270+
271+
deploy := &aimaRuntime.DeploymentStatus{
272+
Name: "qwen3-6-35b-a3b-sglang",
273+
Phase: "running",
274+
Ready: true,
275+
Runtime: "docker",
276+
Labels: map[string]string{
277+
"aima.dev/model": "qwen3-6-35b-a3b",
278+
"aima.dev/engine": "sglang",
279+
},
280+
}
281+
dockerRt := &deleteTrackingRuntime{
282+
name: "docker",
283+
status: map[string]*aimaRuntime.DeploymentStatus{deploy.Name: deploy},
284+
aliases: map[string]string{"qwen3.6-35b-a3b": deploy.Name},
285+
keep: map[string]bool{deploy.Name: true},
286+
}
287+
288+
deps := &mcp.ToolDeps{}
289+
buildDeployDeps(&appContext{
290+
db: db,
291+
rt: dockerRt,
292+
dockerRt: dockerRt,
293+
proxy: proxy.NewServer(),
294+
}, deps,
295+
func(context.Context, string, func(string, string), func(int64, int64)) error { return nil },
296+
func(context.Context, string, string, string, map[string]any, bool, func(string, string), func(engine.ProgressEvent), func(int64, int64)) (json.RawMessage, error) {
297+
return nil, nil
298+
},
299+
)
300+
301+
err = deps.DeployDelete(ctx, "qwen3.6-35b-a3b")
302+
if err == nil {
303+
t.Fatal("DeployDelete error = nil, want verification failure")
304+
}
305+
if !strings.Contains(err.Error(), "still active after delete") {
306+
t.Fatalf("DeployDelete error = %v, want still-active verification failure", err)
307+
}
308+
309+
tombstones, err := db.ListDeletedDeploymentsSince(ctx, time.Now().Add(-time.Minute))
310+
if err != nil {
311+
t.Fatalf("ListDeletedDeploymentsSince: %v", err)
312+
}
313+
if len(tombstones) != 0 {
314+
t.Fatalf("deleted deployment tombstones = %v, want empty on failed delete", tombstones)
315+
}
316+
}
317+
263318
func TestDeployListAndStatusExposeTopLevelModelAndEngine(t *testing.T) {
264319
ctx := context.Background()
265320
db, err := state.Open(ctx, ":memory:")

0 commit comments

Comments
 (0)