use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use zart_scheduler::{ExecutionRecord, ExecutionSortField, ListExecutionsParams, SortOrder};
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StartExecutionRequest {
#[serde(default)]
pub execution_id: Option<String>,
pub task_name: String,
#[serde(default)]
pub payload: serde_json::Value,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ListQuery {
pub status: Option<String>,
pub task_name: Option<String>,
pub from: Option<DateTime<Utc>>,
pub to: Option<DateTime<Utc>>,
pub search: Option<String>,
pub sort_by: Option<String>,
pub sort_order: Option<String>,
#[serde(default = "default_limit")]
pub limit: usize,
#[serde(default)]
pub offset: usize,
}
impl ListQuery {
pub fn into_params(self) -> ListExecutionsParams {
let status = self
.status
.as_deref()
.and_then(|s| s.parse::<zart_scheduler::ExecutionStatus>().ok());
let sort_by = match self.sort_by.as_deref() {
Some("status") => ExecutionSortField::Status,
Some("taskName") => ExecutionSortField::TaskName,
_ => ExecutionSortField::ScheduledAt,
};
let sort_order = match self.sort_order.as_deref() {
Some("asc") => SortOrder::Asc,
_ => SortOrder::Desc,
};
ListExecutionsParams {
status,
task_name: self.task_name,
from: self.from,
to: self.to,
search: self.search,
sort_by,
sort_order,
limit: self.limit,
offset: self.offset,
}
}
}
fn default_limit() -> usize {
20
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WaitQuery {
pub timeout_secs: Option<u64>,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ExecutionResponse {
pub name: String,
pub durable_execution_id: String,
pub payload: serde_json::Value,
pub status: String,
pub scheduled_at: DateTime<Utc>,
pub completed_at: Option<DateTime<Utc>>,
pub version: i32,
pub result: Option<serde_json::Value>,
}
impl From<ExecutionRecord> for ExecutionResponse {
fn from(r: ExecutionRecord) -> Self {
Self {
name: r.task_name,
durable_execution_id: r.execution_id,
payload: r.payload,
status: r.status.to_string(),
scheduled_at: r.scheduled_at,
completed_at: r.completed_at,
version: r.version,
result: r.result,
}
}
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct StartExecutionResponse {
pub execution_id: String,
pub task_id: String,
}
#[derive(Debug, Serialize)]
pub struct ErrorResponse {
pub error: String,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RetryStepRequest {
pub step_name: String,
#[serde(default)]
pub triggered_by: Option<String>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RestartRequest {
#[serde(default)]
pub payload: Option<serde_json::Value>,
#[serde(default)]
pub triggered_by: Option<String>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RerunRequest {
#[serde(default)]
pub rerun_steps: Vec<String>,
#[serde(default)]
pub preserve_steps: Vec<String>,
#[serde(default)]
pub triggered_by: Option<String>,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RetryStepResponse {
pub new_task_id: String,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RestartResponse {
pub new_run_id: String,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RerunResponse {
pub new_run_number: u32,
pub effective_rerun: Vec<String>,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RunRecordResponse {
pub run_id: String,
pub execution_id: String,
pub run_index: i32,
pub payload: serde_json::Value,
pub status: String,
pub result: Option<serde_json::Value>,
pub started_at: DateTime<Utc>,
pub completed_at: Option<DateTime<Utc>>,
pub trigger: String,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PauseRequest {
#[serde(default)]
pub execution_id: Option<String>,
#[serde(default)]
pub task_name: Option<String>,
#[serde(default)]
pub step_pattern: Option<String>,
#[serde(default)]
pub expires_at: Option<DateTime<Utc>>,
#[serde(default)]
pub triggered_by: Option<String>,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PauseRuleResponse {
pub rule_id: String,
#[serde(default)]
pub execution_id: Option<String>,
#[serde(default)]
pub task_name: Option<String>,
#[serde(default)]
pub step_pattern: Option<String>,
pub created_at: DateTime<Utc>,
#[serde(default)]
pub expires_at: Option<DateTime<Utc>>,
#[serde(default)]
pub created_by: Option<String>,
#[serde(default)]
pub deleted_at: Option<DateTime<Utc>>,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ResumeResponse {
pub rules_deleted: usize,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct StatsResponse {
pub scheduled: i64,
pub running: i64,
pub completed: i64,
pub failed: i64,
pub cancelled: i64,
}
impl From<zart_scheduler::ExecutionStats> for StatsResponse {
fn from(s: zart_scheduler::ExecutionStats) -> Self {
Self {
scheduled: s.scheduled,
running: s.running,
completed: s.completed,
failed: s.failed,
cancelled: s.cancelled,
}
}
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ExecutionDetailResponse {
pub execution: ExecutionResponse,
pub runs: Vec<RunRecordResponse>,
pub steps: Vec<StepDetailResponse>,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct StepDetailResponse {
pub step_id: String,
pub name: String,
pub kind: String,
pub status: String,
pub retry_attempt: i32,
pub result: Option<serde_json::Value>,
pub last_error: Option<String>,
pub retryable: bool,
pub scheduled_at: DateTime<Utc>,
pub completed_at: Option<DateTime<Utc>>,
pub attempts: Vec<StepAttemptResponse>,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct StepAttemptResponse {
pub attempt_number: i32,
pub status: String,
pub result: Option<serde_json::Value>,
pub error: Option<String>,
pub started_at: DateTime<Utc>,
pub completed_at: Option<DateTime<Utc>>,
}