Unexport instance options

This commit is contained in:
2025-07-19 11:53:35 +02:00
parent 13bbf07465
commit 016e67a6c4
2 changed files with 69 additions and 30 deletions

View File

@@ -3,6 +3,7 @@ package llamactl
import ( import (
"bufio" "bufio"
"context" "context"
"encoding/json"
"fmt" "fmt"
"io" "io"
"log" "log"
@@ -13,7 +14,7 @@ import (
type Instance struct { type Instance struct {
Name string `json:"name"` Name string `json:"name"`
Options *InstanceOptions `json:"options,omitempty"` options *InstanceOptions `json:"-"` // Now unexported - access via GetOptions/SetOptions
// Status // Status
Running bool `json:"running"` Running bool `json:"running"`
@@ -35,7 +36,7 @@ type Instance struct {
func NewInstance(name string, options *InstanceOptions) *Instance { func NewInstance(name string, options *InstanceOptions) *Instance {
return &Instance{ return &Instance{
Name: name, Name: name,
Options: options, options: options,
Running: false, Running: false,
@@ -47,7 +48,7 @@ func NewInstance(name string, options *InstanceOptions) *Instance {
func (i *Instance) GetOptions() *InstanceOptions { func (i *Instance) GetOptions() *InstanceOptions {
i.mu.Lock() i.mu.Lock()
defer i.mu.Unlock() defer i.mu.Unlock()
return i.Options return i.options
} }
func (i *Instance) SetOptions(options *InstanceOptions) { func (i *Instance) SetOptions(options *InstanceOptions) {
@@ -57,7 +58,7 @@ func (i *Instance) SetOptions(options *InstanceOptions) {
log.Println("Warning: Attempted to set nil options on instance", i.Name) log.Println("Warning: Attempted to set nil options on instance", i.Name)
return return
} }
i.Options = options i.options = options
} }
func (i *Instance) Start() error { func (i *Instance) Start() error {
@@ -68,7 +69,7 @@ func (i *Instance) Start() error {
return fmt.Errorf("instance %s is already running", i.Name) return fmt.Errorf("instance %s is already running", i.Name)
} }
args := i.Options.BuildCommandArgs() args := i.options.BuildCommandArgs()
i.ctx, i.cancel = context.WithCancel(context.Background()) i.ctx, i.cancel = context.WithCancel(context.Background())
i.cmd = exec.CommandContext(i.ctx, "llama-server", args...) i.cmd = exec.CommandContext(i.ctx, "llama-server", args...)
@@ -170,14 +171,14 @@ func (i *Instance) monitorProcess() {
} }
// Handle restart if process crashed and auto-restart is enabled // Handle restart if process crashed and auto-restart is enabled
if err != nil && i.Options.AutoRestart && i.restarts < i.Options.MaxRestarts { if err != nil && i.options.AutoRestart && i.restarts < i.options.MaxRestarts {
i.restarts++ i.restarts++
log.Printf("Auto-restarting instance %s (attempt %d/%d) in %v", log.Printf("Auto-restarting instance %s (attempt %d/%d) in %v",
i.Name, i.restarts, i.Options.MaxRestarts, i.Options.RestartDelay.ToDuration()) i.Name, i.restarts, i.options.MaxRestarts, i.options.RestartDelay.ToDuration())
// Unlock mutex during sleep to avoid blocking other operations // Unlock mutex during sleep to avoid blocking other operations
i.mu.Unlock() i.mu.Unlock()
time.Sleep(i.Options.RestartDelay.ToDuration()) time.Sleep(i.options.RestartDelay.ToDuration())
i.mu.Lock() i.mu.Lock()
// Attempt restart // Attempt restart
@@ -187,7 +188,59 @@ func (i *Instance) monitorProcess() {
log.Printf("Successfully restarted instance %s", i.Name) log.Printf("Successfully restarted instance %s", i.Name)
i.restarts = 0 // Reset restart count on successful restart i.restarts = 0 // Reset restart count on successful restart
} }
} else if i.restarts >= i.Options.MaxRestarts { } else if i.restarts >= i.options.MaxRestarts {
log.Printf("Instance %s exceeded max restart attempts (%d)", i.Name, i.Options.MaxRestarts) log.Printf("Instance %s exceeded max restart attempts (%d)", i.Name, i.options.MaxRestarts)
} }
} }
// MarshalJSON implements json.Marshaler for Instance
func (i *Instance) MarshalJSON() ([]byte, error) {
i.mu.Lock()
defer i.mu.Unlock()
// Create a temporary struct with exported fields for JSON marshalling
temp := struct {
Name string `json:"name"`
Options *InstanceOptions `json:"options,omitempty"`
Running bool `json:"running"`
}{
Name: i.Name,
Options: i.options,
Running: i.Running,
}
return json.Marshal(temp)
}
// UnmarshalJSON implements json.Unmarshaler for Instance
func (i *Instance) UnmarshalJSON(data []byte) error {
// Create a temporary struct for unmarshalling
temp := struct {
Name string `json:"name"`
Options *InstanceOptions `json:"options,omitempty"`
Running bool `json:"running"`
}{}
if err := json.Unmarshal(data, &temp); err != nil {
return err
}
// Set the fields
i.Name = temp.Name
i.Running = temp.Running
// Handle options - ensure embedded LlamaServerOptions is initialized
if temp.Options != nil {
i.options = temp.Options
}
// Initialize channels if they don't exist
if i.StdOutChan == nil {
i.StdOutChan = make(chan string, 100)
}
if i.StdErrChan == nil {
i.StdErrChan = make(chan string, 100)
}
return nil
}

View File

@@ -40,26 +40,7 @@ type InstanceOptions struct {
MaxRestarts int `json:"max_restarts,omitempty"` MaxRestarts int `json:"max_restarts,omitempty"`
RestartDelay Duration `json:"restart_delay,omitempty" example:"5"` // Duration in seconds RestartDelay Duration `json:"restart_delay,omitempty" example:"5"` // Duration in seconds
*LlamaServerOptions LlamaServerOptions `json:",inline"`
}
// UnmarshalJSON implements custom JSON unmarshaling with default values
func (o *InstanceOptions) UnmarshalJSON(data []byte) error {
// Set defaults first
o.AutoRestart = true
o.MaxRestarts = 3
o.RestartDelay = Duration(5 * time.Second) // 5 seconds
// Create a temporary struct to avoid recursion
type tempInstanceOptions InstanceOptions
temp := (*tempInstanceOptions)(o)
// Unmarshal into the temporary struct
if err := json.Unmarshal(data, temp); err != nil {
return err
}
return nil
} }
type LlamaServerOptions struct { type LlamaServerOptions struct {
@@ -417,3 +398,8 @@ func (o *LlamaServerOptions) BuildCommandArgs() []string {
return args return args
} }
// BuildCommandArgs converts InstanceOptions to command line arguments by delegating to LlamaServerOptions
func (o *InstanceOptions) BuildCommandArgs() []string {
return o.LlamaServerOptions.BuildCommandArgs()
}