use crate::{models::PreparedJob, types::Id, u_runner::IdentifiableFuture}; use chrono::{DateTime, Utc}; use core::fmt; use serde::{Deserialize, Serialize}; use std::sync::Arc; pub trait SchedulerJob { fn call(&self) -> IdentifiableFuture<()>; } // scheduler job need to be called repeatedly, // the only way to achieve this is to use Fn() -> Future impl SchedulerJob for F where F: Fn() -> IdentifiableFuture<()>, { fn call(&self) -> IdentifiableFuture<()> { self() } } #[derive(Clone)] pub struct Entry { pub entry_id: Id, pub schedule: Option, pub next: Option>, pub runnable: EntryType, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct EntryStat { pub entry_id: Id, pub job_ident: String, pub schedule: String, pub next: Option>, } #[derive(Clone)] pub enum EntryType { Common(Arc), URunner(PreparedJob), } impl From for EntryType { fn from(value: J) -> Self { Self::Common(Arc::new(value)) } } impl From for EntryType { fn from(value: PreparedJob) -> Self { Self::URunner(value) } } impl Entry { pub fn set_next_run_time(&mut self) { self.next = self.get_next_run_time(); } pub fn get_next_run_time(&self) -> Option> { match &self.schedule { Some(schedule) => schedule.upcoming(Utc).next(), None => Some(Utc::now()), } } pub fn as_stat(&self) -> EntryStat { let job_ident = match &self.runnable { EntryType::URunner(entry) => entry.job.meta.id.to_string(), EntryType::Common(entry) => entry.call().job_ident.to_string(), }; EntryStat { entry_id: self.entry_id, job_ident, schedule: self .schedule .as_ref() .map(|s| s.to_string()) .unwrap_or_default(), next: self.next.clone(), } } } impl fmt::Debug for Entry { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{} {:?} {:?}", self.entry_id, self.schedule, self.next) } }