1use crate::atoms::Atom;
2use crate::steps::finalizers::FlowControl;
3use tracing::error;
4
5pub mod finalizers;
6pub mod initializers;
7
8pub struct Step {
9 pub atom: Box<dyn Atom>,
10 pub initializers: Vec<initializers::FlowControl>,
11 pub finalizers: Vec<finalizers::FlowControl>,
12}
13
14impl Step {
15 pub fn do_initializers_allow_us_to_run(&self) -> bool {
16 self.initializers
17 .iter()
18 .fold(true, |_, flow_control| match flow_control {
19 initializers::FlowControl::Ensure(i) => {
20 i.initialize().unwrap_or_else(|err| {
21 error!("Failed to run initializer: {}", err.to_string());
22
23 false
26 })
27 }
28
29 initializers::FlowControl::SkipIf(i) => {
30 match i.initialize() {
31 Ok(true) => {
32 false
35 }
36 Ok(false) => true,
37 Err(err) => {
38 error!("Failed to run initializer: {}", err.to_string());
39
40 false
43 }
44 }
45 }
46 })
47 }
48
49 pub fn do_finalizers_allow_us_to_continue(&self) -> bool {
50 self.finalizers
51 .iter()
52 .fold(true, |_, flow_control| match flow_control {
53 finalizers::FlowControl::StopIf(i) => {
54 match i.finalize(self.atom.as_ref()) {
55 Ok(true) => {
56 false
59 }
60 Ok(false) => true,
61 Err(err) => {
62 error!("Failed to run finalizers: {}", err.to_string());
63
64 false
67 }
68 }
69 }
70 FlowControl::Ensure(i) => {
71 match i.finalize(self.atom.as_ref()) {
72 Ok(true) => true,
73 Ok(false) => false,
74 Err(err) => {
75 error!("Failed to run finalizers: {}", err.to_string());
76
77 false
80 }
81 }
82 }
83 })
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::finalizers::test::EchoFinalizer;
90 use super::finalizers::test::ErrorFinalizer;
91 use super::finalizers::FlowControl as FinalizerFlowControl;
92 use super::initializers::test::Echo as EchoInitializer;
93 use super::initializers::test::Error as ErrorInitializer;
94 use super::initializers::FlowControl as InitializerFlowControl;
95 use crate::atoms::Echo as EchoAtom;
96 use pretty_assertions::assert_eq;
97
98 use super::*;
99
100 #[test]
101 fn initializers_can_control_execution() {
102 let step = Step {
103 atom: Box::new(EchoAtom("hello-world")),
104 initializers: vec![InitializerFlowControl::Ensure(Box::new(EchoInitializer(
105 true,
106 )))],
107 finalizers: vec![],
108 };
109
110 assert_eq!(true, step.do_initializers_allow_us_to_run());
111
112 let step = Step {
113 atom: Box::new(EchoAtom("hello-world")),
114 initializers: vec![InitializerFlowControl::Ensure(Box::new(EchoInitializer(
115 false,
116 )))],
117 finalizers: vec![],
118 };
119
120 assert_eq!(false, step.do_initializers_allow_us_to_run());
121
122 let step = Step {
123 atom: Box::new(EchoAtom("hello-world")),
124 initializers: vec![InitializerFlowControl::SkipIf(Box::new(EchoInitializer(
125 true,
126 )))],
127 finalizers: vec![],
128 };
129
130 assert_eq!(false, step.do_initializers_allow_us_to_run());
131
132 let step = Step {
133 atom: Box::new(EchoAtom("hello-world")),
134 initializers: vec![InitializerFlowControl::SkipIf(Box::new(EchoInitializer(
135 false,
136 )))],
137 finalizers: vec![],
138 };
139
140 assert_eq!(true, step.do_initializers_allow_us_to_run());
141
142 let step = Step {
143 atom: Box::new(EchoAtom("hello-world")),
144 initializers: vec![
145 InitializerFlowControl::SkipIf(Box::new(EchoInitializer(false))),
146 InitializerFlowControl::SkipIf(Box::new(EchoInitializer(true))),
147 ],
148 finalizers: vec![],
149 };
150
151 assert_eq!(false, step.do_initializers_allow_us_to_run());
152 }
153
154 #[test]
155 fn initializers_that_error_block_execution() {
156 let step = Step {
157 atom: Box::new(EchoAtom("hello-world")),
158 initializers: vec![InitializerFlowControl::SkipIf(Box::new(ErrorInitializer()))],
159 finalizers: vec![],
160 };
161
162 assert_eq!(false, step.do_initializers_allow_us_to_run());
163
164 let step = Step {
165 atom: Box::new(EchoAtom("hello-world")),
166 initializers: vec![
167 InitializerFlowControl::SkipIf(Box::new(EchoInitializer(false))),
168 InitializerFlowControl::SkipIf(Box::new(ErrorInitializer())),
169 ],
170 finalizers: vec![],
171 };
172
173 assert_eq!(false, step.do_initializers_allow_us_to_run());
174 }
175
176 #[test]
177 fn finalizers_can_control_execution() {
178 let step = Step {
179 atom: Box::new(EchoAtom("hello-world")),
180 initializers: vec![],
181 finalizers: vec![FinalizerFlowControl::StopIf(Box::new(EchoFinalizer(false)))],
182 };
183
184 assert_eq!(true, step.do_finalizers_allow_us_to_continue());
185
186 let step = Step {
187 atom: Box::new(EchoAtom("hello-world")),
188 initializers: vec![],
189 finalizers: vec![FinalizerFlowControl::StopIf(Box::new(EchoFinalizer(true)))],
190 };
191
192 assert_eq!(false, step.do_finalizers_allow_us_to_continue());
193
194 let step = Step {
195 atom: Box::new(EchoAtom("hello-world")),
196 initializers: vec![],
197 finalizers: vec![
198 FinalizerFlowControl::StopIf(Box::new(EchoFinalizer(false))),
199 FinalizerFlowControl::StopIf(Box::new(EchoFinalizer(true))),
200 ],
201 };
202
203 assert_eq!(false, step.do_finalizers_allow_us_to_continue());
204 }
205
206 #[test]
207 fn finalizers_that_error_block_execution() {
208 let step = Step {
209 atom: Box::new(EchoAtom("hello-world")),
210 initializers: vec![],
211 finalizers: vec![FinalizerFlowControl::StopIf(Box::new(ErrorFinalizer()))],
212 };
213
214 assert_eq!(false, step.do_finalizers_allow_us_to_continue());
215
216 let step = Step {
217 atom: Box::new(EchoAtom("hello-world")),
218 initializers: vec![],
219 finalizers: vec![
220 FinalizerFlowControl::StopIf(Box::new(EchoFinalizer(false))),
221 FinalizerFlowControl::StopIf(Box::new(ErrorFinalizer())),
222 ],
223 };
224
225 assert_eq!(false, step.do_finalizers_allow_us_to_continue());
226 }
227}