Files
kandev/apps/backend/internal/agent/runtime/lifecycle/manager_resume_attempt.go
T
2026-09-13 12:08:05 +01:00

43 lines
1.4 KiB
Go

package lifecycle
import (
"context"
"fmt"
)
// BindResumeAttempt attaches a prompt-owned recovery identity to the startup
// generation of an execution that is already being initialized. The execution
// store guard makes the session-to-execution lookup and identity update one
// mutation, so a replacement execution cannot be rebound accidentally.
func (m *Manager) BindResumeAttempt(_ context.Context, sessionID, attemptID string) error {
if m == nil || m.executionStore == nil {
return fmt.Errorf("execution store is unavailable")
}
if sessionID == "" || attemptID == "" {
return fmt.Errorf("session ID and attempt ID are required")
}
execution, exists := m.executionStore.GetBySessionID(sessionID)
if !exists || execution == nil {
return ErrExecutionNotFound
}
// Startup callbacks acquire startupCallbackMu before they take the
// execution-store lock. Acquire the same locks in that order here so an
// adopted execution cannot deadlock a callback while its identity is bound.
execution.startupCallbackMu.Lock()
defer execution.startupCallbackMu.Unlock()
bound := false
err := m.executionStore.WithLock(execution.ID, func(current *AgentExecution) {
if current == execution && current.SessionID == sessionID {
bound = current.bindStartupAttemptIDWithLease(attemptID)
}
})
if err != nil {
return err
}
if !bound {
return fmt.Errorf("execution %q has no startup generation", execution.ID)
}
return nil
}