job_queue: delete the cancelled-power-op intent revert
The revert hook is dead by construction, so it can only ever be wrong. DAG state `Cancelled` has exactly one producer: `JobQueue::cancel`, which refuses unless every work node is still `Pending`. A cancel *cascade* (some node failed, downstream cancelled) rolls up `Failed` instead — `dag_rollup` short-circuits on any failed subtree node. So on a DAG that reaches `Cancelled`, no node ever executed: the `SetWanted` head provably never ran and `wanted` still reads whatever the operator last set it to. There is therefore nothing to revert, and `revert_intent` did not revert anything — it wrote `Wanted::from_running(observed)`, i.e. the agent's *observed* state, over an intent the DAG never touched. Harmless when observed already matched, silent corruption otherwise: cancel a queued start for an agent that is down but `wanted = Up` (crashed, or caught mid-bounce) and the intent flips to `Offline`, leaving it deliberately-stopped as far as reconcile and crash-watch are concerned. The hook made sense when `set_wanted` was a pre-submit side effect written before the DAG ran; moving it into the DAG as a node left the hook vestigial. Drop `HookKind::RevertIntent`, `revert_intent`, and the power-op arm of `terminal_hook` — start / stop / graceful-stop now settle with no terminal hook, same as restart always did. The test asserts the general statement across restart/stop/start x graceful x running: stop and start carry a `SetWanted` head, and cancelling them still fires no hook.
This commit is contained in:
parent
7589f4c06c
commit
5c4a637941
4 changed files with 64 additions and 79 deletions
|
|
@ -169,22 +169,18 @@ pub enum HookKind {
|
|||
ResolveApproval,
|
||||
/// Rebuild / perm-change: emit one `Rebuilt` manager event per agent.
|
||||
EmitRebuilt,
|
||||
/// Intent-writing power-op: on a *cancelled* DAG, revert each agent's
|
||||
/// `wanted` intent. Only for templates that actually carry a `SetWanted`
|
||||
/// head — reverting an intent a DAG never wrote invents one.
|
||||
RevertIntent,
|
||||
}
|
||||
|
||||
/// The terminal hook a DAG needs, from its template + approval id — or `None`
|
||||
/// for a DAG with no terminal side effect (meta-update, boot, bare reconcile).
|
||||
/// for a DAG with no terminal side effect (power-op, meta-update, boot, bare
|
||||
/// reconcile).
|
||||
///
|
||||
/// Restart is deliberately **not** a `RevertIntent` template. `restart_chain`
|
||||
/// writes no `SetWanted` (it bounces the container and lets the tail
|
||||
/// `Reconcile` converge to the agent's existing intent), so there is nothing
|
||||
/// for a cancel to revert — and `revert_intent` writes the *observed* state,
|
||||
/// which for a down-but-`wanted = Up` agent (crashed, or mid-bounce) would
|
||||
/// flip it to `Offline` and keep it down. Cancelling a restart must leave the
|
||||
/// intent exactly as it was found.
|
||||
/// A cancelled DAG deliberately gets **no** compensating hook. [`JobQueue::cancel`]
|
||||
/// refuses unless every work node is still `Pending`, and a cancel *cascade*
|
||||
/// rolls up `Failed` (see `dag_rollup`), never `Cancelled` — so on a
|
||||
/// `Cancelled` DAG no node ever executed and there is nothing to undo. A power
|
||||
/// op's `SetWanted` head provably never ran, so its intent is still whatever
|
||||
/// the operator last set it to.
|
||||
#[must_use]
|
||||
pub fn terminal_hook(template: Template, approval_id: Option<i64>) -> Option<HookKind> {
|
||||
if approval_id.is_some() {
|
||||
|
|
@ -192,7 +188,6 @@ pub fn terminal_hook(template: Template, approval_id: Option<i64>) -> Option<Hoo
|
|||
}
|
||||
match template {
|
||||
Template::Rebuild | Template::PermChange => Some(HookKind::EmitRebuilt),
|
||||
Template::Start | Template::Stop | Template::GracefulStop => Some(HookKind::RevertIntent),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue