Skip to main content

ironflow_api/entities/
schedule.rs

1//! Schedule request and response DTOs.
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6use uuid::Uuid;
7use validator::Validate;
8
9use ironflow_store::entities::{Schedule, ScheduleSource};
10
11/// Schedule list/detail response.
12#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
13#[derive(Debug, Serialize)]
14pub struct ScheduleResponse {
15    /// Schedule ID.
16    pub id: Uuid,
17    /// Name of the workflow to trigger.
18    pub workflow_name: String,
19    /// Cron expression.
20    pub cron_expression: String,
21    /// JSON payload passed to the workflow.
22    pub inputs: Value,
23    /// Where this schedule was created (`handler` or `api`).
24    pub source: ScheduleSource,
25    /// When the schedule was disabled. `None` means active.
26    pub disabled_at: Option<DateTime<Utc>>,
27    /// When the schedule last created a run.
28    pub last_triggered_at: Option<DateTime<Utc>>,
29    /// When the schedule will next fire. Always set on an active schedule.
30    pub next_trigger_at: Option<DateTime<Utc>>,
31    /// Why Ironflow disabled the schedule on its own (e.g. its next trigger
32    /// cannot be computed). `None` when paused by a user or never disabled.
33    pub last_error: Option<String>,
34    /// Queue priority given to every run the schedule creates, from -100 to 100.
35    pub priority: i16,
36    /// User who created the schedule. `None` for handler-declared schedules.
37    pub created_by_user_id: Option<Uuid>,
38    /// When the schedule was created.
39    pub created_at: DateTime<Utc>,
40    /// When the schedule was last updated.
41    pub updated_at: DateTime<Utc>,
42}
43
44impl From<Schedule> for ScheduleResponse {
45    fn from(s: Schedule) -> Self {
46        Self {
47            id: s.id,
48            workflow_name: s.workflow_name,
49            cron_expression: s.cron_expression,
50            inputs: s.inputs,
51            source: s.source,
52            disabled_at: s.disabled_at,
53            last_triggered_at: s.last_triggered_at,
54            next_trigger_at: s.next_trigger_at,
55            last_error: s.last_error,
56            priority: s.priority,
57            created_by_user_id: s.created_by_user_id,
58            created_at: s.created_at,
59            updated_at: s.updated_at,
60        }
61    }
62}
63
64/// Create schedule request body.
65#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
66#[derive(Debug, Deserialize, Validate)]
67pub struct CreateScheduleRequest {
68    /// Name of the workflow to trigger.
69    #[validate(length(min = 1, message = "workflow_name must not be empty"))]
70    pub workflow_name: String,
71    /// Cron expression (6-field format, e.g. `"0 */5 * * * *"`).
72    #[validate(length(min = 1, message = "cron_expression must not be empty"))]
73    pub cron_expression: String,
74    /// JSON payload for the workflow. Defaults to `{}`.
75    #[serde(default = "default_inputs")]
76    pub inputs: Value,
77    /// Queue priority given to every run the schedule creates, from -100 to
78    /// 100. Defaults to the priority the workflow handler declares.
79    ///
80    /// A higher priority run is picked first by workers. A running run is
81    /// never preempted, and a low priority run is not aged.
82    #[serde(default)]
83    pub priority: Option<i16>,
84}
85
86fn default_inputs() -> Value {
87    Value::Object(serde_json::Map::new())
88}
89
90/// Update schedule request body. All fields optional.
91#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
92#[derive(Debug, Deserialize)]
93pub struct UpdateScheduleRequest {
94    /// New cron expression.
95    pub cron_expression: Option<String>,
96    /// New inputs payload.
97    pub inputs: Option<Value>,
98}