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 search_attributes: Option<String>,
194 pub archived_at: Option<f64>,
199 pub archive_uri: Option<String>,
200 pub created_at: f64,
201 pub updated_at: f64,
202 pub completed_at: Option<f64>,
203}
204
205#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
206pub struct WorkflowEvent {
207 pub id: Option<i64>,
208 pub workflow_id: String,
209 pub seq: i32,
210 pub event_type: String,
211 pub payload: Option<String>,
212 pub timestamp: f64,
213}
214
215#[derive(Clone, Debug, Default, Serialize, Deserialize, ToSchema)]
219pub struct ScheduleActivityOpts {
220 pub max_attempts: Option<i32>,
221 pub initial_interval_secs: Option<f64>,
222 pub backoff_coefficient: Option<f64>,
223 pub start_to_close_secs: Option<f64>,
224 pub heartbeat_timeout_secs: Option<f64>,
225}
226
227#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
228pub struct WorkflowActivity {
229 pub id: Option<i64>,
230 pub workflow_id: String,
231 pub seq: i32,
232 pub name: String,
233 pub task_queue: String,
234 pub input: Option<String>,
235 pub status: String,
236 pub result: Option<String>,
237 pub error: Option<String>,
238 pub attempt: i32,
239 pub max_attempts: i32,
240 pub initial_interval_secs: f64,
241 pub backoff_coefficient: f64,
242 pub start_to_close_secs: f64,
243 pub heartbeat_timeout_secs: Option<f64>,
244 pub claimed_by: Option<String>,
245 pub scheduled_at: f64,
246 pub started_at: Option<f64>,
247 pub completed_at: Option<f64>,
248 pub last_heartbeat: Option<f64>,
249}
250
251#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
252pub struct WorkflowTimer {
253 pub id: Option<i64>,
254 pub workflow_id: String,
255 pub seq: i32,
256 pub fire_at: f64,
257 pub fired: bool,
258}
259
260#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
261pub struct WorkflowSignal {
262 pub id: Option<i64>,
263 pub workflow_id: String,
264 pub name: String,
265 pub payload: Option<String>,
266 pub consumed: bool,
267 pub received_at: f64,
268}
269
270#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
271pub struct WorkflowSchedule {
272 pub name: String,
273 pub namespace: String,
274 pub workflow_type: String,
275 pub cron_expr: String,
276 pub timezone: String,
280 pub input: Option<String>,
281 pub task_queue: String,
282 pub overlap_policy: String,
283 pub paused: bool,
284 pub last_run_at: Option<f64>,
285 pub next_run_at: Option<f64>,
286 pub last_workflow_id: Option<String>,
287 pub created_at: f64,
288}
289
290#[derive(Clone, Debug, Default, Serialize, Deserialize, ToSchema)]
294pub struct SchedulePatch {
295 pub cron_expr: Option<String>,
296 pub timezone: Option<String>,
297 pub input: Option<serde_json::Value>,
298 pub task_queue: Option<String>,
299 pub overlap_policy: Option<String>,
300}
301
302#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
303pub struct WorkflowWorker {
304 pub id: String,
305 pub namespace: String,
306 pub identity: String,
307 pub task_queue: String,
308 pub workflows: Option<String>,
309 pub activities: Option<String>,
310 pub max_concurrent_workflows: i32,
311 pub max_concurrent_activities: i32,
312 pub active_tasks: i32,
313 pub last_heartbeat: f64,
314 pub registered_at: f64,
315}
316
317#[derive(Clone, Debug, Serialize, Deserialize)]
318pub struct WorkflowSnapshot {
319 pub workflow_id: String,
320 pub event_seq: i32,
321 pub state_json: String,
322 pub created_at: f64,
323}