mirror of
https://github.com/lordmathis/llamactl.git
synced 2025-12-22 17:14:22 +00:00
Refactor JSON marshaling in Options to improve thread safety
This commit is contained in:
@@ -79,14 +79,8 @@ func (o *Options) UnmarshalJSON(data []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *Options) MarshalJSON() ([]byte, error) {
|
func (o *Options) MarshalJSON() ([]byte, error) {
|
||||||
type Alias Options
|
|
||||||
aux := &struct {
|
|
||||||
*Alias
|
|
||||||
}{
|
|
||||||
Alias: (*Alias)(o),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get backend and marshal it
|
// Get backend and marshal it
|
||||||
|
var backendOptions map[string]any
|
||||||
backend := o.getBackend()
|
backend := o.getBackend()
|
||||||
if backend != nil {
|
if backend != nil {
|
||||||
optionsData, err := json.Marshal(backend)
|
optionsData, err := json.Marshal(backend)
|
||||||
@@ -94,13 +88,19 @@ func (o *Options) MarshalJSON() ([]byte, error) {
|
|||||||
return nil, fmt.Errorf("failed to marshal backend options: %w", err)
|
return nil, fmt.Errorf("failed to marshal backend options: %w", err)
|
||||||
}
|
}
|
||||||
// Create a new map to avoid concurrent map writes
|
// Create a new map to avoid concurrent map writes
|
||||||
aux.BackendOptions = make(map[string]any)
|
backendOptions = make(map[string]any)
|
||||||
if err := json.Unmarshal(optionsData, &aux.BackendOptions); err != nil {
|
if err := json.Unmarshal(optionsData, &backendOptions); err != nil {
|
||||||
return nil, fmt.Errorf("failed to unmarshal backend options to map: %w", err)
|
return nil, fmt.Errorf("failed to unmarshal backend options to map: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return json.Marshal(aux)
|
return json.Marshal(&struct {
|
||||||
|
BackendType BackendType `json:"backend_type"`
|
||||||
|
BackendOptions map[string]any `json:"backend_options,omitempty"`
|
||||||
|
}{
|
||||||
|
BackendType: o.BackendType,
|
||||||
|
BackendOptions: backendOptions,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// setBackendOptions stores the backend in the appropriate typed field
|
// setBackendOptions stores the backend in the appropriate typed field
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"llamactl/pkg/config"
|
"llamactl/pkg/config"
|
||||||
"llamactl/pkg/validation"
|
"llamactl/pkg/validation"
|
||||||
"log"
|
"log"
|
||||||
|
"maps"
|
||||||
"slices"
|
"slices"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
@@ -144,15 +145,25 @@ func (c *Options) UnmarshalJSON(data []byte) error {
|
|||||||
|
|
||||||
// MarshalJSON implements custom JSON marshaling for Options
|
// MarshalJSON implements custom JSON marshaling for Options
|
||||||
func (c *Options) MarshalJSON() ([]byte, error) {
|
func (c *Options) MarshalJSON() ([]byte, error) {
|
||||||
// Use anonymous struct to avoid recursion
|
|
||||||
type Alias Options
|
type Alias Options
|
||||||
aux := struct {
|
|
||||||
|
// Make a copy of the struct
|
||||||
|
temp := *c
|
||||||
|
|
||||||
|
// Copy environment map to avoid concurrent access issues
|
||||||
|
if temp.Environment != nil {
|
||||||
|
envCopy := make(map[string]string, len(temp.Environment))
|
||||||
|
maps.Copy(envCopy, temp.Environment)
|
||||||
|
temp.Environment = envCopy
|
||||||
|
}
|
||||||
|
|
||||||
|
aux := &struct {
|
||||||
Nodes []string `json:"nodes,omitempty"` // Output as JSON array
|
Nodes []string `json:"nodes,omitempty"` // Output as JSON array
|
||||||
BackendType backends.BackendType `json:"backend_type"`
|
BackendType backends.BackendType `json:"backend_type"`
|
||||||
BackendOptions map[string]any `json:"backend_options,omitempty"`
|
BackendOptions map[string]any `json:"backend_options,omitempty"`
|
||||||
*Alias
|
*Alias
|
||||||
}{
|
}{
|
||||||
Alias: (*Alias)(c),
|
Alias: (*Alias)(&temp),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert nodes map to array (sorted for consistency)
|
// Convert nodes map to array (sorted for consistency)
|
||||||
@@ -169,13 +180,12 @@ func (c *Options) MarshalJSON() ([]byte, error) {
|
|||||||
aux.BackendType = c.BackendOptions.BackendType
|
aux.BackendType = c.BackendOptions.BackendType
|
||||||
|
|
||||||
// Marshal the backends.Options struct to get the properly formatted backend options
|
// Marshal the backends.Options struct to get the properly formatted backend options
|
||||||
// Marshal a pointer to trigger the pointer receiver MarshalJSON method
|
|
||||||
backendData, err := json.Marshal(&c.BackendOptions)
|
backendData, err := json.Marshal(&c.BackendOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to marshal backend options: %w", err)
|
return nil, fmt.Errorf("failed to marshal backend options: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal into a temporary struct to extract the backend_options map
|
// Unmarshal into a new temporary map to extract the backend_options
|
||||||
var tempBackend struct {
|
var tempBackend struct {
|
||||||
BackendOptions map[string]any `json:"backend_options,omitempty"`
|
BackendOptions map[string]any `json:"backend_options,omitempty"`
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user