Skip to main content

syspulse_core/
scheduler.rs

1use tokio_cron_scheduler::{Job, JobScheduler};
2use tracing::info;
3
4use crate::error::{Result, SyspulseError};
5
6pub struct Scheduler {
7    scheduler: JobScheduler,
8}
9
10impl Scheduler {
11    pub async fn new() -> Result<Self> {
12        let scheduler = JobScheduler::new()
13            .await
14            .map_err(|e| SyspulseError::Scheduler(e.to_string()))?;
15        Ok(Self { scheduler })
16    }
17
18    /// Schedule a daemon to be triggered on a cron expression.
19    /// The callback receives the daemon name and should start the daemon.
20    pub async fn schedule_daemon<F, Fut>(
21        &mut self,
22        name: &str,
23        cron_expr: &str,
24        callback: F,
25    ) -> Result<()>
26    where
27        F: Fn(String) -> Fut + Send + Sync + Clone + 'static,
28        Fut: std::future::Future<Output = ()> + Send,
29    {
30        let daemon_name = name.to_string();
31        let cb = callback.clone();
32        let job = Job::new_async(cron_expr, move |_uuid, _lock| {
33            let name = daemon_name.clone();
34            let cb = cb.clone();
35            Box::pin(async move {
36                info!("Cron trigger firing for daemon '{}'", name);
37                cb(name).await;
38            })
39        })
40        .map_err(|e| SyspulseError::Scheduler(e.to_string()))?;
41
42        self.scheduler
43            .add(job)
44            .await
45            .map_err(|e| SyspulseError::Scheduler(e.to_string()))?;
46        info!("Scheduled daemon '{}' with cron '{}'", name, cron_expr);
47        Ok(())
48    }
49
50    /// Start the scheduler so jobs begin firing.
51    pub async fn start(&self) -> Result<()> {
52        self.scheduler
53            .start()
54            .await
55            .map_err(|e| SyspulseError::Scheduler(e.to_string()))?;
56        info!("Cron scheduler started");
57        Ok(())
58    }
59
60    /// Shut down the scheduler, stopping all jobs.
61    pub async fn shutdown(&mut self) -> Result<()> {
62        self.scheduler
63            .shutdown()
64            .await
65            .map_err(|e| SyspulseError::Scheduler(e.to_string()))?;
66        info!("Cron scheduler shut down");
67        Ok(())
68    }
69}