cronback_api_model/
trigger.rs1use chrono::{DateTime, Utc};
2#[cfg(feature = "dto")]
3use dto::{FromProto, IntoProto};
4use serde::{Deserialize, Serialize};
5use serde_with::skip_serializing_none;
6use strum::Display;
7#[cfg(feature = "validation")]
8use validator::Validate;
9
10use super::{Action, Payload, Schedule};
11use crate::{Recurring, RunAt, Webhook};
12
13#[derive(Debug, Deserialize, Default)]
14#[cfg_attr(feature = "validation", derive(Validate))]
15#[cfg_attr(
16 feature = "dto",
17 derive(IntoProto),
18 proto(target = "proto::scheduler_proto::ListTriggersFilter")
19)]
20pub struct TriggersFilter {
21 #[serde(default)]
22 #[cfg_attr(feature = "dto", proto(name = "statuses"))]
23 pub status: Vec<TriggerStatus>,
24}
25
26#[derive(Debug, Display, Clone, Copy, Serialize, Deserialize, PartialEq)]
27#[cfg_attr(feature = "client", non_exhaustive)]
28#[cfg_attr(
29 feature = "dto",
30 derive(IntoProto, FromProto),
31 proto(target = "proto::trigger_proto::TriggerStatus")
32)]
33#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
34#[cfg_attr(feature = "clap", clap(rename_all = "snake_case"))]
35#[serde(rename_all = "snake_case")]
36#[strum(serialize_all = "snake_case")]
37pub enum TriggerStatus {
38 Scheduled,
39 OnDemand,
40 Expired,
41 Cancelled,
42 Paused,
43}
44
45#[skip_serializing_none]
46#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
47#[cfg_attr(feature = "validation", derive(Validate))]
48#[cfg_attr(
49 feature = "dto",
50 derive(IntoProto, FromProto),
51 proto(target = "proto::trigger_proto::Trigger")
52)]
53#[cfg_attr(feature = "server", serde(deny_unknown_fields))]
54pub struct Trigger {
55 #[cfg_attr(feature = "server", serde(skip))]
58 #[cfg(feature = "dto")]
59 pub id: Option<lib::types::TriggerId>,
60 #[cfg_attr(
61 feature = "validation",
62 validate(length(
63 min = 2,
64 max = 64,
65 message = "name must be between 2 and 64 characters if set"
66 ))
67 )]
68 #[cfg_attr(feature = "dto", proto(required))]
69 pub name: Option<String>,
70 pub description: Option<String>,
71 pub created_at: Option<DateTime<Utc>>,
72 pub updated_at: Option<DateTime<Utc>>,
73 #[cfg_attr(feature = "validation", validate)]
74 pub action: Option<Action>,
75 #[cfg_attr(feature = "validation", validate)]
76 pub schedule: Option<Schedule>,
77 pub status: Option<TriggerStatus>,
78 pub last_ran_at: Option<DateTime<Utc>>,
79 #[cfg_attr(feature = "validation", validate)]
80 pub payload: Option<Payload>,
81 #[serde(default)]
83 pub estimated_future_runs: Vec<DateTime<Utc>>,
84}
85
86impl Trigger {
87 pub fn webhook(&self) -> Option<&Webhook> {
89 match self.action.as_ref() {
90 | Some(Action::Webhook(webhook)) => Some(webhook),
91 | _ => None,
92 }
93 }
94
95 pub fn recurring(&self) -> Option<&Recurring> {
97 match self.schedule.as_ref() {
98 | Some(Schedule::Recurring(r)) => Some(r),
99 | _ => None,
100 }
101 }
102
103 pub fn run_at(&self) -> Option<&RunAt> {
105 match self.schedule.as_ref() {
106 | Some(Schedule::RunAt(r)) => Some(r),
107 | _ => None,
108 }
109 }
110}
111
112#[cfg(all(test, feature = "validation"))]
113mod tests {
114 use anyhow::Result;
115 use serde_json::json;
116
117 use super::*;
118
119 #[test]
121 fn trigger_status_to_string() {
122 assert_eq!("scheduled", TriggerStatus::Scheduled.to_string());
123 assert_eq!("on_demand", TriggerStatus::OnDemand.to_string());
124 assert_eq!("expired", TriggerStatus::Expired.to_string());
125 assert_eq!("cancelled", TriggerStatus::Cancelled.to_string());
126 assert_eq!("paused", TriggerStatus::Paused.to_string());
127 }
128
129 #[test]
130 fn validate_install_trigger_01() -> Result<()> {
131 std::env::set_var("CRONBACK__SKIP_PUBLIC_IP_VALIDATION", "true");
132
133 let request = json!(
134 {
135 "schedule": {
136 "type": "recurring",
137 "cron": "*/3 * * * * *",
138 "limit": 5
139 },
140 "action": {
141 "url": "http://localhost:3000/action",
142 "timeout_s": 10,
143 "retry": {
144 "delay_s": 100
145 }
146
147 }
148 }
149 );
150
151 let parsed: Trigger = serde_json::from_value(request)?;
152 parsed.validate()?;
153 std::env::remove_var("CRONBACK__SKIP_PUBLIC_IP_VALIDATION");
154 Ok(())
155 }
156}