Skip to main content

dapr_durabletask/api/
orchestration_status.rs

1use std::fmt;
2
3/// The runtime status of an orchestration instance.
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
5pub enum OrchestrationStatus {
6    Running,
7    Completed,
8    ContinuedAsNew,
9    Failed,
10    Canceled,
11    Terminated,
12    Pending,
13    Suspended,
14    Stalled,
15}
16
17impl OrchestrationStatus {
18    /// Returns `true` if the orchestration has reached a terminal state
19    /// (completed, failed, cancelled, or terminated).
20    pub fn is_terminal(&self) -> bool {
21        matches!(
22            self,
23            Self::Completed | Self::Failed | Self::Canceled | Self::Terminated
24        )
25    }
26
27    /// Returns `true` if the orchestration is actively running.
28    pub fn is_running(&self) -> bool {
29        matches!(self, Self::Running)
30    }
31}
32
33impl TryFrom<i32> for OrchestrationStatus {
34    type Error = i32;
35
36    fn try_from(value: i32) -> std::result::Result<Self, Self::Error> {
37        match value {
38            0 => Ok(Self::Running),
39            1 => Ok(Self::Completed),
40            2 => Ok(Self::ContinuedAsNew),
41            3 => Ok(Self::Failed),
42            4 => Ok(Self::Canceled),
43            5 => Ok(Self::Terminated),
44            6 => Ok(Self::Pending),
45            7 => Ok(Self::Suspended),
46            8 => Ok(Self::Stalled),
47            _ => Err(value),
48        }
49    }
50}
51
52impl From<OrchestrationStatus> for i32 {
53    fn from(status: OrchestrationStatus) -> Self {
54        match status {
55            OrchestrationStatus::Running => 0,
56            OrchestrationStatus::Completed => 1,
57            OrchestrationStatus::ContinuedAsNew => 2,
58            OrchestrationStatus::Failed => 3,
59            OrchestrationStatus::Canceled => 4,
60            OrchestrationStatus::Terminated => 5,
61            OrchestrationStatus::Pending => 6,
62            OrchestrationStatus::Suspended => 7,
63            OrchestrationStatus::Stalled => 8,
64        }
65    }
66}
67
68impl fmt::Display for OrchestrationStatus {
69    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70        fmt::Debug::fmt(self, f)
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77
78    #[test]
79    fn test_roundtrip_conversion() {
80        for value in 0..=8 {
81            let status = OrchestrationStatus::try_from(value).unwrap();
82            let back: i32 = status.into();
83            assert_eq!(value, back);
84        }
85    }
86
87    #[test]
88    fn test_unknown_value_returns_error() {
89        assert!(OrchestrationStatus::try_from(99).is_err());
90    }
91
92    #[test]
93    fn test_is_terminal() {
94        assert!(OrchestrationStatus::Completed.is_terminal());
95        assert!(OrchestrationStatus::Failed.is_terminal());
96        assert!(OrchestrationStatus::Canceled.is_terminal());
97        assert!(OrchestrationStatus::Terminated.is_terminal());
98        assert!(!OrchestrationStatus::Running.is_terminal());
99        assert!(!OrchestrationStatus::Pending.is_terminal());
100    }
101
102    #[test]
103    fn test_is_running() {
104        assert!(OrchestrationStatus::Running.is_running());
105        assert!(!OrchestrationStatus::Completed.is_running());
106    }
107
108    #[test]
109    fn test_display() {
110        assert_eq!(
111            OrchestrationStatus::ContinuedAsNew.to_string(),
112            "ContinuedAsNew"
113        );
114    }
115}