pub enum AttemptState {
Allocated,
JitReceived,
Starting,
Idle,
Busy,
Finished,
Failed,
Orphaned,
Cleaned,
}Expand description
The runner-attempt lifecycle, exactly as 04-subsystem-contracts.md draws
it after its 2026-08-21 amendment:
allocated -> jit_received -> starting -> idle | busy
idle -> busy
allocated | jit_received | starting -> failed | orphaned
idle | busy -> finished | failed | orphaned
finished | failed | orphaned -> cleanedidle means the runner process is registered and awaiting its single job
assignment. It is short-lived and is not an idle persistent runner — this
product has none, by D7.
Every transition outside that diagram is rejected, which b1’s
Definition of Done requires. cleaned is absorbing, which is correct and
intended.
The last two edge sets were added by amendment, and the reasons matter to
anyone reading this state machine. b1 first implemented the original
diagram faithfully and surfaced its gaps as an explicit
NoLegalTransition decision rather than inventing edges; the amendment
closed them at the design level, and that decision value is gone with them:
idle -> busy.e3’s Scope step 4 moves an attempt throughjit_received,starting,idle,busyin sequence, and the definition ofidleabove describes a state that by construction precedes a job. Without this edge a runner observed idle and then assigned a job had nowhere legal to go.- Terminal edges out of the three pre-registration states. An attempt
counts against host capacity for exactly as long as it is non-terminal
(
Self::counts_against_capacity), so an attempt that could not reach a terminal state held a host capacity slot permanently: two failed JIT requests on ahost_capacity: 2host wedged that host into starting zero runners, with no error state and no cleanup path.orphanedis included for the restart case, where a pre-registration attempt is found after the agent restarts.
Those edges are also what make seven of the nine FailureReason variants
reachable at all — JitRequestFailed, JitExpired,
RunnerPackageUnverified, RunnerVersionRejected, ProcessStartFailed,
RegistrationTimedOut and TerminatedAfterRegistrationTimeout each occur at
a pre-registration state. 03-control-flows.md flow 2 names the first five
as conditions the agent must record; the last two are named by no document
and are this crate’s own, added because recovery_decision needs to say
“alive, past its deadline, still unregistered” without calling it a crash,
and because e3 then needs to say what became of that runner without
calling a process it stopped itself either a crash or still running.
Variants§
Implementations§
Source§impl AttemptState
impl AttemptState
pub const ALL: [AttemptState; 9]
Sourcepub const LEGAL: &'static [(AttemptState, AttemptState)]
pub const LEGAL: &'static [(AttemptState, AttemptState)]
The complete legal transition list. A self-transition is not in it.
Sourcepub const CONCLUDABLE_FROM: &'static [AttemptState]
pub const CONCLUDABLE_FROM: &'static [AttemptState]
The five states an attempt can still be concluded from: every
non-terminal state. After the amendment this is exactly
“not Self::is_terminal”, which is what closed the permanently-held
capacity slot — but it is written out rather than derived, because the
two are only equal while the diagram gives every live state a terminal
edge, and that equality is a property worth failing loudly on.
pub fn can_transition_to(self, next: AttemptState) -> bool
Sourcepub const fn is_terminal(self) -> bool
pub const fn is_terminal(self) -> bool
Terminal states, at which capacity is reclaimed.
e1: “capacity is reclaimed only when an attempt reaches a terminal
state.” cleaned is included because it follows a terminal state.
Sourcepub const fn counts_against_capacity(self) -> bool
pub const fn counts_against_capacity(self) -> bool
Whether this attempt still occupies one of the host’s capacity slots.
This is the term the reconciliation formula subtracts, and getting it
wrong is silent: counting a terminal attempt starves the host, and failing
to count a starting one starts a second runner for a job already being
served.
Sourcepub const fn is_concluded(self) -> bool
pub const fn is_concluded(self) -> bool
The three terminal states that require an outcome before cleaned.
Trait Implementations§
Source§impl Clone for AttemptState
impl Clone for AttemptState
Source§fn clone(&self) -> AttemptState
fn clone(&self) -> AttemptState
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more