Fix paused session resume lifecycle
This commit is contained in:
parent
e1136fdb82
commit
49e43248b0
|
|
@ -119,15 +119,23 @@ func (s *Session) ToolsConn() *toolclient.ToolsrvConn {
|
|||
// Caller is responsible for closing the returned conn.
|
||||
func (s *Session) DialToolServer() *toolclient.ToolsrvConn {
|
||||
s.mu.RLock()
|
||||
if s.paused {
|
||||
s.mu.RUnlock()
|
||||
return nil
|
||||
}
|
||||
k := s.Keeper
|
||||
s.mu.RUnlock()
|
||||
if k == nil {
|
||||
s.log.Debug("DialToolServer: no keeper")
|
||||
return nil
|
||||
}
|
||||
s.log.Debug("DialToolServer: dialing keeper paused=%v", s.IsPaused())
|
||||
conn, err := k.Dial()
|
||||
if err != nil {
|
||||
s.log.Debug("DialToolServer: dial failed: %v", err)
|
||||
return nil
|
||||
}
|
||||
s.log.Debug("DialToolServer: dial succeeded")
|
||||
return conn
|
||||
}
|
||||
|
||||
|
|
@ -351,24 +359,31 @@ func (s *Session) SetSessionID(newID string) error {
|
|||
|
||||
// Pause stops the tool server to save resources.
|
||||
func (s *Session) Pause() error {
|
||||
s.log.Debug("Pause: begin")
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.paused {
|
||||
return fmt.Errorf("session already paused")
|
||||
}
|
||||
s.paused = true
|
||||
s.log.Debug("Pause: marked paused")
|
||||
if s.Cancel != nil {
|
||||
s.Cancel()
|
||||
}
|
||||
s.log.Debug("Pause: context canceled")
|
||||
if s.Keeper != nil {
|
||||
s.log.Debug("Pause: closing keeper")
|
||||
s.Keeper.Close()
|
||||
} else if s.Proc != nil {
|
||||
s.Proc.Close()
|
||||
}
|
||||
if s.toolsConn != nil {
|
||||
s.log.Debug("Pause: closing tools connection")
|
||||
s.toolsConn.Close()
|
||||
s.toolsConn = nil
|
||||
}
|
||||
s.paused = true
|
||||
s.log.Debug("Pause: complete")
|
||||
go s.saveSession()
|
||||
PublishEvent("session."+s.ID+".pause", "")
|
||||
return nil
|
||||
|
|
@ -376,26 +391,31 @@ func (s *Session) Pause() error {
|
|||
|
||||
// Resume restarts the tool server after a Pause.
|
||||
func (s *Session) Resume() error {
|
||||
s.log.Debug("Resume: begin")
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if !s.paused {
|
||||
s.mu.Unlock()
|
||||
return fmt.Errorf("session not paused")
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(serverCtx)
|
||||
s.Ctx = ctx
|
||||
s.Cancel = cancel
|
||||
s.log.Debug("Resume: context created")
|
||||
|
||||
// Ensure we always have a Keeper. If the session was restored from disk
|
||||
// without infra, spawn a new tool server now.
|
||||
if s.Keeper == nil {
|
||||
cwd := ""
|
||||
if len(s.agents) > 0 {
|
||||
cwd = s.agents[0].Cwd()
|
||||
}
|
||||
s.log.Info("Resume: no keeper, starting toolsrv")
|
||||
cwd := s.cwd
|
||||
if cwd == "" {
|
||||
cwd, _ = os.Getwd()
|
||||
}
|
||||
if s.Remote != "" {
|
||||
s.log.Info("Resume: spawning remote toolsrv target=%s cwd=%s", s.Remote, cwd)
|
||||
} else {
|
||||
s.log.Info("Resume: spawning local toolsrv cwd=%s", cwd)
|
||||
}
|
||||
infra, err := SetupToolServer(ToolServerConfig{
|
||||
Ctx: ctx,
|
||||
CWD: cwd,
|
||||
|
|
@ -404,8 +424,12 @@ func (s *Session) Resume() error {
|
|||
Yolo: pkgYolo,
|
||||
})
|
||||
if err != nil {
|
||||
s.log.Error("Resume: toolsrv startup failed: %v", err)
|
||||
cancel()
|
||||
s.mu.Unlock()
|
||||
return fmt.Errorf("resume: %w", err)
|
||||
}
|
||||
s.log.Info("Resume: toolsrv started")
|
||||
s.Proc = infra.Proc
|
||||
s.Keeper = infra.Keeper
|
||||
s.toolsConn = infra.ToolsConn
|
||||
|
|
@ -415,12 +439,14 @@ func (s *Session) Resume() error {
|
|||
}
|
||||
} else {
|
||||
// Keeper exists — just re-dial.
|
||||
s.log.Debug("Resume: dialing existing keeper")
|
||||
s.Keeper.SetContext(ctx)
|
||||
conn, err := s.Keeper.Dial()
|
||||
if err != nil {
|
||||
return fmt.Errorf("resume failed: %w", err)
|
||||
}
|
||||
s.toolsConn = conn
|
||||
s.log.Debug("Resume: existing keeper dial succeeded")
|
||||
// Update agent connections with fresh dials
|
||||
for _, ag := range s.agents {
|
||||
agConn, err := s.Keeper.Dial()
|
||||
|
|
@ -436,6 +462,13 @@ func (s *Session) Resume() error {
|
|||
}
|
||||
|
||||
s.paused = false
|
||||
s.mu.Unlock()
|
||||
s.log.Debug("Resume: marked active")
|
||||
|
||||
// Start bypass approval loop for the new session context.
|
||||
if pkgBypassNotify != nil {
|
||||
s.StartBypassLoop(pkgBypassNotify)
|
||||
}
|
||||
|
||||
// Rebuild full runtimes for restored agents (they have stub runtimes from persist).
|
||||
for _, ag := range s.agents {
|
||||
|
|
@ -450,6 +483,7 @@ func (s *Session) Resume() error {
|
|||
}
|
||||
go s.saveSession()
|
||||
PublishEvent("session."+s.ID+".resume", "")
|
||||
s.log.Debug("Resume: complete")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue