Skip to content

Instantly share code, notes, and snippets.

@imbolc
Created July 15, 2022 12:43
Show Gist options
  • Save imbolc/25a504e7819f68f82717399c59a259a5 to your computer and use it in GitHub Desktop.
Save imbolc/25a504e7819f68f82717399c59a259a5 to your computer and use it in GitHub Desktop.
Statically checked sqlxmq context and job list
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::fmt::Debug;
use std::marker::PhantomData;
use std::sync::Arc;
struct JobRegistry<J, C> {
jobs: PhantomData<J>,
context: Arc<C>,
}
struct JobContext<C> {
name: String,
context: Arc<C>,
}
trait CurrentJob<C>: Debug + Sized + DeserializeOwned {
fn run(self, _ctx: JobContext<C>) {
println!("{:?}", self);
}
}
trait JobList<C>: CurrentJob<C> + Serialize {
fn schedule(&self) -> String {
serde_json::to_string(self).unwrap()
}
}
impl<J, C> JobRegistry<J, C>
where
J: CurrentJob<C>,
{
fn spawn_from_db(&self, db_data: &str) {
let job = serde_json::from_str(db_data).unwrap();
self.spawn_internal(job)
}
fn spawn_internal(&self, job: J) {
job.run(JobContext {
name: "foo".into(),
context: self.context.clone(),
})
}
}
#[derive(Debug, Deserialize, Serialize)]
struct JobFoo;
#[derive(Debug, Deserialize, Serialize)]
struct JobBar;
#[derive(Debug, Deserialize, Serialize)]
enum Jobs {
Foo(JobFoo),
Bar(JobBar),
}
impl CurrentJob<()> for JobFoo {}
impl CurrentJob<()> for JobBar {}
// Could be probably done by a macro
impl JobList<()> for Jobs {}
impl CurrentJob<()> for Jobs {
fn run(self, ctx: JobContext<()>) {
match self {
Self::Foo(j) => j.run(ctx),
Self::Bar(j) => j.run(ctx),
}
}
}
fn main() {
let r = JobRegistry {
jobs: PhantomData::<Jobs>,
context: Arc::new(()),
};
// Scheduling is done using job list rather than a particular job,
// so you can't schedule a job until you add it to the list
let db_data = Jobs::Foo(JobFoo).schedule();
r.spawn_from_db(&db_data)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment