use crate::job::{BoxFuture, FailedJob, Job, QueuedJob, ReservedJob};
use rustlavel_core::events::{self, Event};
use rustlavel_core::{Json, Result};
use std::time::Duration;
pub trait Queue: Send + Sync + 'static {
fn driver(&self) -> &'static str;
fn push(&self, job: QueuedJob) -> BoxFuture<'_, Result<String>>;
fn push_on<'a>(&'a self, queue: &'a str, job: QueuedJob) -> BoxFuture<'a, Result<String>> {
self.push(job.on_queue(queue))
}
fn later<'a>(&'a self, delay: Duration, job: QueuedJob) -> BoxFuture<'a, Result<String>> {
self.push(job.with_delay(delay))
}
fn pop<'a>(&'a self, queue: &'a str) -> BoxFuture<'a, Result<Option<ReservedJob>>>;
fn size<'a>(&'a self, queue: &'a str) -> BoxFuture<'a, Result<u64>>;
fn delete<'a>(&'a self, job: &'a ReservedJob) -> BoxFuture<'a, Result<()>>;
fn release<'a>(&'a self, job: &'a ReservedJob, delay: Duration) -> BoxFuture<'a, Result<()>>;
fn fail<'a>(&'a self, job: &'a ReservedJob, error: &'a str) -> BoxFuture<'a, Result<()>>;
fn failed_jobs(&self) -> BoxFuture<'_, Result<Vec<FailedJob>>>;
fn clear<'a>(&'a self, queue: &'a str) -> BoxFuture<'a, Result<u64>>;
}
pub trait QueueExt: Queue {
fn dispatch<'a, J: Job>(&'a self, job: &'a J) -> BoxFuture<'a, Result<String>> {
self.push(job.to_queued())
}
fn dispatch_on<'a, J: Job>(
&'a self,
queue: &'a str,
job: &'a J,
) -> BoxFuture<'a, Result<String>> {
self.push_on(queue, job.to_queued())
}
fn dispatch_later<'a, J: Job>(
&'a self,
delay: Duration,
job: &'a J,
) -> BoxFuture<'a, Result<String>> {
self.later(delay, job.to_queued())
}
}
impl<T: Queue + ?Sized> QueueExt for T {}
pub(crate) fn record_pushed(driver: &'static str, job: &QueuedJob, id: &str) {
if !events::has_subscribers() {
return;
}
Event::new("queue.pushed")
.with("job", job.name.as_str())
.with("queue", job.queue.as_str())
.with("id", id)
.with("driver", driver)
.with("delay_seconds", job.delay.as_secs())
.dispatch();
}
pub async fn stats(queue: &dyn Queue, names: &[String]) -> Result<Json> {
let mut sizes = Vec::new();
for name in names {
sizes.push((name.clone(), Json::from(queue.size(name).await?)));
}
let failed = queue.failed_jobs().await?;
Ok(Json::object([
("driver", Json::from(queue.driver())),
("queues", Json::Object(sizes.into_iter().collect())),
("failed", Json::Array(failed.iter().map(FailedJob::to_json).collect())),
]))
}