nixfleet_state_machine/rollout/
error.rs

1//! Rollout reducer error path. Parallel to the per-host `TransitionError`
2//! (`crate::error`). The applier logs + drops or surfaces depending on
3//! the variant.
4
5use thiserror::Error;
6
7use crate::rollout::state::{RolloutId, RolloutState};
8
9#[derive(Debug, Error, Clone, PartialEq)]
10pub enum RolloutTransitionError {
11    /// The event is not legal from the current `RolloutState`. Typically
12    /// out-of-order arrival (e.g., `RolloutTerminal` from `Opening` before
13    /// any host joined).
14    #[error("event {event} not legal from rollout state {from:?} (rollout {rollout_id})")]
15    IllegalForState {
16        from: RolloutState,
17        event: &'static str,
18        rollout_id: RolloutId,
19    },
20
21    /// A `RolloutOpened` arrived for a `(channel, ref)` whose channel
22    /// already has an `active_rollout_id`. The planner must emit
23    /// `SuccessorOpened` first (RFC-0008 §3 invariant).
24    #[error(
25        "rollout {rollout_id} opened on channel {channel} without prior SuccessorOpened (expected supersession)"
26    )]
27    SupersessionExpected {
28        rollout_id: RolloutId,
29        channel: String,
30    },
31
32    /// Invariant from RFC-0008 §3 violated by the event's payload (e.g.,
33    /// `RolloutTerminal` while at least one host is not Converged).
34    #[error("rollout invariant violation: {0}")]
35    Invariant(&'static str),
36
37    /// Reducer arm not yet implemented. Returned by the Phase 10a
38    /// skeleton; every variant gets a real arm in Phase 10b. Should never
39    /// be reached after Phase 10 closes — if it is, that's a code defect.
40    #[error("rollout transition not yet implemented for event {event} from state {from:?}")]
41    Unimplemented {
42        from: RolloutState,
43        event: &'static str,
44    },
45}