1use crate::plan::DEFAULT_TIMEOUT;
2use crate::{
3 AutomataError, Desktop, Executor, Plan, RecoveryHandler, RetryPolicy, Step, WorkflowState,
4};
5use std::time::Duration;
6
7pub struct WorkflowPhase {
9 pub name: String,
10 pub steps: Vec<Step>,
11 pub recovery_handlers: Vec<RecoveryHandler>,
12 pub unmount: Vec<String>,
13 pub default_timeout: Duration,
14 pub default_retry: RetryPolicy,
15}
16
17impl WorkflowPhase {
18 pub fn new(name: impl Into<String>, steps: Vec<Step>) -> Self {
19 Self {
20 name: name.into(),
21 steps,
22 recovery_handlers: vec![],
23 unmount: vec![],
24 default_timeout: DEFAULT_TIMEOUT,
25 default_retry: RetryPolicy::None,
26 }
27 }
28}
29
30pub struct Workflow<D: Desktop> {
32 phases: Vec<WorkflowPhase>,
33 _marker: std::marker::PhantomData<D>,
34}
35
36impl<D: Desktop> Workflow<D> {
37 pub fn new() -> Self {
38 Self {
39 phases: vec![],
40 _marker: std::marker::PhantomData,
41 }
42 }
43
44 pub fn phase(mut self, phase: WorkflowPhase) -> Self {
46 self.phases.push(phase);
47 self
48 }
49
50 pub fn run(&self, executor: &mut Executor<D>) -> Result<(), AutomataError> {
52 let mut state = WorkflowState::new(true);
53 for phase in &self.phases {
54 eprintln!("[workflow] phase: {}", phase.name);
55 let plan = Plan {
56 name: &phase.name,
57 steps: &phase.steps,
58 recovery_handlers: phase.recovery_handlers.clone(),
59 max_recoveries: 10,
60 unmount: &phase.unmount,
61 default_timeout: phase.default_timeout,
62 default_retry: phase.default_retry.clone(),
63 };
64 executor.run(&plan, &mut state)?;
65 }
66 Ok(())
67 }
68}
69
70impl<D: Desktop> Default for Workflow<D> {
71 fn default() -> Self {
72 Self::new()
73 }
74}