use std::sync::Arc;
use std::sync::Mutex;
use std::sync::PoisonError;
use std::time::Duration;
use leptoskit_db::Timestamp;
use leptoskit_query::BoxFuture;
use serde::Serialize;
use serde_json::Value;
#[derive(Clone, Debug, PartialEq)]
pub struct JobRecord {
pub name: &'static str,
pub arguments: Value,
pub after: Option<Duration>,
pub at: Option<Timestamp>,
pub key: Option<String>,
pub priority: i32,
}
impl JobRecord {
pub(crate) fn new<J: Serialize>(job: J) -> Self {
Self {
name: std::any::type_name::<J>(),
arguments: serde_json::to_value(job).unwrap_or(Value::Null),
after: None,
at: None,
key: None,
priority: 0,
}
}
}
#[derive(Clone, Debug)]
#[must_use = "a job does nothing unless the mutation commits"]
pub struct Enqueued(Arc<Mutex<JobRecord>>);
impl Enqueued {
pub(crate) fn new(record: JobRecord) -> Self {
Self(Arc::new(Mutex::new(record)))
}
pub fn after(self, delay: Duration) -> Self {
self.update(|record| record.after = Some(delay));
self
}
pub fn at(self, at: Timestamp) -> Self {
self.update(|record| record.at = Some(at));
self
}
pub fn key(self, key: impl Into<String>) -> Self {
let key = key.into();
self.update(|record| record.key = Some(key));
self
}
pub fn priority(self, priority: i32) -> Self {
self.update(|record| record.priority = priority);
self
}
#[must_use]
pub fn record(&self) -> JobRecord {
self.0
.lock()
.unwrap_or_else(PoisonError::into_inner)
.clone()
}
fn update(&self, change: impl FnOnce(&mut JobRecord)) {
change(&mut self.0.lock().unwrap_or_else(PoisonError::into_inner));
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Published {
pub channel: String,
pub message: Value,
}
pub(crate) struct Effects {
pub(crate) after_commit: Vec<BoxFuture<'static, ()>>,
pub(crate) jobs: Vec<Enqueued>,
pub(crate) publications: Vec<Published>,
}
impl Effects {
pub(crate) fn discard(self) {
drop(self);
}
pub(crate) fn release(self) {
for work in self.after_commit {
tokio::spawn(work);
}
drop(self.jobs);
drop(self.publications);
}
}