scouter_types/alert/
cron.rs

1use crate::error::TypeError;
2use chrono::{DateTime, Utc};
3use cron::Schedule;
4use pyo3::prelude::*;
5use serde::{Deserialize, Serialize};
6use std::fmt;
7use std::str::FromStr;
8
9#[pyclass(eq)]
10#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
11pub enum CommonCrons {
12    Every1Minute,
13    Every5Minutes,
14    Every15Minutes,
15    Every30Minutes,
16    EveryHour,
17    Every6Hours,
18    Every12Hours,
19    EveryDay,
20    EveryWeek,
21}
22
23#[pymethods]
24impl CommonCrons {
25    #[getter]
26    pub fn cron(&self) -> String {
27        match self {
28            CommonCrons::Every1Minute => "0 * * * * * *".to_string(),
29            CommonCrons::Every5Minutes => {
30                "0 0,5,10,15,20,25,30,35,40,45,50,55 * * * * *".to_string()
31            }
32            CommonCrons::Every15Minutes => "0 0,15,30,45 * * * * *".to_string(),
33            CommonCrons::Every30Minutes => "0 0,30 * * * * *".to_string(),
34            CommonCrons::EveryHour => "0 0 * * * *".to_string(),
35            CommonCrons::Every6Hours => "0 0 */6 * * *".to_string(),
36            CommonCrons::Every12Hours => "0 0 */12 * * *".to_string(),
37            CommonCrons::EveryDay => "0 0 0 * * *".to_string(),
38            CommonCrons::EveryWeek => "0 0 0 * * SUN".to_string(),
39        }
40    }
41
42    pub fn get_next(&self) -> String {
43        match self {
44            CommonCrons::Every1Minute => {
45                let schedule = Schedule::from_str("0 * * * * * *").unwrap();
46                schedule.upcoming(Utc).next().unwrap().to_string()
47            }
48            CommonCrons::Every5Minutes => {
49                let schedule =
50                    Schedule::from_str("0 0,5,10,15,20,25,30,35,40,45,50,55 * * * * *").unwrap();
51                schedule.upcoming(Utc).next().unwrap().to_string()
52            }
53            CommonCrons::Every15Minutes => {
54                let schedule = Schedule::from_str("0 0,15,30,45 * * * * *").unwrap();
55                schedule.upcoming(Utc).next().unwrap().to_string()
56            }
57            CommonCrons::Every30Minutes => {
58                let schedule = Schedule::from_str("0 0,30 * * * * *").unwrap();
59                schedule.upcoming(Utc).next().unwrap().to_string()
60            }
61            CommonCrons::EveryHour => {
62                let schedule = Schedule::from_str("0 0 * * * *").unwrap();
63                schedule.upcoming(Utc).next().unwrap().to_string()
64            }
65            CommonCrons::Every6Hours => {
66                let schedule = Schedule::from_str("0 0 */6 * * *").unwrap();
67                schedule.upcoming(Utc).next().unwrap().to_string()
68            }
69            CommonCrons::Every12Hours => {
70                let schedule = Schedule::from_str("0 0 */12 * * *").unwrap();
71                schedule.upcoming(Utc).next().unwrap().to_string()
72            }
73            CommonCrons::EveryDay => {
74                let schedule = Schedule::from_str("0 0 0 * * *").unwrap();
75                schedule.upcoming(Utc).next().unwrap().to_string()
76            }
77            CommonCrons::EveryWeek => {
78                let schedule = Schedule::from_str("0 0 0 * * SUN").unwrap();
79                schedule.upcoming(Utc).next().unwrap().to_string()
80            }
81        }
82    }
83}
84
85#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
86pub struct CustomInterval {
87    pub begin: DateTime<Utc>,
88    pub end: DateTime<Utc>,
89}
90
91impl CustomInterval {
92    pub fn new(begin: DateTime<Utc>, end: DateTime<Utc>) -> Result<Self, TypeError> {
93        if begin >= end {
94            return Err(TypeError::StartTimeError);
95        }
96        Ok(CustomInterval { begin, end })
97    }
98}
99
100#[pyclass(eq)]
101#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Default)]
102pub enum TimeInterval {
103    FifteenMinutes,
104    ThirtyMinutes,
105    OneHour,
106    #[default]
107    FourHours,
108    SixHours,
109    TwelveHours,
110    TwentyFourHours,
111    SevenDays,
112    Custom,
113}
114
115impl TimeInterval {
116    pub fn to_minutes(&self) -> i32 {
117        match self {
118            TimeInterval::FifteenMinutes => 15,
119            TimeInterval::ThirtyMinutes => 30,
120            TimeInterval::OneHour => 60,
121            TimeInterval::FourHours => 240,
122            TimeInterval::SixHours => 360,
123            TimeInterval::TwelveHours => 720,
124            TimeInterval::TwentyFourHours => 1440,
125            TimeInterval::SevenDays => 10080,
126            TimeInterval::Custom => 0,
127        }
128    }
129
130    /// Convert interval to a start and end time
131    pub fn to_begin_end_times(&self) -> Result<(DateTime<Utc>, DateTime<Utc>), TypeError> {
132        let end = Utc::now();
133        let start = match self {
134            TimeInterval::FifteenMinutes => end - chrono::Duration::minutes(15),
135            TimeInterval::ThirtyMinutes => end - chrono::Duration::minutes(30),
136            TimeInterval::OneHour => end - chrono::Duration::hours(1),
137            TimeInterval::FourHours => end - chrono::Duration::hours(4),
138            TimeInterval::SixHours => end - chrono::Duration::hours(6),
139            TimeInterval::TwelveHours => end - chrono::Duration::hours(12),
140            TimeInterval::TwentyFourHours => end - chrono::Duration::hours(24),
141            TimeInterval::SevenDays => end - chrono::Duration::days(7),
142            _ => {
143                return Err(TypeError::InvalidTimeIntervalError);
144            }
145        };
146        Ok((start, end))
147    }
148
149    pub fn from_string(time_interval: &str) -> TimeInterval {
150        match time_interval {
151            "15minute" => TimeInterval::FifteenMinutes,
152            "30minute" => TimeInterval::ThirtyMinutes,
153            "1hour" => TimeInterval::OneHour,
154            "4hour" => TimeInterval::FourHours,
155            "6hour" => TimeInterval::SixHours,
156            "12hour" => TimeInterval::TwelveHours,
157            "24hour" => TimeInterval::TwentyFourHours,
158            "7day" => TimeInterval::SevenDays,
159            "custom" => TimeInterval::Custom,
160            _ => TimeInterval::SixHours,
161        }
162    }
163}
164
165impl fmt::Display for TimeInterval {
166    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
167        match self {
168            TimeInterval::FifteenMinutes => write!(f, "15minute"),
169            TimeInterval::ThirtyMinutes => write!(f, "30minute"),
170            TimeInterval::OneHour => write!(f, "1hour"),
171            TimeInterval::FourHours => write!(f, "4hour"),
172            TimeInterval::SixHours => write!(f, "6hour"),
173            TimeInterval::TwelveHours => write!(f, "12hour"),
174            TimeInterval::TwentyFourHours => write!(f, "24hour"),
175            TimeInterval::SevenDays => write!(f, "7day"),
176            TimeInterval::Custom => write!(f, "custom"),
177        }
178    }
179}
180
181// test crons
182
183#[cfg(test)]
184mod tests {
185    use super::*;
186
187    #[test]
188    fn test_every_30_minutes_cron() {
189        let cron = CommonCrons::Every30Minutes;
190
191        // check cron
192        assert_eq!(cron.cron(), "0 0,30 * * * * *");
193
194        // check next
195        let _next = cron.get_next();
196    }
197
198    #[test]
199    fn test_every_hour_cron() {
200        let cron = CommonCrons::EveryHour;
201        // check cron
202        assert_eq!(cron.cron(), "0 0 * * * *");
203        let _next = cron.get_next();
204    }
205
206    #[test]
207    fn test_every_6_hours_cron() {
208        let cron = CommonCrons::Every6Hours;
209        // check cron
210        assert_eq!(cron.cron(), "0 0 */6 * * *");
211        let _next = cron.get_next();
212    }
213
214    #[test]
215    fn test_every_12_hours_cron() {
216        let cron = CommonCrons::Every12Hours;
217        // check cron
218        assert_eq!(cron.cron(), "0 0 */12 * * *");
219        let _next = cron.get_next();
220    }
221
222    #[test]
223    fn test_every_day_cron() {
224        let cron = CommonCrons::EveryDay;
225        // check cron
226        assert_eq!(cron.cron(), "0 0 0 * * *");
227        let _next = cron.get_next();
228    }
229
230    #[test]
231    fn test_every_week_cron() {
232        let cron = CommonCrons::EveryWeek;
233        // check cron
234        assert_eq!(cron.cron(), "0 0 0 * * SUN");
235        let _next = cron.get_next();
236    }
237
238    #[test]
239    fn test_cron_schedule_cron() {
240        let cron = CommonCrons::Every1Minute;
241        let schedule = Schedule::from_str(&cron.cron()).unwrap();
242        let next = schedule.upcoming(Utc).next().unwrap();
243        assert_eq!(next.to_string(), cron.get_next());
244
245        let cron = CommonCrons::Every5Minutes;
246        let schedule = Schedule::from_str(&cron.cron()).unwrap();
247        let next = schedule.upcoming(Utc).next().unwrap();
248        assert_eq!(next.to_string(), cron.get_next());
249
250        let cron = CommonCrons::Every15Minutes;
251        let schedule = Schedule::from_str(&cron.cron()).unwrap();
252        let next = schedule.upcoming(Utc).next().unwrap();
253        assert_eq!(next.to_string(), cron.get_next());
254
255        let cron = CommonCrons::Every30Minutes;
256        let schedule = Schedule::from_str(&cron.cron()).unwrap();
257        let next = schedule.upcoming(Utc).next().unwrap();
258        assert_eq!(next.to_string(), cron.get_next());
259
260        let cron = CommonCrons::EveryHour;
261        let schedule = Schedule::from_str(&cron.cron()).unwrap();
262        let next = schedule.upcoming(Utc).next().unwrap();
263        assert_eq!(next.to_string(), cron.get_next());
264
265        let cron = CommonCrons::Every6Hours;
266        let schedule = Schedule::from_str(&cron.cron()).unwrap();
267        let next = schedule.upcoming(Utc).next().unwrap();
268        assert_eq!(next.to_string(), cron.get_next());
269
270        let cron = CommonCrons::Every12Hours;
271        let schedule = Schedule::from_str(&cron.cron()).unwrap();
272        let next = schedule.upcoming(Utc).next().unwrap();
273        assert_eq!(next.to_string(), cron.get_next());
274
275        let cron = CommonCrons::EveryDay;
276        let schedule = Schedule::from_str(&cron.cron()).unwrap();
277        let next = schedule.upcoming(Utc).next().unwrap();
278        assert_eq!(next.to_string(), cron.get_next());
279
280        let cron = CommonCrons::EveryWeek;
281        let schedule = Schedule::from_str(&cron.cron()).unwrap();
282        let next = schedule.upcoming(Utc).next().unwrap();
283        assert_eq!(next.to_string(), cron.get_next());
284    }
285}