78 lines
2.0 KiB
Rust
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();
|
|
}
|
|
}
|