use std::{thread, time}; use cron::Schedule; use chrono::Utc; use std::str::FromStr; // --------------------------------------------------------------------------------------------------- trait Task { fn run(&self); } // --------------------------------------------------------------------------------------------------- struct TaskWebsiteUp { url: String, } impl TaskWebsiteUp { fn new(url: String) -> TaskWebsiteUp { let task = TaskWebsiteUp { url: url, }; return task; } } impl Task for TaskWebsiteUp { fn run(&self) { let client = reqwest::blocking::Client::new(); let resp = client.get(self.url).send().expect("Got an error calling for the website"); let status = resp.status().as_u16(); println!("{}", status); } } // --------------------------------------------------------------------------------------------------- struct Job { schedule: cron::Schedule, next: chrono::DateTime<chrono::Utc>, name: String, function: Box<dyn Fn()>, } impl Job { fn new(expression: &str, name: String, function: Box<dyn Fn()>) -> Job { let job = Job{ schedule: Schedule::from_str(expression).unwrap(), next: chrono::MIN_DATETIME, name: name, function: function, }; return job; } fn set_next_time(&mut self) { self.next = self.schedule.upcoming(Utc).take(1).next().unwrap(); } fn run(&self) { (self.function)(); } } // --------------------------------------------------------------------------------------------------- fn main() { // Store an array of jobs let mut jobs = Vec::new(); // Define a job to run let test_task = TaskWebsiteUp::new("xxnetwork.wiki".to_string()); let test_job = Job::new("0 * * * * * *", "Hello, World.".to_string(), Box::new(move || test_task.run())); jobs.push(test_job); loop { // Get a second from now for sleep let one_sec = time::Duration::from_secs(1); // Get the next timestamp for each job // We need to check this before the sleep, because if checked in the same second it should run, // it returns the next time instead for job in jobs.iter_mut() { job.set_next_time(); } // Sleep for a second // TODO: just sleep to the next job to run thread::sleep(one_sec); // Check through all the jobs in the queue for job in jobs.iter() { // Check if its time for the job to run if chrono::offset::Utc::now().timestamp() >= job.next.timestamp() { println!("{}", job.name); job.run(); } } } }