spring-job 0.4.7

Integrate tokio-cron-scheduler with spring-rs framework
Documentation
use crate::{JobId, JobScheduler};
use serde::de::DeserializeOwned;
use spring::async_trait;
use spring::config::ConfigRegistry;
use spring::plugin::ComponentRegistry;
use spring::{app::App, config::Configurable};
use std::ops::{Deref, DerefMut};

#[async_trait]
pub trait FromApp {
    async fn from_app(job_id: &JobId, scheduler: &JobScheduler, app: &App) -> Self;
}

pub struct Component<T: Clone>(pub T);

#[async_trait]
impl<T> FromApp for Component<T>
where
    T: Clone + Send + Sync + 'static,
{
    async fn from_app(_job_id: &JobId, _scheduler: &JobScheduler, app: &App) -> Self {
        match app.get_component_ref::<T>() {
            Some(component) => Component(T::clone(&component)),
            None => panic!(
                "There is no component of `{}` type",
                std::any::type_name::<T>()
            ),
        }
    }
}

impl<T: Clone> Deref for Component<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<T: Clone> DerefMut for Component<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

#[async_trait]
impl FromApp for JobId {
    async fn from_app(job_id: &JobId, _scheduler: &JobScheduler, _app: &App) -> Self {
        *job_id
    }
}

#[async_trait]
impl FromApp for JobScheduler {
    async fn from_app(_job_id: &JobId, scheduler: &JobScheduler, _app: &App) -> Self {
        scheduler.clone()
    }
}

pub struct Data<T: DeserializeOwned>(pub T);

#[async_trait]
impl<T: DeserializeOwned> FromApp for Data<T> {
    async fn from_app(job_id: &JobId, scheduler: &JobScheduler, _app: &App) -> Self {
        let mut guard = scheduler.context.metadata_storage.write().await;
        let job = guard.get(*job_id).await.expect("job get failed");
        let data =
            job.map(|j| serde_json::from_slice(&j.extra).expect("job extra parse to json failed"));
        Self(data.expect("job extra parse is empty"))
    }
}

pub struct Config<T>(pub T)
where
    T: serde::de::DeserializeOwned + Configurable;

#[async_trait]
impl<T> FromApp for Config<T>
where
    T: serde::de::DeserializeOwned + Configurable,
{
    async fn from_app(_job_id: &JobId, _scheduler: &JobScheduler, app: &App) -> Self {
        match app.get_config::<T>() {
            Ok(config) => Config(config),
            Err(e) => panic!(
                "get config for typeof {} failed: {}",
                std::any::type_name::<T>(),
                e
            ),
        }
    }
}

impl<T> Deref for Config<T>
where
    T: serde::de::DeserializeOwned + Configurable,
{
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}