Skip to main content

ironflow_store/entities/
step_status.rs

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