refactor(#2756): declare the terminal hook instead of inferring it
`Template` was a DAG-level enum that three different things read back out: `terminal_hook()` mapped it to a side effect, the retention pass bucketed history by it, and a tracing field printed it. None of those needed a *label* — they needed the two facts the label happened to encode. So the enum was a lossy stand-in for intent, and every new DAG shape had to pick the variant whose inferred behaviour matched, whether or not the name fit (`reparent` rode `MetaUpdate` for exactly this reason, with a 10-line comment apologising for it). Replace the inference with a declaration: `DagSpec.hook: Option<HookKind>`. Only the builder assembling a DAG knows why it did so, so only the builder can say what should happen when it settles. `run_terminal_hook` becomes a field read, and `reparent`'s apology becomes `hook: None`. Hook assignment is byte-identical to the old precedence rule (`approval_id.is_some()` wins, then `Rebuild | PermChange`), checked site by site; `meta_update` is the only builder with a variable approval id and so the only remaining conditional. Retention loses the per-template bucket with the enum that keyed it. The dashboard renders one recent-builds list, so one flat newest-first cap (`MAX_HISTORY_DAGS`) bounds it. `HISTORY_GRACE_SECS` goes too — it existed to stop a burst of same-template DAGs evicting each other inside one poll interval, which is not a failure mode a flat cap has. That takes `snapshot_capped()` and the `snapshot_no_grace()` test hook with it. The queue is runtime-only (empty graph on boot), so the serde changes carry no migration risk.
This commit is contained in:
parent
a8728ac532
commit
ca7146e4f0
8 changed files with 113 additions and 241 deletions
|
|
@ -97,18 +97,18 @@ pub(super) async fn run_node(coord: &Arc<Coordinator>, claim: &Claim) -> Result<
|
|||
NodeKind::DeployTail { .. } => run_deploy_tail(coord, claim).await,
|
||||
NodeKind::SetWanted { up, .. } => run_set_wanted(coord, claim, *up),
|
||||
// Pure grouping container — no work; completing it lets it reach
|
||||
// `Finishing` so its child template nodes start. The DAG's terminal
|
||||
// `Finishing` so its child work nodes start. The DAG's terminal
|
||||
// hook fires (inline, via `run_terminal_hook`) when the container itself
|
||||
// rolls up terminal — not as a scheduled node.
|
||||
NodeKind::Dag { .. } => Ok(NodeOutput::default()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Run a settled DAG's inline terminal hook, dispatched off its rolled-up
|
||||
/// summary — the container-terminal replacement for the old per-DAG hook node.
|
||||
/// Always best-effort: a hook failure is logged inside, never surfaced.
|
||||
/// Run a settled DAG's inline terminal hook — the container-terminal
|
||||
/// replacement for the old per-DAG hook node. Always best-effort: a hook
|
||||
/// failure is logged inside, never surfaced.
|
||||
pub(crate) async fn run_terminal_hook(coord: &Arc<Coordinator>, terminal: &super::TerminalDag) {
|
||||
match super::terminal_hook(terminal.template, terminal.approval_id) {
|
||||
match terminal.hook {
|
||||
Some(super::HookKind::ResolveApproval) => {
|
||||
crate::actions::resolve_approval_dag(coord, terminal).await;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue