From d15976e7aa94e03de00fdf267b81c52510374a84 Mon Sep 17 00:00:00 2001 From: LordMathis Date: Sat, 4 Oct 2025 21:17:55 +0200 Subject: [PATCH] Implement auto-stop for instances with auto-restart disabled and add corresponding tests --- pkg/manager/manager.go | 19 +++++++++-- pkg/manager/manager_test.go | 63 +++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/pkg/manager/manager.go b/pkg/manager/manager.go index 6999643..725b1a9 100644 --- a/pkg/manager/manager.go +++ b/pkg/manager/manager.go @@ -263,19 +263,32 @@ func (im *instanceManager) loadInstance(name, path string) error { } // autoStartInstances starts instances that were running when persisted and have auto-restart enabled +// For instances with auto-restart disabled, it sets their status to Stopped func (im *instanceManager) autoStartInstances() { im.mu.RLock() var instancesToStart []*instance.Process + var instancesToStop []*instance.Process for _, inst := range im.instances { if inst.IsRunning() && // Was running when persisted inst.GetOptions() != nil && - inst.GetOptions().AutoRestart != nil && - *inst.GetOptions().AutoRestart { - instancesToStart = append(instancesToStart, inst) + inst.GetOptions().AutoRestart != nil { + if *inst.GetOptions().AutoRestart { + instancesToStart = append(instancesToStart, inst) + } else { + // Instance was running but auto-restart is disabled, mark as stopped + instancesToStop = append(instancesToStop, inst) + } } } im.mu.RUnlock() + // Stop instances that have auto-restart disabled + for _, inst := range instancesToStop { + log.Printf("Instance %s was running but auto-restart is disabled, setting status to stopped", inst.Name) + inst.SetStatus(instance.Stopped) + } + + // Start instances that have auto-restart enabled for _, inst := range instancesToStart { log.Printf("Auto-starting instance %s", inst.Name) // Reset running state before starting (since Start() expects stopped instance) diff --git a/pkg/manager/manager_test.go b/pkg/manager/manager_test.go index c629c63..3b683d6 100644 --- a/pkg/manager/manager_test.go +++ b/pkg/manager/manager_test.go @@ -209,3 +209,66 @@ func createTestManager() manager.InstanceManager { } return manager.NewInstanceManager(backendConfig, cfg) } + +func TestAutoRestartDisabledInstanceStatus(t *testing.T) { + tempDir := t.TempDir() + + backendConfig := config.BackendConfig{ + LlamaCpp: config.BackendSettings{ + Command: "llama-server", + }, + } + + cfg := config.InstancesConfig{ + PortRange: [2]int{8000, 9000}, + InstancesDir: tempDir, + MaxInstances: 10, + TimeoutCheckInterval: 5, + } + + // Create first manager and instance with auto-restart disabled + manager1 := manager.NewInstanceManager(backendConfig, cfg) + + autoRestart := false + options := &instance.CreateInstanceOptions{ + BackendType: backends.BackendTypeLlamaCpp, + AutoRestart: &autoRestart, + LlamaServerOptions: &llamacpp.LlamaServerOptions{ + Model: "/path/to/model.gguf", + Port: 8080, + }, + } + + inst, err := manager1.CreateInstance("test-instance", options) + if err != nil { + t.Fatalf("CreateInstance failed: %v", err) + } + + // Simulate instance being in running state when persisted + // (this would happen if the instance was running when llamactl was stopped) + inst.SetStatus(instance.Running) + + // Shutdown first manager + manager1.Shutdown() + + // Create second manager (simulating restart of llamactl) + manager2 := manager.NewInstanceManager(backendConfig, cfg) + + // Get the loaded instance + loadedInst, err := manager2.GetInstance("test-instance") + if err != nil { + t.Fatalf("GetInstance failed: %v", err) + } + + // The instance should be marked as Stopped, not Running + // because auto-restart is disabled + if loadedInst.IsRunning() { + t.Errorf("Expected instance with auto-restart disabled to be stopped after manager restart, but it was running") + } + + if loadedInst.GetStatus() != instance.Stopped { + t.Errorf("Expected instance status to be Stopped, got %v", loadedInst.GetStatus()) + } + + manager2.Shutdown() +}