nixfleet_state_machine/transitions/
failed.rs1use chrono::{DateTime, Utc};
13use nixfleet_proto::RolloutPolicy;
14
15use crate::effect::{Effect, OutboundAgentEvent};
16use crate::error::TransitionError;
17use crate::event::Event;
18use crate::state::{HostRolloutState, HostState};
19
20use super::illegal;
21
22pub(super) fn handle(
23 mut state: HostRolloutState,
24 event: Event,
25 _now: DateTime<Utc>,
26 _policy: &RolloutPolicy,
27) -> Result<(HostRolloutState, Vec<Effect>), TransitionError> {
28 match event {
29 Event::LocalRollbackCompleted {
30 reverted_to_closure,
31 exit_code,
32 completed_at,
33 seq,
34 } => {
35 let from = state.state;
36 state.state = HostState::Reverted;
37 state.reverted_at = Some(completed_at);
38 state.reverted_to = Some(reverted_to_closure.clone());
39 state.current_closure = Some(reverted_to_closure.clone());
40 state.last_event_seq = seq;
41
42 let effects = vec![
43 Effect::LocalEmitEvent {
44 rollout_id: state.rollout_id.clone(),
45 payload: OutboundAgentEvent::RollbackComplete {
46 reverted_to_closure,
47 exit_code,
48 completed_at,
49 seq,
50 },
51 durable: true,
52 },
53 Effect::RecordTransition {
54 host: state.hostname.clone(),
55 rollout_id: state.rollout_id.clone(),
56 from,
57 to: HostState::Reverted,
58 at: completed_at,
59 },
60 ];
61 Ok((state, effects))
62 }
63 Event::RemoteRollbackComplete {
64 reverted_to_closure,
65 exit_code,
66 completed_at,
67 seq,
68 } => {
69 let from = state.state;
70 let bad_closure = state.target_closure.clone();
71 let channel = state.channel.clone();
72 state.state = HostState::Reverted;
73 state.reverted_at = Some(completed_at);
74 state.reverted_to = Some(reverted_to_closure.clone());
75 state.current_closure = Some(reverted_to_closure.clone());
76 state.last_event_seq = seq;
77
78 let effects = vec![
79 Effect::RemoteAppendEventLog {
80 host: state.hostname.clone(),
81 rollout_id: state.rollout_id.clone(),
82 payload: OutboundAgentEvent::RollbackComplete {
83 reverted_to_closure,
84 exit_code,
85 completed_at,
86 seq,
87 },
88 },
89 Effect::RemoteInsertQuarantine {
90 channel,
91 closure: bad_closure,
92 },
93 Effect::RecordTransition {
94 host: state.hostname.clone(),
95 rollout_id: state.rollout_id.clone(),
96 from,
97 to: HostState::Reverted,
98 at: completed_at,
99 },
100 ];
101 Ok((state, effects))
102 }
103
104 other => Err(illegal(&state, &other)),
105 }
106}