nixfleet_state_machine/transitions/
mod.rs1mod activating;
13mod converged;
14mod deferred;
15mod failed;
16mod pending;
17mod reverted;
18mod soaking;
19
20use chrono::{DateTime, Utc};
21use nixfleet_proto::RolloutPolicy;
22
23use crate::effect::Effect;
24use crate::error::TransitionError;
25use crate::event::Event;
26use crate::state::{HostRolloutState, HostState};
27
28pub(crate) fn dispatch(
29 state: HostRolloutState,
30 event: Event,
31 now: DateTime<Utc>,
32 policy: &RolloutPolicy,
33) -> Result<(HostRolloutState, Vec<Effect>), TransitionError> {
34 let got = event.seq();
39 if got <= state.last_event_seq {
40 return Err(TransitionError::SeqRegression {
41 got,
42 last: state.last_event_seq,
43 rollout_id: state.rollout_id.clone(),
44 hostname: state.hostname.clone(),
45 });
46 }
47
48 match state.state {
49 HostState::Pending => pending::handle(state, event, now, policy),
50 HostState::Activating => activating::handle(state, event, now, policy),
51 HostState::Deferred => deferred::handle(state, event, now, policy),
52 HostState::Soaking => soaking::handle(state, event, now, policy),
53 HostState::Failed => failed::handle(state, event, now, policy),
54 HostState::Converged => converged::handle(state, event, now, policy),
55 HostState::Reverted => reverted::handle(state, event, now, policy),
56 }
57}
58
59pub(crate) fn event_name(event: &Event) -> &'static str {
61 match event {
62 Event::LocalActivate { .. } => "LocalActivate",
63 Event::LocalActivationStarted { .. } => "LocalActivationStarted",
64 Event::LocalActivationCompleted { .. } => "LocalActivationCompleted",
65 Event::LocalActivationDeferred { .. } => "LocalActivationDeferred",
66 Event::LocalActivationFailed { .. } => "LocalActivationFailed",
67 Event::LocalProbeTopologyDeclared { .. } => "LocalProbeTopologyDeclared",
68 Event::LocalProbeObservedFirst { .. } => "LocalProbeObservedFirst",
69 Event::LocalProbeResult { .. } => "LocalProbeResult",
70 Event::LocalProbeFailureFirst { .. } => "LocalProbeFailureFirst",
71 Event::LocalSustainedFailureCrossed { .. } => "LocalSustainedFailureCrossed",
72 Event::LocalRollbackCompleted { .. } => "LocalRollbackCompleted",
73 Event::LocalConvergedReached { .. } => "LocalConvergedReached",
74 Event::RemoteDispatchAck { .. } => "RemoteDispatchAck",
75 Event::RemoteActivationStarted { .. } => "RemoteActivationStarted",
76 Event::RemoteActivationCompleted { .. } => "RemoteActivationCompleted",
77 Event::RemoteActivationDeferred { .. } => "RemoteActivationDeferred",
78 Event::RemoteActivationFailed { .. } => "RemoteActivationFailed",
79 Event::RemoteProbeTopologyDeclared { .. } => "RemoteProbeTopologyDeclared",
80 Event::RemoteProbeObservedFirst { .. } => "RemoteProbeObservedFirst",
81 Event::RemoteProbeResult { .. } => "RemoteProbeResult",
82 Event::RemoteProbeFailureFirst { .. } => "RemoteProbeFailureFirst",
83 Event::RemoteFailed { .. } => "RemoteFailed",
84 Event::RemoteRollbackComplete { .. } => "RemoteRollbackComplete",
85 Event::RemoteConverged { .. } => "RemoteConverged",
86 }
87}
88
89pub(crate) fn illegal(state: &HostRolloutState, event: &Event) -> TransitionError {
90 TransitionError::IllegalForState {
91 from: state.state,
92 event: event_name(event),
93 rollout_id: state.rollout_id.clone(),
94 hostname: state.hostname.clone(),
95 }
96}