nixfleet_state_machine/
error.rs

1//! Reducer error path. Distinct from runtime errors — these mean the input
2//! event is structurally inapplicable to the current state, which is a
3//! runtime invariant violation (out-of-order event, stale seq, etc.). The
4//! runtime layer decides whether to log + drop, request replay, or panic.
5
6use thiserror::Error;
7
8use crate::state::{HostState, RolloutId};
9
10#[derive(Debug, Error, Clone, PartialEq)]
11pub enum TransitionError {
12    /// The event is not legal from the current `HostState`. The runtime
13    /// layer should typically log + drop (lost-ordering noise) and rely on
14    /// heartbeat drift-detection to recover via Replay-From (RFC-0005 §4.3).
15    #[error("event {event} not legal from state {from:?} (rollout {rollout_id}, host {hostname})")]
16    IllegalForState {
17        from: HostState,
18        event: &'static str,
19        rollout_id: RolloutId,
20        hostname: String,
21    },
22
23    /// Event `seq` is not strictly greater than `last_event_seq`. Could be
24    /// a retransmit (idempotent, runtime dedupes on `(host, rollout, seq)`)
25    /// or out-of-order arrival.
26    #[error(
27        "event seq {got} is not > last_event_seq {last} (rollout {rollout_id}, host {hostname})"
28    )]
29    SeqRegression {
30        got: u64,
31        last: u64,
32        rollout_id: RolloutId,
33        hostname: String,
34    },
35
36    /// Invariant from RFC-0005 §3 violated by the event's payload (e.g.
37    /// `Converged` claimed but `current != target`). CP rejects the event
38    /// with `409 Conflict`; agent retries after re-verifying.
39    #[error("invariant violation: {0}")]
40    Invariant(&'static str),
41
42    /// Reducer arm not yet implemented. Returned by the Phase 3a skeleton;
43    /// every variant gets a real arm in Phase 3b. Should never be reached
44    /// after Phase 3 closes — if it is, that's a code defect.
45    #[error("transition not yet implemented for event {event} from state {from:?}")]
46    Unimplemented {
47        from: HostState,
48        event: &'static str,
49    },
50}