nest_rs_queue/producer.rs
1//! Backend + producer seams.
2//!
3//! Every queue backend implements [`QueueBackend`] (the boot identity used by
4//! diagnostics) and exposes a [`JobProducer`] surface so any feature can
5//! enqueue without naming the backend. The first-class backend is `apalis-redis`
6//! (shipped as `nestrs-queue`); third-party backends provide their own
7//! `*Module` that registers a `JobProducer` in the container the same way.
8
9use async_trait::async_trait;
10use serde::Serialize;
11
12use crate::processor::Job;
13
14/// A queue backend, identified by name for boot diagnostics. The actual
15/// runtime work happens through [`JobProducer`] (enqueue) and
16/// [`JobConsumer`](crate::consumer::JobConsumer) (drain `ProcessMethod` and
17/// dispatch). A backend's module typically:
18///
19/// 1. seeds an `Arc<dyn JobProducer>` in the container (so any service can
20/// inject it generically), and
21/// 2. contributes a `Transport` whose `serve` runs the backend's
22/// [`JobConsumer`] driver.
23pub trait QueueBackend: Send + Sync + 'static {
24 /// Stable display name (e.g. `"apalis-redis"`, `"sqs"`, `"in-memory"`).
25 /// Logged at boot when the consumer attaches.
26 fn name(&self) -> &'static str;
27}
28
29/// Backend-agnostic producer: push a JSON-serialized job onto a named queue.
30/// Concrete backends implement this; typed pushes are a convenience built on
31/// top via [`JobProducerExt`].
32#[async_trait]
33pub trait JobProducer: Send + Sync + 'static {
34 /// Push a JSON-encoded job onto `queue`. The wire format is always JSON;
35 /// a backend may re-encode internally but must round-trip the payload.
36 async fn push_json(&self, queue: &str, payload: serde_json::Value) -> anyhow::Result<()>;
37}
38
39/// Typed-push convenience over any [`JobProducer`]. Lives as an extension trait
40/// so the producer trait stays object-safe (`Arc<dyn JobProducer>`).
41#[async_trait]
42pub trait JobProducerExt: JobProducer {
43 /// Serialize `job` to JSON and push it onto `queue`.
44 async fn push<J: Job + Serialize>(&self, queue: &str, job: J) -> anyhow::Result<()> {
45 let value = serde_json::to_value(&job)?;
46 self.push_json(queue, value).await
47 }
48}
49
50impl<T: JobProducer + ?Sized> JobProducerExt for T {}