1use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5use zart::{ExecutionRecord, ExecutionSortField, ListExecutionsParams, SortOrder};
6
7#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
11#[derive(Debug, Deserialize)]
12#[serde(rename_all = "camelCase")]
13pub struct StartExecutionRequest {
14 #[serde(default)]
16 pub execution_id: Option<String>,
17 pub task_name: String,
19 #[serde(default)]
21 pub payload: serde_json::Value,
22}
23
24#[cfg_attr(feature = "openapi", derive(utoipa::IntoParams, utoipa::ToSchema))]
26#[derive(Debug, Deserialize)]
27#[serde(rename_all = "camelCase")]
28pub struct ListQuery {
29 pub status: Option<String>,
30 pub task_name: Option<String>,
31 pub from: Option<DateTime<Utc>>,
32 pub to: Option<DateTime<Utc>>,
33 pub search: Option<String>,
34 pub sort_by: Option<String>,
35 pub sort_order: Option<String>,
36 #[serde(default = "default_limit")]
37 pub limit: usize,
38 #[serde(default)]
39 pub offset: usize,
40}
41
42impl ListQuery {
43 pub fn into_params(self) -> ListExecutionsParams {
44 let status = self
45 .status
46 .as_deref()
47 .and_then(|s| s.parse::<zart::ExecutionStatus>().ok());
48 let sort_by = match self.sort_by.as_deref() {
49 Some("status") => ExecutionSortField::Status,
50 Some("taskName") => ExecutionSortField::TaskName,
51 _ => ExecutionSortField::ScheduledAt,
52 };
53 let sort_order = match self.sort_order.as_deref() {
54 Some("asc") => SortOrder::Asc,
55 _ => SortOrder::Desc,
56 };
57 ListExecutionsParams {
58 status,
59 task_name: self.task_name,
60 from: self.from,
61 to: self.to,
62 search: self.search,
63 sort_by,
64 sort_order,
65 limit: self.limit,
66 offset: self.offset,
67 }
68 }
69}
70
71fn default_limit() -> usize {
72 20
73}
74
75#[cfg_attr(feature = "openapi", derive(utoipa::IntoParams, utoipa::ToSchema))]
77#[derive(Debug, Deserialize)]
78#[serde(rename_all = "camelCase")]
79pub struct WaitQuery {
80 pub timeout_secs: Option<u64>,
82}
83
84#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
88#[derive(Debug, Serialize)]
89#[serde(rename_all = "camelCase")]
90pub struct ExecutionResponse {
91 pub name: String,
93 pub durable_execution_id: String,
95 pub payload: serde_json::Value,
97 pub status: String,
99 pub scheduled_at: DateTime<Utc>,
101 pub completed_at: Option<DateTime<Utc>>,
103 pub version: i32,
105 pub result: Option<serde_json::Value>,
107}
108
109impl From<ExecutionRecord> for ExecutionResponse {
110 fn from(r: ExecutionRecord) -> Self {
111 Self {
112 name: r.task_name,
113 durable_execution_id: r.execution_id,
114 payload: r.payload,
115 status: r.status.to_string(),
116 scheduled_at: r.scheduled_at,
117 completed_at: r.completed_at,
118 version: r.version,
119 result: r.result,
120 }
121 }
122}
123
124#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
126#[derive(Debug, Serialize)]
127#[serde(rename_all = "camelCase")]
128pub struct StartExecutionResponse {
129 pub execution_id: String,
130 pub task_id: String,
131}
132
133#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
135#[derive(Debug, Serialize)]
136pub struct ErrorResponse {
137 pub error: String,
138}
139
140#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
144#[derive(Debug, Deserialize)]
145#[serde(rename_all = "camelCase")]
146pub struct RetryStepRequest {
147 pub step_name: String,
148 #[serde(default)]
149 pub triggered_by: Option<String>,
150}
151
152#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
154#[derive(Debug, Deserialize)]
155#[serde(rename_all = "camelCase")]
156pub struct RestartRequest {
157 #[serde(default)]
158 pub payload: Option<serde_json::Value>,
159 #[serde(default)]
160 pub triggered_by: Option<String>,
161}
162
163#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
165#[derive(Debug, Deserialize)]
166#[serde(rename_all = "camelCase")]
167pub struct RerunRequest {
168 #[serde(default)]
169 pub rerun_steps: Vec<String>,
170 #[serde(default)]
171 pub preserve_steps: Vec<String>,
172 #[serde(default)]
173 pub triggered_by: Option<String>,
174}
175
176#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
180#[derive(Debug, Serialize)]
181#[serde(rename_all = "camelCase")]
182pub struct RetryStepResponse {
183 pub new_task_id: String,
184}
185
186#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
188#[derive(Debug, Serialize)]
189#[serde(rename_all = "camelCase")]
190pub struct RestartResponse {
191 pub new_run_id: String,
192}
193
194#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
196#[derive(Debug, Serialize)]
197#[serde(rename_all = "camelCase")]
198pub struct RerunResponse {
199 pub new_run_number: u32,
200 pub effective_rerun: Vec<String>,
201 #[serde(skip_serializing_if = "Vec::is_empty")]
202 pub potentially_stale: Vec<PotentiallyStaleDepResponse>,
203}
204
205#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
207#[derive(Debug, Serialize)]
208#[serde(rename_all = "camelCase")]
209pub struct PotentiallyStaleDepResponse {
210 pub preserved_step: String,
211 pub possibly_depends_on: Vec<String>,
212}
213
214#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
216#[derive(Debug, Serialize)]
217#[serde(rename_all = "camelCase")]
218pub struct RunRecordResponse {
219 pub run_id: String,
220 pub execution_id: String,
221 pub run_index: i32,
222 pub payload: serde_json::Value,
223 pub status: String,
224 pub result: Option<serde_json::Value>,
225 pub started_at: DateTime<Utc>,
226 pub completed_at: Option<DateTime<Utc>>,
227 pub trigger: String,
228}
229
230#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
234#[derive(Debug, Deserialize)]
235#[serde(rename_all = "camelCase")]
236pub struct PauseRequest {
237 #[serde(default)]
238 pub execution_id: Option<String>,
239 #[serde(default)]
240 pub task_name: Option<String>,
241 #[serde(default)]
242 pub step_pattern: Option<String>,
243 #[serde(default)]
244 pub expires_at: Option<DateTime<Utc>>,
245 #[serde(default)]
246 pub triggered_by: Option<String>,
247 #[serde(default)]
248 pub reason: Option<String>,
249}
250
251#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
253#[derive(Debug, Serialize)]
254#[serde(rename_all = "camelCase")]
255pub struct PauseRuleResponse {
256 pub rule_id: String,
257 #[serde(default)]
258 pub execution_id: Option<String>,
259 #[serde(default)]
260 pub task_name: Option<String>,
261 #[serde(default)]
262 pub step_pattern: Option<String>,
263 pub created_at: DateTime<Utc>,
264 #[serde(default)]
265 pub expires_at: Option<DateTime<Utc>>,
266 #[serde(default)]
267 pub created_by: Option<String>,
268 #[serde(default)]
269 pub deleted_at: Option<DateTime<Utc>>,
270 #[serde(default)]
271 pub reason: Option<String>,
272}
273
274#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
276#[derive(Debug, Serialize)]
277#[serde(rename_all = "camelCase")]
278pub struct ResumeResponse {
279 pub rules_deleted: usize,
280}
281
282#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
284#[derive(Debug, Serialize)]
285#[serde(rename_all = "camelCase")]
286pub struct StatsResponse {
287 pub scheduled: i64,
288 pub running: i64,
289 pub completed: i64,
290 pub failed: i64,
291 pub cancelled: i64,
292}
293
294impl From<zart::ExecutionStats> for StatsResponse {
295 fn from(s: zart::ExecutionStats) -> Self {
296 Self {
297 scheduled: s.scheduled,
298 running: s.running,
299 completed: s.completed,
300 failed: s.failed,
301 cancelled: s.cancelled,
302 }
303 }
304}
305
306#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
308#[derive(Debug, Serialize)]
309#[serde(rename_all = "camelCase")]
310pub struct ExecutionDetailResponse {
311 pub execution: ExecutionResponse,
312 pub runs: Vec<RunRecordResponse>,
313 pub steps: Vec<StepDetailResponse>,
314}
315
316#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
318#[derive(Debug, Serialize)]
319#[serde(rename_all = "camelCase")]
320pub struct StepDetailResponse {
321 pub step_id: String,
322 pub name: String,
323 pub kind: String,
324 pub status: String,
325 pub retry_attempt: i32,
326 pub result: Option<serde_json::Value>,
327 pub last_error: Option<String>,
328 pub retryable: bool,
329 pub scheduled_at: DateTime<Utc>,
330 pub completed_at: Option<DateTime<Utc>>,
331 pub attempts: Vec<StepAttemptResponse>,
332}
333
334#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
336#[derive(Debug, Serialize)]
337#[serde(rename_all = "camelCase")]
338pub struct StepAttemptResponse {
339 pub attempt_number: i32,
340 pub status: String,
341 pub result: Option<serde_json::Value>,
342 pub error: Option<String>,
343 pub started_at: DateTime<Utc>,
344 pub completed_at: Option<DateTime<Utc>>,
345}