Skip to main content

ironflow_store/entities/
step_status.rs

1//! [`StepStatus`] — lifecycle states for a workflow step.
2
3use serde::{Deserialize, Serialize};
4use strum::EnumIter;
5
6/// Status of an individual step within a run.
7///
8/// # Examples
9///
10/// ```
11/// use ironflow_store::entities::StepStatus;
12///
13/// assert!(!StepStatus::Pending.is_terminal());
14/// assert!(StepStatus::Completed.is_terminal());
15/// ```
16#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, EnumIter)]
18#[serde(rename_all = "snake_case")]
19pub enum StepStatus {
20    /// Waiting to execute.
21    Pending,
22    /// Currently executing.
23    Running,
24    /// Executed successfully.
25    Completed,
26    /// Execution failed.
27    Failed,
28    /// Skipped (e.g. when a prior step failed).
29    Skipped,
30    /// Waiting for human approval before continuing.
31    AwaitingApproval,
32    /// Human rejected the approval request.
33    Rejected,
34}
35
36impl StepStatus {
37    /// Returns `true` if this is a terminal state.
38    pub fn is_terminal(&self) -> bool {
39        matches!(
40            self,
41            StepStatus::Completed | StepStatus::Failed | StepStatus::Skipped | StepStatus::Rejected
42        )
43    }
44}
45
46impl std::fmt::Display for StepStatus {
47    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48        match self {
49            StepStatus::Pending => f.write_str("Pending"),
50            StepStatus::Running => f.write_str("Running"),
51            StepStatus::Completed => f.write_str("Completed"),
52            StepStatus::Failed => f.write_str("Failed"),
53            StepStatus::Skipped => f.write_str("Skipped"),
54            StepStatus::AwaitingApproval => f.write_str("AwaitingApproval"),
55            StepStatus::Rejected => f.write_str("Rejected"),
56        }
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    #[test]
65    fn terminal() {
66        assert!(StepStatus::Completed.is_terminal());
67        assert!(StepStatus::Failed.is_terminal());
68        assert!(StepStatus::Skipped.is_terminal());
69        assert!(!StepStatus::Pending.is_terminal());
70        assert!(!StepStatus::Running.is_terminal());
71        assert!(!StepStatus::AwaitingApproval.is_terminal());
72        assert!(StepStatus::Rejected.is_terminal());
73    }
74
75    #[test]
76    fn display() {
77        assert_eq!(StepStatus::Pending.to_string(), "Pending");
78        assert_eq!(StepStatus::Running.to_string(), "Running");
79        assert_eq!(StepStatus::Completed.to_string(), "Completed");
80        assert_eq!(StepStatus::Failed.to_string(), "Failed");
81        assert_eq!(StepStatus::Skipped.to_string(), "Skipped");
82        assert_eq!(StepStatus::AwaitingApproval.to_string(), "AwaitingApproval");
83        assert_eq!(StepStatus::Rejected.to_string(), "Rejected");
84    }
85}