Run discards on the state-driven coordinator
This commit is contained in:
+31
-84
@@ -134,7 +134,7 @@ func (m *Manager) searchClosedText(ctx context.Context, projectID, query string,
|
||||
}
|
||||
|
||||
func (m *Manager) Discard(ctx context.Context, task api.Task, actor string) (api.Task, error) {
|
||||
state, err := m.store.RequestDiscard(ctx, task.Id, actor)
|
||||
err := m.store.RequestDiscard(ctx, task.Id, actor)
|
||||
switch {
|
||||
case errors.Is(err, store.ErrNotFound):
|
||||
return api.Task{}, fmt.Errorf("%w: task %s is closed", ErrConflict, task.Id)
|
||||
@@ -149,94 +149,74 @@ func (m *Manager) Discard(ctx context.Context, task api.Task, actor string) (api
|
||||
case err != nil:
|
||||
return api.Task{}, err
|
||||
}
|
||||
if state == store.DiscardClosing {
|
||||
go m.finishDiscard(task.Id)
|
||||
} else {
|
||||
go m.startDiscard(task.Id)
|
||||
}
|
||||
return m.store.GetTask(ctx, task.Id)
|
||||
}
|
||||
|
||||
func (m *Manager) startDiscard(taskID string) {
|
||||
ctx := context.Background()
|
||||
started, err := m.launchDiscard(ctx, taskID)
|
||||
func (m *Manager) startDiscard(ctx context.Context, taskID string) {
|
||||
err := m.beginDiscard(ctx, taskID)
|
||||
if err == nil {
|
||||
if started {
|
||||
slog.Info("discard turn started", "task", taskID)
|
||||
}
|
||||
return
|
||||
}
|
||||
slog.Error("start discard turn", "task", taskID, "err", err)
|
||||
err = m.store.CloseDiscard(ctx, taskID)
|
||||
if err != nil {
|
||||
slog.Error("close discard", "task", taskID, "err", err)
|
||||
return
|
||||
}
|
||||
m.finishDiscard(taskID)
|
||||
m.closeDiscard(ctx, taskID)
|
||||
}
|
||||
|
||||
func (m *Manager) launchDiscard(ctx context.Context, taskID string) (bool, error) {
|
||||
func (m *Manager) closeDiscard(ctx context.Context, taskID string) {
|
||||
err := m.store.CloseDiscard(ctx, taskID)
|
||||
if err != nil {
|
||||
slog.Error("close discard", "task", taskID, "err", err)
|
||||
}
|
||||
m.poke()
|
||||
}
|
||||
|
||||
func (m *Manager) beginDiscard(ctx context.Context, taskID string) error {
|
||||
task, err := m.store.GetTask(ctx, taskID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return err
|
||||
}
|
||||
sess, found, err := m.liveSession(ctx, taskID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return err
|
||||
}
|
||||
if !found {
|
||||
creator, err := m.store.GetUser(ctx, task.CreatedBy)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return err
|
||||
}
|
||||
sess, err = m.newSession(ctx, task, creator, sess.Member, "")
|
||||
if err != nil {
|
||||
return false, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = m.store.StartDiscardTurn(ctx, taskID, sess.Id, "byre")
|
||||
if errors.Is(err, store.ErrStateChanged) {
|
||||
return false, nil
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
return err
|
||||
}
|
||||
_, err = m.launch(ctx, sess, task, "byre", discardPrompt, "", "", nil)
|
||||
return err == nil, err
|
||||
slog.Info("discard turn started", "task", taskID)
|
||||
go func() {
|
||||
ctx := context.Background()
|
||||
_, err := m.launch(ctx, sess, task, "byre", discardPrompt, "", "", nil)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
slog.Error("launch discard turn", "task", taskID, "err", err)
|
||||
m.closeDiscard(ctx, taskID)
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) finishDiscard(taskID string) {
|
||||
m.mu.Lock()
|
||||
if m.finishing[taskID] {
|
||||
m.mu.Unlock()
|
||||
return
|
||||
}
|
||||
m.finishing[taskID] = true
|
||||
m.mu.Unlock()
|
||||
defer func() {
|
||||
m.mu.Lock()
|
||||
delete(m.finishing, taskID)
|
||||
m.mu.Unlock()
|
||||
}()
|
||||
|
||||
ctx := context.Background()
|
||||
err := m.discardNow(ctx, taskID)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
slog.Error("finish discard", "task", taskID, "err", err)
|
||||
sessions, serr := m.store.ListSessions(ctx, taskID)
|
||||
if serr != nil {
|
||||
slog.Error("list sessions for discard error", "task", taskID, "err", serr)
|
||||
return
|
||||
}
|
||||
task, terr := m.store.GetTask(ctx, taskID)
|
||||
if terr != nil {
|
||||
slog.Error("load task for discard error", "task", taskID, "err", terr)
|
||||
return
|
||||
}
|
||||
m.fileTaskError(ctx, task, sessions, "Discarding the task failed: "+err.Error()+". Discard again to retry; byre also retries when it next starts.")
|
||||
m.fileError(ctx, taskID, "Discarding the task failed: "+err.Error()+". byre retries when it next starts.")
|
||||
}
|
||||
|
||||
func (m *Manager) discardNow(ctx context.Context, taskID string) error {
|
||||
@@ -264,36 +244,3 @@ func (m *Manager) discardNow(ctx context.Context, taskID string) error {
|
||||
_, err = m.store.DiscardTask(ctx, task.Id, discard.By)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *Manager) recoverDiscards(ctx context.Context) error {
|
||||
tasks, err := m.store.PendingDiscards(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, t := range tasks {
|
||||
discard, err := m.store.GetDiscard(ctx, t.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch discard.State {
|
||||
case store.DiscardHeld:
|
||||
go m.startDiscard(t.Id)
|
||||
case store.DiscardClosing:
|
||||
go m.finishDiscard(t.Id)
|
||||
case store.DiscardRunning:
|
||||
sess, err := m.store.GetSession(ctx, discard.Session)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if sess.State == api.AgentSessionStateRunning {
|
||||
continue
|
||||
}
|
||||
err = m.store.CloseDiscard(ctx, t.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go m.finishDiscard(t.Id)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user