queue worker decouples producers from consumers: a function publishes a message to a named
topic and returns right away, and any function subscribed to that topic processes the message in the
background, with retries and a dead-letter queue (DLQ) for messages that keep failing.
Before adding the worker
compose::add is served by a running Compose daemon. Keep the engine and a daemon for this project
running in separate terminals before using any of the commands below. If this project does not have
a Compose file yet, create worker-compose.yaml containing containers: {} first.
iii compose is an intentional verbless daemon invocation, documented in the
CLI reference. The -n used below is the short form of
--namespace for iii trigger.
Run the remaining commands from a third terminal in that same project directory:
This page covers common queue patterns. For the complete configuration and trigger API, see the
queue worker docs.
Named Queues
When you need to control function execution for time consuming operations, or guarantee a certain number of retries then you can useTriggerAction.Enqueue to place that operation into a queue.
Creating a Queue
Create a named queue calledemail-jobs by following the
queue worker configuration reference, then use that name
when enqueueing functions below. The worker reference owns the accepted fields, defaults, and FIFO
options.
Enqueue functions
Enqueued functions are registered the same as any other call toworker.trigger with the one
difference being providing an action called TriggerAction.Enqueue to the trigger:
- Node / TypeScript
- Python
- Rust
Pub/Sub Queues
Queues can also be used in a publish/subscribe form when multiple listeners need to subscribe to the same data and it’s important that the messages be durable (ie. will succeed).Consuming messages
A consumer can bind to a message by registering a Trigger fordurable:subscriber trigger to it.
The engine runs the function once per message, passing the published data as the payload.
Returning normally acknowledges the message; throwing nacks it, so it is retried and eventually
dead-lettered.
In a worker, register the consumer function and subscribe it to the topic. If you do not have a
worker yet, follow Create a new worker, then edit its source:
- Node / TypeScript
- Python
- Rust
Publishing a message
With the consumer running, publish to its topic. The engine delivers thedata to every subscriber,
so email::send runs once per message:
Retries and delivery
The examples use thetopic to choose what to consume and queue_config to tune delivery for
one subscriber. See the
durable:subscriber reference for the complete trigger
schema, including filtering and adapter-specific options.
A failed delivery retries with exponential backoff (1 second, then 2 seconds) for up to 3 attempts,
then the message dead-letters.
Each subscriber’s durable queue is scoped by the subscribing worker’s namespace, so two subscribers
of the same topic and function id in different namespaces are two queues that each receive every
published event, rather than two competing consumers of one queue.
For example, to process messages strictly one at a time instead of concurrently, register the
trigger with a fifo queue:
- Node / TypeScript
- Python
- Rust
Inspecting Queue Topics
These commands list both kinds of queue. A pub/sub topic appears once a function subscribes to it, and showsbroker_type: "builtin". (Publishing to a topic that nothing subscribes to does not
register it, so there is nothing to inspect.) A configured named queue appears with
broker_type: "function_queue".
List every topic (this inspects the emails topic from above):
depth is messages waiting for the consumer, dlq_depth is
dead-lettered). A topic whose consumer keeps up sits at depth: 0. For a named queue,
consumer_count reports its active delivery slots:
Inspecting Dead Letter Queue Messages
A message reaches the dead-letter queue only once its subscribed function exhausts its retries, so the DLQ functions return empty until something fails.Forcing a message into the dead-letter queue
To see the DLQ populated, makeemail::send fail by changing the handler to throw. Each message
then fails its 3 delivery attempts (a few seconds with the exponential backoff) and dead-letters.
- Node / TypeScript
- Python
- Rust
Listing topics with dead-lettered messages
Browsing dead-lettered messages
Redriving dead-lettered messages
Fix the code back to what it was originally, then move the topic’s dead-lettered messages back to the main queue for reprocessing:Redriving or discarding a single message
To handle one message instead of the whole topic, pass theid from engine::queue::dlq_messages.
Redrive one message back to the main queue: