mirror of
https://github.com/lordmathis/llamactl.git
synced 2025-11-05 16:44:22 +00:00
Refactor instance locking mechanism to use per-instance locks for concurrency
This commit is contained in:
@@ -40,8 +40,9 @@ type instanceManager struct {
|
|||||||
localNodeName string // Name of the local node
|
localNodeName string // Name of the local node
|
||||||
|
|
||||||
// Synchronization
|
// Synchronization
|
||||||
operationMu sync.Mutex // Protects start/stop/update/delete/restart operations
|
operationMu sync.Mutex // DEPRECATED: Use instanceLocks for per-instance operations
|
||||||
shutdownOnce sync.Once
|
instanceLocks sync.Map // map[string]*sync.Mutex - per-instance locks for concurrent operations
|
||||||
|
shutdownOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new instance of InstanceManager.
|
// New creates a new instance of InstanceManager.
|
||||||
@@ -287,3 +288,20 @@ func (im *instanceManager) getNodeForInstance(inst *instance.Instance) *config.N
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lockInstance returns the lock for a specific instance, creating one if needed.
|
||||||
|
// This allows concurrent operations on different instances while preventing
|
||||||
|
// concurrent operations on the same instance.
|
||||||
|
func (im *instanceManager) lockInstance(name string) *sync.Mutex {
|
||||||
|
lock, _ := im.instanceLocks.LoadOrStore(name, &sync.Mutex{})
|
||||||
|
return lock.(*sync.Mutex)
|
||||||
|
}
|
||||||
|
|
||||||
|
// unlockAndCleanup unlocks the instance lock and removes it from the map.
|
||||||
|
// This should only be called when deleting an instance to prevent memory leaks.
|
||||||
|
func (im *instanceManager) unlockAndCleanup(name string) {
|
||||||
|
if lock, ok := im.instanceLocks.Load(name); ok {
|
||||||
|
lock.(*sync.Mutex).Unlock()
|
||||||
|
im.instanceLocks.Delete(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -240,9 +240,10 @@ func (im *instanceManager) UpdateInstance(name string, options *instance.Options
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock for local instance operations to prevent races
|
// Lock this specific instance only
|
||||||
im.operationMu.Lock()
|
lock := im.lockInstance(name)
|
||||||
defer im.operationMu.Unlock()
|
lock.Lock()
|
||||||
|
defer lock.Unlock()
|
||||||
|
|
||||||
// Handle port changes
|
// Handle port changes
|
||||||
oldPort := inst.GetPort()
|
oldPort := inst.GetPort()
|
||||||
@@ -330,9 +331,10 @@ func (im *instanceManager) DeleteInstance(name string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock for local instance operations to prevent races
|
// Lock this specific instance and clean up the lock on completion
|
||||||
im.operationMu.Lock()
|
lock := im.lockInstance(name)
|
||||||
defer im.operationMu.Unlock()
|
lock.Lock()
|
||||||
|
defer im.unlockAndCleanup(name)
|
||||||
|
|
||||||
if inst.IsRunning() {
|
if inst.IsRunning() {
|
||||||
return fmt.Errorf("instance with name %s is still running, stop it before deleting", name)
|
return fmt.Errorf("instance with name %s is still running, stop it before deleting", name)
|
||||||
@@ -376,9 +378,10 @@ func (im *instanceManager) StartInstance(name string) (*instance.Instance, error
|
|||||||
return inst, nil
|
return inst, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock for local instance operations to prevent races
|
// Lock this specific instance only
|
||||||
im.operationMu.Lock()
|
lock := im.lockInstance(name)
|
||||||
defer im.operationMu.Unlock()
|
lock.Lock()
|
||||||
|
defer lock.Unlock()
|
||||||
|
|
||||||
if inst.IsRunning() {
|
if inst.IsRunning() {
|
||||||
return inst, fmt.Errorf("instance with name %s is already running", name)
|
return inst, fmt.Errorf("instance with name %s is already running", name)
|
||||||
@@ -438,9 +441,10 @@ func (im *instanceManager) StopInstance(name string) (*instance.Instance, error)
|
|||||||
return inst, nil
|
return inst, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock for local instance operations to prevent races
|
// Lock this specific instance only
|
||||||
im.operationMu.Lock()
|
lock := im.lockInstance(name)
|
||||||
defer im.operationMu.Unlock()
|
lock.Lock()
|
||||||
|
defer lock.Unlock()
|
||||||
|
|
||||||
if !inst.IsRunning() {
|
if !inst.IsRunning() {
|
||||||
return inst, fmt.Errorf("instance with name %s is already stopped", name)
|
return inst, fmt.Errorf("instance with name %s is already stopped", name)
|
||||||
@@ -479,9 +483,10 @@ func (im *instanceManager) RestartInstance(name string) (*instance.Instance, err
|
|||||||
return inst, nil
|
return inst, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock for the entire restart operation to ensure atomicity
|
// Lock this specific instance for the entire restart operation to ensure atomicity
|
||||||
im.operationMu.Lock()
|
lock := im.lockInstance(name)
|
||||||
defer im.operationMu.Unlock()
|
lock.Lock()
|
||||||
|
defer lock.Unlock()
|
||||||
|
|
||||||
// Stop the instance
|
// Stop the instance
|
||||||
if inst.IsRunning() {
|
if inst.IsRunning() {
|
||||||
|
|||||||
Reference in New Issue
Block a user