graphile_worker_crontab_runner 0.7.9

Crontab runner package for graphile worker, a high performance Rust/PostgreSQL job queue
Documentation
use chrono::prelude::*;
use graphile_worker_crontab_types::{Crontab, JobKeyMode};
use serde::Serialize;
use serde_json::json;

#[derive(Serialize, Debug)]
#[serde(rename_all = "camelCase")]
struct CrontabJobInner {
    task: String,
    payload: Option<serde_json::Value>,
    queue_name: Option<String>,
    run_at: DateTime<Local>,
    max_attempts: Option<u16>,
    priority: Option<i16>,
    job_key: Option<String>,
    job_key_mode: Option<JobKeyMode>,
}

impl CrontabJobInner {
    fn from_crontab_and_run_at<Tz: TimeZone>(crontab: &Crontab, run_at: &DateTime<Tz>) -> Self {
        Self {
            task: crontab.task_identifier.to_owned(),
            payload: crontab.payload.to_owned(),
            queue_name: crontab.options.queue.to_owned(),
            run_at: run_at.with_timezone(&Local),
            max_attempts: crontab.options.max.to_owned(),
            priority: crontab.options.priority.to_owned(),
            job_key: crontab.options.job_key.to_owned(),
            job_key_mode: crontab.options.job_key_mode.to_owned(),
        }
    }
}

#[derive(Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub(crate) struct CrontabJob {
    identifier: String,
    job: CrontabJobInner,
}

impl CrontabJob {
    pub(crate) fn for_cron<Tz: TimeZone>(
        crontab: &Crontab,
        ts: &DateTime<Tz>,
        backfilled: bool,
    ) -> Self {
        let mut job = CrontabJobInner::from_crontab_and_run_at(crontab, ts);

        if let Some(payload) = job.payload.as_mut().and_then(|p| p.as_object_mut()) {
            payload.insert(
                "_cron".into(),
                json!({
                    "ts": format!("{ts:?}"),
                    "backfilled": backfilled
                }),
            );
        }

        Self {
            identifier: crontab.identifier().to_owned(),
            job,
        }
    }
}