跳到主要内容
本页尚未翻译

下面显示的是英文原文。

Dead letters

dead_letter(name) names where a spent delivery goes; on ZeroMQ that is a publisher on another endpoint, because a name on the own one stays home.

When a retry would go past the cap of max_attempts, the runtime publishes the delivery under the dead-letter name instead, payload and headers as they arrived. A mount with a dead-letter name and no cap sends every failed delivery there at once. A cap with no dead-letter name drops the spent delivery with a warning naming the subscription.

A name is frame 0, not an address, and the dead letter leaves through the retry publisher. On the subscription's own bound queue that publisher refuses jobs.dead with ZmqError::Send, and the delivery is dropped with a warning. On the subscription's own bound fan-out jobs.dead matches the prefix jobs and comes back to the subscription that gave up on it.

So a dead letter leaves through a publisher on another endpoint, set with .out_retry(..). The retry copies leave through that publisher as well, so such a mount sends every failed delivery to the dead letters, with no retry first. A handler that should see its retries again keeps .out_retry(..) on its own endpoint and declares no dead-letter name.

Retries and dead letters parks failed invoices on a queue of their own.

Example​

A job that fails leaves for a second queue the service binds, where park reads it under jobs.dead.

#[ruststream::app]
fn app() -> impl App {
let dead = ZmqQueue::new(ZmqEndpoint::bind("tcp://0.0.0.0:5561")).bindable();
let parked = dead.bind(Publish);
RustStream::new(AppInfo::new("worker", "0.1.0"))
.with_broker_labeled(
"worker",
ZmqQueue::new(ZmqEndpoint::bind("tcp://0.0.0.0:5555")),
|b| {
// Every failed job leaves for the second queue, under the name it is read by.
b.include(work).dead_letter("jobs.dead").out_retry(parked);
},
)
.with_broker_labeled("dead", dead, |b| {
b.include(park);
})
}