time_sigil 0.0.2

task scheduler
Documentation
use tokio::sync::{
    mpsc::{self, Receiver, Sender},
    oneshot,
};
use tokio_cron_scheduler::JobScheduler;
pub use tokio_cron_scheduler::{Job, JobSchedulerError};
pub use uuid::Uuid;

use crate::Error;

enum ScheduleCommand {
    New(Job, oneshot::Sender<Uuid>),
    Remove(Uuid),
}

pub struct Schedule {
    inner: JobScheduler,
    rx: Receiver<ScheduleCommand>,
}

#[derive(Debug)]
pub struct ScheduleHandler {
    tx: Sender<ScheduleCommand>,
}

impl Clone for ScheduleHandler {
    fn clone(&self) -> Self {
        Self {
            tx: self.tx.clone(),
        }
    }
}

impl ScheduleHandler {
    pub async fn add(&self, job: Job) -> Result<Uuid, Error> {
        let (tx, rx) = oneshot::channel();
        self.tx
            .send(ScheduleCommand::New(job, tx))
            .await
            .map_err(|_| Error::ChannelClosed)?;
        rx.await.map_err(|_| Error::ChannelClosed)
    }

    pub async fn remove(&self, id: Uuid) -> Result<(), Error> {
        self.tx
            .send(ScheduleCommand::Remove(id))
            .await
            .map_err(|_| Error::ChannelClosed)
    }
}

impl Schedule {
    pub async fn new() -> (Self, ScheduleHandler) {
        let sched = JobScheduler::new().await.unwrap();
        let (tx, rx) = mpsc::channel(10);
        (
            Self {
                inner: sched.into(),
                rx,
            },
            ScheduleHandler { tx },
        )
    }

    pub async fn start(self) -> Result<(), JobSchedulerError> {
        self.inner.start().await?;
        tokio::spawn(self.listen_add_sched());
        Ok(())
    }

    async fn listen_add_sched(mut self) {
        loop {
            while let Some(c) = self.rx.recv().await {
                match c {
                    ScheduleCommand::New(job, tx) => {
                        let uuid = self.inner.add(job).await.unwrap();
                        tx.send(uuid).unwrap();
                    }
                    ScheduleCommand::Remove(id) => {
                        self.inner.remove(&id).await.unwrap();
                    }
                }
            }
        }
    }
}