Skip to content

queuey

Queues are declared as an enum, jobs as structs, and derive macros wire them together so a job can only be enqueued to, or consumed from, the queue it statically belongs to. Cross-application mix-ups do not compile.

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Queues)]
#[queues(prefix = "myapp")]
enum AppQueues {
#[queue(prefetch = 10)]
Emails,
#[queue(retry(max_attempts = 3, backoff = "exponential", base = "1s", max = "2m"))]
Images,
}
#[derive(Debug, Serialize, Deserialize, Job)]
#[job(queue = AppQueues::Emails, retry(max_attempts = 5))]
struct SendEmail { to: String, body: String }

Compile-time queue binding

#[derive(Job)] ties a job to one queue set. Producer<Q, _> and Worker<Q, _> are generic over that set, so enqueueing another application’s job is a type error rather than a message that quietly lands on the wrong queue.

Retries you configure once

Exponential backoff with base, factor, cap and full jitter; fixed delay; or none at all. Set per queue, overridden per job, all in the attribute.

Fatal and retryable failures

A handler says which kind of failure it hit. Retryable goes through the policy, fatal goes straight to the dead-letter queue.

Deferral for rate limits

A job that cannot run yet is not a job that failed. It waits exactly as long as the API asks, comes back ahead of the backlog, and spends no attempt doing it.

An in-memory backend

MemoryBackend runs the whole stack with no broker, honours delays through tokio::time so tests can use paused virtual time, and exposes what it saw for assertions.

Graceful shutdown

Stop consuming, finish what was already pulled, await what is in flight. Nothing is pulled and then discarded.

If you want to understand the design rather than the API, read Deferral and Broker topology first. They are where the interesting decisions are.

If you are looking for exhaustive signatures, this site is the narrative layer; docs.rs/queuey is the complete one.

Reconnection is out of scope. When the connection to the broker drops, consumer streams end and Worker::run returns an error. Supervise the process and let it restart.

Hold-queue arguments are not configurable. They follow from the queue name alone, so every process declares them identically and no two processes can deadlock each other with PRECONDITION_FAILED.

Version 0.2.0
License MIT OR Apache-2.0
Rust edition 2024
Minimum supported Rust 1.88
Unsafe code #![forbid(unsafe_code)] on every crate
Repository github.com/jaapieaapie1/queuey
Crate Role
queuey Facade: prelude, re-exports, examples
queuey-core Traits, Producer, Worker, retry policies, MemoryBackend
queuey-macros #[derive(Queues)], #[derive(Job)]
queuey-rabbitmq RabbitMqBackend on lapin