1use serde::{Deserialize, Serialize};
2use std::fmt;
3use std::str::FromStr;
4use utoipa::ToSchema;
5
6#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
9#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
10pub enum WorkflowStatus {
11 Pending,
12 Running,
13 Waiting,
14 Completed,
15 Failed,
16 Cancelled,
17 TimedOut,
18}
19
20impl fmt::Display for WorkflowStatus {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 match self {
23 Self::Pending => write!(f, "PENDING"),
24 Self::Running => write!(f, "RUNNING"),
25 Self::Waiting => write!(f, "WAITING"),
26 Self::Completed => write!(f, "COMPLETED"),
27 Self::Failed => write!(f, "FAILED"),
28 Self::Cancelled => write!(f, "CANCELLED"),
29 Self::TimedOut => write!(f, "TIMED_OUT"),
30 }
31 }
32}
33
34impl FromStr for WorkflowStatus {
35 type Err = String;
36
37 fn from_str(s: &str) -> Result<Self, Self::Err> {
38 match s {
39 "PENDING" => Ok(Self::Pending),
40 "RUNNING" => Ok(Self::Running),
41 "WAITING" => Ok(Self::Waiting),
42 "COMPLETED" => Ok(Self::Completed),
43 "FAILED" => Ok(Self::Failed),
44 "CANCELLED" => Ok(Self::Cancelled),
45 "TIMED_OUT" => Ok(Self::TimedOut),
46 _ => Err(format!("unknown workflow status: {s}")),
47 }
48 }
49}
50
51impl WorkflowStatus {
52 pub fn is_terminal(self) -> bool {
53 matches!(
54 self,
55 Self::Completed | Self::Failed | Self::Cancelled | Self::TimedOut
56 )
57 }
58}
59
60#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
63#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
64pub enum ActivityStatus {
65 Pending,
66 Running,
67 Completed,
68 Failed,
69 Cancelled,
70}
71
72impl fmt::Display for ActivityStatus {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 match self {
75 Self::Pending => write!(f, "PENDING"),
76 Self::Running => write!(f, "RUNNING"),
77 Self::Completed => write!(f, "COMPLETED"),
78 Self::Failed => write!(f, "FAILED"),
79 Self::Cancelled => write!(f, "CANCELLED"),
80 }
81 }
82}
83
84impl FromStr for ActivityStatus {
85 type Err = String;
86
87 fn from_str(s: &str) -> Result<Self, Self::Err> {
88 match s {
89 "PENDING" => Ok(Self::Pending),
90 "RUNNING" => Ok(Self::Running),
91 "COMPLETED" => Ok(Self::Completed),
92 "FAILED" => Ok(Self::Failed),
93 "CANCELLED" => Ok(Self::Cancelled),
94 _ => Err(format!("unknown activity status: {s}")),
95 }
96 }
97}
98
99#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
102pub enum EventType {
103 WorkflowStarted,
104 ActivityScheduled,
105 ActivityCompleted,
106 ActivityFailed,
107 TimerStarted,
108 TimerFired,
109 SignalReceived,
110 WorkflowCompleted,
111 WorkflowFailed,
112 WorkflowCancelled,
113 ChildWorkflowStarted,
114 ChildWorkflowCompleted,
115 SideEffectRecorded,
116}
117
118impl fmt::Display for EventType {
119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120 let s = serde_json::to_value(self)
121 .ok()
122 .and_then(|v| v.as_str().map(String::from))
123 .unwrap_or_else(|| format!("{self:?}"));
124 write!(f, "{s}")
125 }
126}
127
128impl FromStr for EventType {
129 type Err = String;
130
131 fn from_str(s: &str) -> Result<Self, Self::Err> {
132 serde_json::from_value(serde_json::Value::String(s.to_string()))
133 .map_err(|_| format!("unknown event type: {s}"))
134 }
135}
136
137#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
140#[serde(rename_all = "snake_case")]
141pub enum OverlapPolicy {
142 Skip,
143 Queue,
144 CancelOld,
145 AllowAll,
146}
147
148impl fmt::Display for OverlapPolicy {
149 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150 match self {
151 Self::Skip => write!(f, "skip"),
152 Self::Queue => write!(f, "queue"),
153 Self::CancelOld => write!(f, "cancel_old"),
154 Self::AllowAll => write!(f, "allow_all"),
155 }
156 }
157}
158
159impl FromStr for OverlapPolicy {
160 type Err = String;
161
162 fn from_str(s: &str) -> Result<Self, Self::Err> {
163 match s {
164 "skip" => Ok(Self::Skip),
165 "queue" => Ok(Self::Queue),
166 "cancel_old" => Ok(Self::CancelOld),
167 "allow_all" => Ok(Self::AllowAll),
168 _ => Err(format!("unknown overlap policy: {s}")),
169 }
170 }
171}
172
173#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
176pub struct WorkflowRecord {
177 pub id: String,
178 pub namespace: String,
179 pub run_id: String,
180 pub workflow_type: String,
181 pub task_queue: String,
182 pub status: String,
183 pub input: Option<String>,
184 pub result: Option<String>,
185 pub error: Option<String>,
186 pub parent_id: Option<String>,
187 pub claimed_by: Option<String>,
188 pub created_at: f64,
189 pub updated_at: f64,
190 pub completed_at: Option<f64>,
191}
192
193#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
194pub struct WorkflowEvent {
195 pub id: Option<i64>,
196 pub workflow_id: String,
197 pub seq: i32,
198 pub event_type: String,
199 pub payload: Option<String>,
200 pub timestamp: f64,
201}
202
203#[derive(Clone, Debug, Default, Serialize, Deserialize, ToSchema)]
207pub struct ScheduleActivityOpts {
208 pub max_attempts: Option<i32>,
209 pub initial_interval_secs: Option<f64>,
210 pub backoff_coefficient: Option<f64>,
211 pub start_to_close_secs: Option<f64>,
212 pub heartbeat_timeout_secs: Option<f64>,
213}
214
215#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
216pub struct WorkflowActivity {
217 pub id: Option<i64>,
218 pub workflow_id: String,
219 pub seq: i32,
220 pub name: String,
221 pub task_queue: String,
222 pub input: Option<String>,
223 pub status: String,
224 pub result: Option<String>,
225 pub error: Option<String>,
226 pub attempt: i32,
227 pub max_attempts: i32,
228 pub initial_interval_secs: f64,
229 pub backoff_coefficient: f64,
230 pub start_to_close_secs: f64,
231 pub heartbeat_timeout_secs: Option<f64>,
232 pub claimed_by: Option<String>,
233 pub scheduled_at: f64,
234 pub started_at: Option<f64>,
235 pub completed_at: Option<f64>,
236 pub last_heartbeat: Option<f64>,
237}
238
239#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
240pub struct WorkflowTimer {
241 pub id: Option<i64>,
242 pub workflow_id: String,
243 pub seq: i32,
244 pub fire_at: f64,
245 pub fired: bool,
246}
247
248#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
249pub struct WorkflowSignal {
250 pub id: Option<i64>,
251 pub workflow_id: String,
252 pub name: String,
253 pub payload: Option<String>,
254 pub consumed: bool,
255 pub received_at: f64,
256}
257
258#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
259pub struct WorkflowSchedule {
260 pub name: String,
261 pub namespace: String,
262 pub workflow_type: String,
263 pub cron_expr: String,
264 pub input: Option<String>,
265 pub task_queue: String,
266 pub overlap_policy: String,
267 pub paused: bool,
268 pub last_run_at: Option<f64>,
269 pub next_run_at: Option<f64>,
270 pub last_workflow_id: Option<String>,
271 pub created_at: f64,
272}
273
274#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
275pub struct WorkflowWorker {
276 pub id: String,
277 pub namespace: String,
278 pub identity: String,
279 pub task_queue: String,
280 pub workflows: Option<String>,
281 pub activities: Option<String>,
282 pub max_concurrent_workflows: i32,
283 pub max_concurrent_activities: i32,
284 pub active_tasks: i32,
285 pub last_heartbeat: f64,
286 pub registered_at: f64,
287}
288
289#[derive(Clone, Debug, Serialize, Deserialize)]
290pub struct WorkflowSnapshot {
291 pub workflow_id: String,
292 pub event_seq: i32,
293 pub state_json: String,
294 pub created_at: f64,
295}