Files
snooze-pal/src/scheduler.rs
2026-03-03 12:14:39 +01:00

78 lines
2.0 KiB
Rust

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<Mutex<dyn Ringer>>,
cron: Arc<Mutex<Cron<Local>>>,
alarms: Arc<Mutex<Vec<Alarm>>>,
db: Arc<DatabaseConnection>,
}
impl Scheduler {
pub fn new(
ringer: Arc<Mutex<dyn Ringer>>,
cron: Arc<Mutex<Cron<Local>>>,
db: Arc<DatabaseConnection>,
) -> 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<Utc>) -> Result<Alarm, String> {
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<bool>) -> Result<Vec<Alarm>, 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();
}
}