bronzeflow_time/
schedule_expr.rs1use bronzeflow_utils::ayn_error;
2use chrono::Duration;
3use cron::Schedule;
4use std::str::FromStr;
5
6use bronzeflow_utils::prelude::{BronzeError, Result};
7
8#[derive(Debug, Clone, Copy, PartialEq)]
9pub enum FixPreset {
10 NotRun,
12 Once,
14 Hourly,
16 Daily,
18 Weekly,
20 Monthly,
22 Yearly,
24}
25
26#[derive(Debug, Clone)]
27pub enum SchedulePreset {
28 NotRun,
29 Once,
30}
31
32#[derive(Debug, Clone)]
34pub struct ScheduleDuration(Duration);
35
36#[derive(Debug, Clone)]
37pub enum ScheduleExpr {
38 Cron(Schedule),
39 Preset(SchedulePreset),
40 }
42
43impl ScheduleExpr {
44 pub fn to_cron_schedule(&self) -> Result<Schedule> {
45 match self {
46 ScheduleExpr::Cron(s) => Ok(s.clone()),
47 _ => Err(BronzeError::msg("Can`t transform to schedule")),
48 }
49 }
50}
51
52impl<'a> TryFrom<&'a str> for ScheduleExpr {
53 type Error = BronzeError;
54
55 fn try_from(value: &'a str) -> std::result::Result<Self, Self::Error> {
56 ScheduleExpr::from_str(value)
57 }
58}
59
60impl TryFrom<FixPreset> for ScheduleExpr {
61 type Error = BronzeError;
62
63 fn try_from(value: FixPreset) -> std::result::Result<Self, Self::Error> {
64 match value {
65 FixPreset::NotRun => Ok(ScheduleExpr::Preset(SchedulePreset::NotRun)),
66 FixPreset::Once => Ok(ScheduleExpr::Preset(SchedulePreset::Once)),
67 s => {
68 let s: String = s.get_string();
69 Schedule::from_str(s.as_str())
70 .map(ScheduleExpr::Cron)
71 .map_err(BronzeError::msg)
72 },
73 }
74 }
75}
76
77impl FromStr for FixPreset {
78 type Err = BronzeError;
79
80 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
81 match s.trim() {
82 "@none" => Ok(FixPreset::NotRun),
83 "@once" => Ok(FixPreset::Once),
84 "@hourly" => Ok(FixPreset::Hourly),
85 "@daily" => Ok(FixPreset::Daily),
86 "@weekly" => Ok(FixPreset::Weekly),
87 "@monthly" => Ok(FixPreset::Monthly),
88 "@yearly" => Ok(FixPreset::Yearly),
89 _ => Err(ayn_error!("Error preset string: {}", s)),
90 }
91 }
92}
93
94impl FromStr for ScheduleExpr {
95 type Err = BronzeError;
96
97 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
98 let s = s.trim();
99 if let Ok(c) = Schedule::from_str(s) {
100 return Ok(ScheduleExpr::Cron(c));
101 }
102 FixPreset::from_str(s).map_or_else(Err, |r: FixPreset| r.try_into())
103 }
104}
105
106impl FixPreset {
107 fn get_string(&self) -> String {
108 match self {
109 FixPreset::NotRun => "@none".to_string(),
110 FixPreset::Once => "@once".to_string(),
111 FixPreset::Hourly => "@hourly".to_string(),
112 FixPreset::Daily => "@daily".to_string(),
113 FixPreset::Weekly => "@weekly".to_string(),
114 FixPreset::Monthly => "@monthly".to_string(),
115 FixPreset::Yearly => "@yearly".to_string(),
116 }
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123 use std::assert_matches::assert_matches;
124
125 #[test]
126 fn test_parse_fix_reset_from_str() {
127 assert_eq!(FixPreset::NotRun, FixPreset::from_str("@none").unwrap());
128 assert_eq!(FixPreset::Once, FixPreset::from_str("@once").unwrap());
129 assert_eq!(FixPreset::Hourly, FixPreset::from_str("@hourly").unwrap());
130 assert_eq!(FixPreset::Daily, FixPreset::from_str("@daily").unwrap());
131 assert_eq!(FixPreset::Weekly, "@weekly".parse().unwrap());
132 assert_eq!(FixPreset::Monthly, "@monthly".parse().unwrap());
133 assert_eq!(FixPreset::Yearly, "@yearly".parse().unwrap());
134 }
135
136 #[test]
137 fn test_parse_schedule_expr_from_str() {
138 let not_run = ScheduleExpr::from_str("@none").ok();
139 assert_matches!(not_run, Some(ScheduleExpr::Preset(SchedulePreset::NotRun)));
140
141 let once = ScheduleExpr::from_str("@once").ok();
142 assert_matches!(once, Some(ScheduleExpr::Preset(SchedulePreset::Once)));
143
144 assert_matches!(ScheduleExpr::from_str("error str expr").ok(), None);
145 let s1: Option<ScheduleExpr> = "0 0 0 * * 1 *".parse().ok();
146 assert_matches!(s1, Some(_));
147
148 let s2 = "1/10 * * * * * *".parse().ok();
149 assert_matches!(s2, Some(ScheduleExpr::Cron(_)));
150 }
151}