|
@@ -85,6 +85,33 @@ namespace ClankerSaddle.Services {
|
|
|
|
|
|
|
|
private OrmSession db = inject<OrmSession>();
|
|
private OrmSession db = inject<OrmSession>();
|
|
|
private StatePulse pulse = inject<StatePulse>();
|
|
private StatePulse pulse = inject<StatePulse>();
|
|
|
|
|
+ private SubtaskEventQueue subtask_events = inject<SubtaskEventQueue>();
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Records a subtask's current state for the daemon hosting its
|
|
|
|
|
+ * parent's live or parked session (`POST /subtask-status`, wire
|
|
|
|
|
+ * contract). The wire carries the four guard-relevant values;
|
|
|
|
|
+ * intermediate web states (assigned, blocked, review-requested,
|
|
|
|
|
+ * suspended) all mean "still in flight" and map to `working`.
|
|
|
|
|
+ * Only the latest state per subtask is kept (queue coalescing).
|
|
|
|
|
+ */
|
|
|
|
|
+ private void note_subtask_event(TaskEntity task) {
|
|
|
|
|
+ if (task.parent_task_id <= 0) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ string wire_status = STATUS_WORKING;
|
|
|
|
|
+ if (task.status == STATUS_QUEUED || task.status == STATUS_DONE
|
|
|
|
|
+ || task.status == STATUS_FAILED) {
|
|
|
|
|
+ wire_status = task.status;
|
|
|
|
|
+ }
|
|
|
|
|
+ subtask_events.enqueue(new SubtaskStatusEvent() {
|
|
|
|
|
+ parent_task_id = task.parent_task_id,
|
|
|
|
|
+ subtask_id = task.id,
|
|
|
|
|
+ title = task.title,
|
|
|
|
|
+ status = wire_status,
|
|
|
|
|
+ summary = task.summary ?? ""
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* Inserts a task (status 'queued'). `parent_task_id`,
|
|
* Inserts a task (status 'queued'). `parent_task_id`,
|
|
@@ -129,9 +156,19 @@ namespace ClankerSaddle.Services {
|
|
|
};
|
|
};
|
|
|
yield db.insert_async<TaskEntity>(task);
|
|
yield db.insert_async<TaskEntity>(task);
|
|
|
yield pulse.bump(task.id, "task created");
|
|
yield pulse.bump(task.id, "task created");
|
|
|
|
|
+ note_subtask_event(task);
|
|
|
return task;
|
|
return task;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Public requeue note for callers that write the queued status
|
|
|
|
|
+ * directly ({@link SaddleService.mark_saddle_unreachable}): the
|
|
|
|
|
+ * subtask's parent daemon hears about the state change.
|
|
|
|
|
+ */
|
|
|
|
|
+ public void note_requeued_subtask(TaskEntity task) {
|
|
|
|
|
+ note_subtask_event(task);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* Loads the full aggregate for `id`: the task, its comments, blocks,
|
|
* Loads the full aggregate for `id`: the task, its comments, blocks,
|
|
|
* progress, child tasks, dependencies and sessions. Returns null
|
|
* progress, child tasks, dependencies and sessions. Returns null
|
|
@@ -305,6 +342,9 @@ namespace ClankerSaddle.Services {
|
|
|
yield db.update_async<TaskEntity>(task);
|
|
yield db.update_async<TaskEntity>(task);
|
|
|
if (changed) {
|
|
if (changed) {
|
|
|
yield pulse.bump(id, @"task $(status ?? "saved")");
|
|
yield pulse.bump(id, @"task $(status ?? "saved")");
|
|
|
|
|
+ if (status != null && status.length > 0) {
|
|
|
|
|
+ note_subtask_event(((!)task));
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
return task;
|
|
return task;
|
|
|
}
|
|
}
|
|
@@ -635,6 +675,7 @@ namespace ClankerSaddle.Services {
|
|
|
yield close_open_sessions(task_id, outcome);
|
|
yield close_open_sessions(task_id, outcome);
|
|
|
yield free_saddles_running(task_id);
|
|
yield free_saddles_running(task_id);
|
|
|
yield pulse.bump(task_id, "task completed");
|
|
yield pulse.bump(task_id, "task completed");
|
|
|
|
|
+ note_subtask_event(((!)task));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -661,6 +702,7 @@ namespace ClankerSaddle.Services {
|
|
|
yield close_open_sessions(task_id, "stopped");
|
|
yield close_open_sessions(task_id, "stopped");
|
|
|
yield free_saddles_running(task_id);
|
|
yield free_saddles_running(task_id);
|
|
|
yield pulse.bump(task_id, "task cancelled");
|
|
yield pulse.bump(task_id, "task cancelled");
|
|
|
|
|
+ note_subtask_event(((!)task));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -691,6 +733,7 @@ namespace ClankerSaddle.Services {
|
|
|
yield close_open_sessions(task_id, "failed");
|
|
yield close_open_sessions(task_id, "failed");
|
|
|
yield free_saddles_running(task_id);
|
|
yield free_saddles_running(task_id);
|
|
|
yield pulse.bump(task_id, "task failed");
|
|
yield pulse.bump(task_id, "task failed");
|
|
|
|
|
+ note_subtask_event(((!)task));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -792,6 +835,9 @@ namespace ClankerSaddle.Services {
|
|
|
yield close_open_sessions(task_id, "stopped");
|
|
yield close_open_sessions(task_id, "stopped");
|
|
|
yield free_saddles_running(task_id);
|
|
yield free_saddles_running(task_id);
|
|
|
yield pulse.bump(task_id, "task requeued");
|
|
yield pulse.bump(task_id, "task requeued");
|
|
|
|
|
+ if (task != null) {
|
|
|
|
|
+ note_subtask_event(((!)task));
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -823,6 +869,7 @@ namespace ClankerSaddle.Services {
|
|
|
yield free_saddles_running(task_id);
|
|
yield free_saddles_running(task_id);
|
|
|
yield add_comment(task_id, "bot", "Task retried by user");
|
|
yield add_comment(task_id, "bot", "Task retried by user");
|
|
|
yield pulse.bump(task_id, "task retried");
|
|
yield pulse.bump(task_id, "task retried");
|
|
|
|
|
+ note_subtask_event(task);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|