fix(runtime): cancel de background task immédiat et fiable depuis le workstate (#199, QA verte)
Transforme l'annulation d'une background task en contrat immédiat, observable et non-best-effort: - domain/background_task: états Cancelling/Cancelled/CancelFailed et transitions idempotentes; un kill PTY qui échoue est surfacé en CancelFailed plutôt qu'en succès silencieux. - infrastructure/runner + store: cancel effectif de la task ciblée, reconcile marque Cancelling même sans live handle, et départage CancelFailed des tâches pending au boot. - application/background + workstate + orchestrator/wake: chemin de cancel initié depuis le workstate, projection synchronisée de l'état (pas d'attente d'un cycle ambigu). - frontend: projection workstate de l'état cancelled/cancelling/cancelFailed (cancellingRow/cancelFailedRow/cancelButtons), normalization et services. Tests QA verts: background_task_cancel, background_task_runner cancel_wins_even_if_output_is_still_available, background_task_store reconcile_marks_cancelling_without_live_handle_cancel_failed_and_pending, workstate.test.tsx.
This commit is contained in:
@ -5161,9 +5161,11 @@ fn background_state_label(state: BackgroundTaskState) -> &'static str {
|
||||
BackgroundTaskState::Queued => "queued",
|
||||
BackgroundTaskState::Running => "running",
|
||||
BackgroundTaskState::Waiting => "waiting",
|
||||
BackgroundTaskState::Cancelling => "cancelling",
|
||||
BackgroundTaskState::Completed => "completed",
|
||||
BackgroundTaskState::Failed => "failed",
|
||||
BackgroundTaskState::Cancelled => "cancelled",
|
||||
BackgroundTaskState::CancelFailed => "cancelFailed",
|
||||
BackgroundTaskState::Expired => "expired",
|
||||
}
|
||||
}
|
||||
@ -5201,6 +5203,9 @@ impl From<BackgroundTask> for BackgroundTaskDto {
|
||||
| Some(BackgroundTaskResult::Expired { reason, .. }) => {
|
||||
(None, Some(reason.clone()), None, None)
|
||||
}
|
||||
Some(BackgroundTaskResult::CancelFailed { error, .. }) => {
|
||||
(None, Some(error.clone()), None, None)
|
||||
}
|
||||
None => (None, None, None, None),
|
||||
};
|
||||
Self {
|
||||
|
||||
@ -1357,6 +1357,7 @@ fn background_task_tail_bytes(task: &BackgroundTask) -> Vec<u8> {
|
||||
.into_bytes(),
|
||||
Some(BackgroundTaskResult::Cancelled { reason, .. })
|
||||
| Some(BackgroundTaskResult::Expired { reason, .. }) => reason.clone().into_bytes(),
|
||||
Some(BackgroundTaskResult::CancelFailed { error, .. }) => error.clone().into_bytes(),
|
||||
None => Vec::new(),
|
||||
}
|
||||
}
|
||||
@ -2452,10 +2453,14 @@ impl BackendCore {
|
||||
)
|
||||
.with_events(Arc::clone(&events_port)),
|
||||
);
|
||||
let cancel_background_task = Arc::new(CancelBackgroundTask::new(
|
||||
Arc::clone(&background_tasks_port),
|
||||
Arc::clone(&background_runner_port),
|
||||
));
|
||||
let cancel_background_task = Arc::new(
|
||||
CancelBackgroundTask::new(
|
||||
Arc::clone(&background_tasks_port),
|
||||
Arc::clone(&background_runner_port),
|
||||
Arc::clone(&clock) as Arc<dyn Clock>,
|
||||
)
|
||||
.with_events(Arc::clone(&events_port)),
|
||||
);
|
||||
let retry_background_task = Arc::new(RetryBackgroundTask::new(
|
||||
Arc::clone(&background_tasks_port),
|
||||
Arc::clone(&background_runner) as Arc<dyn BackgroundCommandArchive>,
|
||||
|
||||
Reference in New Issue
Block a user