use std::sync::{Arc, Mutex}; use chrono::{DateTime, Local, Timelike, Utc}; use cron_tab::Cron; use sea_orm::{DatabaseConnection, DbErr}; use crate::dao::alarm::{self, create_alarm, get_alarms}; use crate::ringer::Ringer; use crate::types::Alarm; #[derive(Debug)] pub struct Scheduler { ringer: Arc>, cron: Arc>>, alarms: Arc>>, db: Arc, } impl Scheduler { pub fn new( ringer: Arc>, cron: Arc>>, db: Arc, ) -> Self { Self { ringer, cron, alarms: Arc::new(Mutex::new(Vec::new())), db, } } pub fn schedule(&self, cron_schedule: &str) -> Result<(), String> { let ringer = self.ringer.clone(); let cron = self.cron.clone(); let job_result = cron .lock() .map_err(|e| e.to_string())? .add_fn(cron_schedule, move || { let guard = ringer.lock(); if let Ok(ringer) = guard { ringer.ring().unwrap(); } }); job_result.expect("Faild to add job"); Ok(()) } pub async fn add_alarm(&self, time: DateTime) -> Result { let cron_schedule = format!("{} {} {} * * *", "*", time.minute(), time.hour()); let alarm = Alarm::new(true, time); create_alarm(&*self.db, "something", time) .await .map_err(|e| e.to_string())?; self.schedule(&cron_schedule).map_err(|e| e.to_string())?; println!("Added alarm {}", cron_schedule); Ok(alarm) } pub async fn get_alarms(&self, enabled: Option) -> Result, DbErr> { get_alarms(&*self.db, enabled).await .map(|alarms| alarms .into_iter() .map(|a| a.into()) .collect() ) } pub fn start(&self) { self.cron.lock().expect("Failed to lock cron").start(); } }