Skip to main content

nest_rs_queue_macros/
lib.rs

1//! The `#[processor]` decorator, re-exported by `nest-rs-queue` (the
2//! backend-agnostic abstractions crate) so the call site keeps writing
3//! `use nest_rs_queue::processor;` regardless of which backend integration
4//! (nest-rs-redis, …) is wired in.
5use proc_macro::TokenStream;
6
7mod processor;
8mod queue;
9
10/// Orchestrator on an `#[injectable]` provider's `impl` block. Each method
11/// tagged with `#[process(queue = "...", concurrency, retries)]` becomes a
12/// queue consumer the `QueueWorker` spawns at boot.
13///
14/// A single provider may carry several `#[process]` methods (different
15/// queues, different concurrencies) sharing the same `#[inject]`
16/// dependencies — pooling related queue handlers on one service keeps
17/// shared state (clients, repositories) in one place.
18///
19/// The `queue` is named either by a raw string literal (legacy form) or by a
20/// [`QueueName`](nest_rs_queue::QueueName) **type** — the preferred form,
21/// declared with [`queue`](macro@crate::queue) at the feature port:
22/// `#[process(queue = AudioQueue)]`. The type form reads
23/// `<AudioQueue as QueueName>::NAME` into the inventory entry **and** asserts,
24/// at compile time, that this method's job argument is
25/// `<AudioQueue as QueueName>::Job` — a mismatch is a build error naming both
26/// types, not a job that silently never drains.
27///
28/// Per-method attributes (exactly one `#[process]` per method):
29///
30/// - `#[process(queue = "audio")]` — minimal, defaults `concurrency = 1`,
31///   `retries = 0`.
32/// - `#[process(queue = "audio", concurrency = 5)]` — bound the in-flight jobs
33///   per worker.
34/// - `#[process(queue = "audio", concurrency = 5, retries = 3)]` — apalis
35///   retries before the job lands on the queue's failed list.
36///
37/// The method signature is `async fn(&self, job: T) -> anyhow::Result<()>`,
38/// where `T: Job`. The macro extracts the job type from the second
39/// parameter, generates a typed handler, and submits a per-method
40/// inventory entry the worker drains.
41///
42/// # Expands to
43///
44/// The impl unchanged, plus per `#[process]` method: a hidden type-erased
45/// handler `fn` (unwraps the wire envelope, deserializes the job, resolves the
46/// provider, dispatches inside the `JobContext`) and a `ProcessMethod`
47/// submitted to the link-time inventory. No `Discoverable` — the host's own
48/// `#[injectable]` owns it.
49///
50/// ```ignore
51/// impl AudioProcessor { /* unchanged */ }
52/// fn __nestrs_process_handler_audio_processor_transcode(payload, container) -> Pin<Box<dyn Future<…>>> { /* … */ }
53/// ::nest_rs_core::inventory::submit! {
54///     ::nest_rs_queue::ProcessMethod {
55///         name: "AudioProcessor::transcode", queue: "audio",
56///         concurrency: 5, retries: 3,
57///         provider_type_id: || TypeId::of::<AudioProcessor>(),
58///         handler: __nestrs_process_handler_audio_processor_transcode,
59///     }
60/// }
61/// ```
62#[proc_macro_attribute]
63pub fn processor(args: TokenStream, input: TokenStream) -> TokenStream {
64    processor::processor(args, input)
65}
66
67/// Stamp a unit struct with a compile-time queue identity — its wire name and
68/// the [`Job`](nest_rs_queue::Job) payload it carries — by implementing
69/// `QueueName`. Lives beside the payload at the feature port; both the producer
70/// (`push_to::<Q>`) and the consumer (`#[process(queue = Q)]`) name the type,
71/// so a typo'd name or a mismatched payload is a compile error, not a job that
72/// silently never drains.
73///
74/// ```ignore
75/// #[queue(name = "audio", job = TranscodeCommand)]
76/// pub struct AudioQueue;
77/// ```
78///
79/// # Expands to
80///
81/// ```ignore
82/// pub struct AudioQueue;
83/// impl ::nest_rs_queue::QueueName for AudioQueue {
84///     const NAME: &'static str = "audio";
85///     type Job = TranscodeCommand;
86/// }
87/// ```
88#[proc_macro_attribute]
89pub fn queue(args: TokenStream, input: TokenStream) -> TokenStream {
90    queue::queue(args, input)
91}