cronjob/
cronjob.rs

1use chrono::{FixedOffset, Local};
2use cron::Schedule;
3
4use std::str::FromStr;
5use std::thread;
6use std::time::Duration;
7
8use command::Command;
9
10/// The object to create and execute cronjobs for yout application.
11pub struct CronJob {
12    name: String,
13    command: Box<dyn Command>,
14    seconds: Option<String>,
15    minutes: Option<String>,
16    hours: Option<String>,
17    day_of_month: Option<String>,
18    month: Option<String>,
19    day_of_week: Option<String>,
20    year: Option<String>,
21    offset: Option<FixedOffset>,
22    interval: u64,
23}
24
25impl CronJob {
26    /// Constructs new `CronJob` object.
27    pub fn new<C: Command>(name: &str, command: C) -> Self {
28        CronJob {
29            name: name.to_string(),
30            command: Box::new(command),
31            seconds: None,
32            minutes: None,
33            hours: None,
34            day_of_month: None,
35            month: None,
36            day_of_week: None,
37            year: None,
38            offset: None,
39            interval: 500,
40        }
41    }
42
43    pub fn seconds(&mut self, seconds: &str) -> &mut Self {
44        self.seconds = Some(seconds.to_string());
45        self
46    }
47
48    pub fn minutes(&mut self, minutes: &str) -> &mut Self {
49        self.minutes = Some(minutes.to_string());
50        self
51    }
52
53    pub fn hours(&mut self, hours: &str) -> &mut Self {
54        self.hours = Some(hours.to_string());
55        self
56    }
57
58    pub fn day_of_month(&mut self, day_of_month: &str) -> &mut Self {
59        self.day_of_month = Some(day_of_month.to_string());
60        self
61    }
62
63    pub fn month(&mut self, month: &str) -> &mut Self {
64        self.month = Some(month.to_string());
65        self
66    }
67
68    pub fn day_of_week(&mut self, day_of_week: &str) -> &mut Self {
69        self.day_of_week = Some(day_of_week.to_string());
70        self
71    }
72
73    pub fn year(&mut self, year: &str) -> &mut Self {
74        self.year = Some(year.to_string());
75        self
76    }
77
78    pub fn offset(&mut self, timezone_offset: i32) -> &mut Self {
79        self.offset = Some(FixedOffset::east(timezone_offset));
80        self
81    }
82
83    /// Set checking interval in millis
84    pub fn set_checking_interval(&mut self, interval: u64) -> &mut Self {
85        self.interval = interval;
86        self
87    }
88
89    /// Returns the schedule for the cronjob, with this you are able to get the next occurences.
90    pub fn get_schedule(&mut self) -> Schedule {
91        let asterix = String::from("*");
92        let cron = format!(
93            "{} {} {} {} {} {} {}",
94            self.seconds.as_ref().unwrap_or(&asterix),
95            self.minutes.as_ref().unwrap_or(&asterix),
96            self.hours.as_ref().unwrap_or(&asterix),
97            self.day_of_month.as_ref().unwrap_or(&asterix),
98            self.month.as_ref().unwrap_or(&asterix),
99            self.day_of_week.as_ref().unwrap_or(&asterix),
100            self.year.as_ref().unwrap_or(&asterix)
101        );
102        Schedule::from_str(&cron).unwrap()
103    }
104
105    /// Starts the cronjob without threading.
106    pub fn start_job(&mut self) {
107        let schedule = self.get_schedule();
108        let offset = self.offset.unwrap_or_else(|| FixedOffset::east(0));
109
110        loop {
111            let mut upcoming = schedule.upcoming(offset).take(1);
112            thread::sleep(Duration::from_millis(self.interval));
113            let local = &Local::now();
114
115            if let Some(datetime) = upcoming.next() {
116                if datetime.timestamp() <= local.timestamp() {
117                    self.command.execute(&self.name);
118                }
119            }
120        }
121    }
122
123    /// Starts the cronjob with threading. Stops when application quits.
124    pub fn start_job_threaded(mut cronjob: CronJob) {
125        thread::Builder::new()
126            .name(cronjob.name.clone())
127            .spawn(move || cronjob.start_job())
128            .expect("There was an error in an cronjob");
129    }
130}