Skip to content

Job attributes

#[proc_macro_derive(Job, attributes(job))]

Applies to any type that is also Serialize + DeserializeOwned + Send + Sync + 'static. Generic types are not supported.

Key Type Valid range Default
queue path expression required; at least two segments, e.g. AppQueues::Emails
name string literal any concat!(module_path!(), "::", stringify!(Type))
retry(...) nested list see below omitted, so Job::retry_policy() stays None and the queue’s policy applies
crate string literal (module path) same rules as #[queues(crate = ...)] auto-resolved

The queue path is split: the last segment becomes the constant Job::QUEUE, and everything before it becomes the associated type Job::Queue. That is why a single-segment path cannot work.

The same grammar in #[job(...)] and #[queue(...)].

retry(
max_attempts = 3, // u32 >= 1, default 3 (1 = no retries)
backoff = "exponential", // "none" | "fixed" | "exponential", default "exponential"
delay = "1s", // fixed ONLY, required when backoff = "fixed"
base = "1s", // exponential ONLY, default "1s", must be <= max
factor = 2.0, // exponential ONLY, default 2.0, finite and > 0
max = "5m", // exponential ONLY, default "5m"
jitter = true, // exponential ONLY, default true
)

retry() with an empty body is accepted and uses every default.

Key Valid with Default
max_attempts every backoff 3
backoff "exponential"
delay backoff = "fixed" only, and required there
base backoff = "exponential" only "1s"
factor backoff = "exponential" only 2.0
max backoff = "exponential" only "5m"
jitter backoff = "exponential" only true

factor accepts a float, a plain integer (2) and a negative literal, though a negative one is then rejected by the range check.

An integer followed by ms, s, m, h or d; a bare integer means seconds. Full rules and the rejected forms are in Queue attributes.

Mistake Message
No queue key #[derive(Job)] requires `#[job(queue = MyQueues::Variant)]`
A single-segment queue path `queue` must be a path to an enum variant such as `AppQueues::Emails`
A generic job type generic job types are not supported
An unknown key lists queue, name, retry, crate
max_attempts = 0 `max_attempts` must be >= 1; 1 means no retries
An unknown backoff unknown backoff `linear`, expected "none", "fixed" or "exponential"
delay with a non-fixed backoff `delay` is only valid with `backoff = "fixed"`
backoff = "fixed" with no delay `backoff = "fixed"` requires `delay = "..."`
base, factor, max or jitter with a non-exponential backoff `<key>` is only valid with `backoff = "exponential"`
base greater than max `base` must be <= `max`, spanned at whichever of the two you wrote
A non-finite or non-positive factor `factor` must be a finite number greater than 0
delay = "0s" `delay` must be greater than zero: express "no backoff" as `backoff = "none"` instead
An unknown retry key lists max_attempts, backoff, delay, base, factor, max, jitter

The derive is what makes these three cases fail to compile. All are covered by compile-fail tests:

Attempt Error
Enqueueing a job from another queue set E0271 type mismatch on <J as Job>::Queue == Q
Registering a handler for a foreign job the same, on WorkerBuilder::handler
Wrapping a foreign job in FnHandler the same

See Jobs for the full error text.

pub trait Job: Serialize + DeserializeOwned + Send + Sync + 'static {
type Queue: QueueSet;
const NAME: &'static str;
const QUEUE: Self::Queue;
fn retry_policy() -> Option<RetryPolicy> { None }
}

retry_policy() is only generated when the attribute has a retry(...). Without it, the default None means “use the queue’s policy”.

Jobs, Retries and backoff, and queuey_core::job on docs.rs.