apalis_core/task/
status.rs1use core::fmt;
11use std::{
12 str::FromStr,
13 sync::{
14 Arc,
15 atomic::{AtomicU8, Ordering},
16 },
17};
18
19#[repr(u8)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
22#[non_exhaustive]
23#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Default)]
24pub enum Status {
25 #[default]
27 Pending,
28 Queued,
30 Running,
32 Done,
34 Failed,
36 Killed,
38}
39
40#[derive(Debug, thiserror::Error)]
42#[non_exhaustive]
43pub enum StatusError {
44 #[error("Unknown state: {0}")]
45 UnknownState(String),
47}
48
49impl FromStr for Status {
50 type Err = StatusError;
51
52 fn from_str(s: &str) -> Result<Self, Self::Err> {
53 match s {
54 "Pending" => Ok(Self::Pending),
55 "Queued" => Ok(Self::Queued),
56 "Running" => Ok(Self::Running),
57 "Done" => Ok(Self::Done),
58 "Failed" => Ok(Self::Failed),
59 "Killed" => Ok(Self::Killed),
60 _ => Err(StatusError::UnknownState(s.to_owned())),
61 }
62 }
63}
64
65impl fmt::Display for Status {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 match &self {
68 Self::Pending => write!(f, "Pending"),
69 Self::Queued => write!(f, "Queued"),
70 Self::Running => write!(f, "Running"),
71 Self::Done => write!(f, "Done"),
72 Self::Failed => write!(f, "Failed"),
73 Self::Killed => write!(f, "Killed"),
74 }
75 }
76}
77
78impl Status {
79 fn from_u8(val: u8) -> Option<Self> {
80 match val {
81 0 => Some(Self::Pending),
82 1 => Some(Self::Queued),
83 2 => Some(Self::Running),
84 3 => Some(Self::Done),
85 4 => Some(Self::Failed),
86 5 => Some(Self::Killed),
87 _ => None,
88 }
89 }
90}
91
92#[repr(transparent)]
94#[derive(Debug, Clone, Default)]
95pub struct AtomicStatus(Arc<AtomicU8>);
96
97impl AtomicStatus {
98 #[must_use]
100 pub fn new(status: Status) -> Self {
101 Self(Arc::new(AtomicU8::new(status as u8)))
102 }
103
104 #[must_use]
106 pub fn load(&self) -> Status {
107 Status::from_u8(self.0.load(Ordering::SeqCst)).unwrap()
108 }
109
110 pub fn store(&self, status: Status) {
112 self.0.store(status as u8, Ordering::SeqCst);
113 }
114 #[must_use]
116 pub fn swap(&self, status: Status) -> Status {
117 Status::from_u8(self.0.swap(status as u8, Ordering::AcqRel)).unwrap()
118 }
119}
120
121impl From<AtomicStatus> for Status {
122 fn from(val: AtomicStatus) -> Self {
123 val.load()
124 }
125}
126
127impl From<Status> for AtomicStatus {
128 fn from(val: Status) -> Self {
129 Self::new(val)
130 }
131}
132
133#[cfg(feature = "serde")]
134mod serde_impl {
135 use serde::{Deserialize, Deserializer, Serialize, Serializer};
136
137 use super::*;
138
139 fn serialize<S>(status: &AtomicStatus, serializer: S) -> Result<S::Ok, S::Error>
141 where
142 S: Serializer,
143 {
144 let value = status.load();
145 serializer.serialize_str(&value.to_string())
146 }
147
148 fn deserialize<'de, D>(deserializer: D) -> Result<AtomicStatus, D::Error>
150 where
151 D: Deserializer<'de>,
152 {
153 let value = String::deserialize(deserializer)?;
154 let status = Status::from_str(&value).map_err(serde::de::Error::custom)?;
155 Ok(AtomicStatus::new(status))
156 }
157
158 impl Serialize for AtomicStatus {
159 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
160 where
161 S: Serializer,
162 {
163 serialize(self, serializer)
164 }
165 }
166
167 impl<'de> Deserialize<'de> for AtomicStatus {
168 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
169 where
170 D: Deserializer<'de>,
171 {
172 deserialize(deserializer)
173 }
174 }
175}