下面显示的是英文原文。
Dead letters
dead_letter(subject) names the subject a spent delivery is published to; a capped JetStream consumer with none terminates it.
It follows max_attempts(n) at the mount site.
When a retry would make the delivery the n-th one, the framework settles it and publishes it to the dead-letter subject instead, payload and headers as they arrived.
On a JetStream consumer the delivery is then terminated, so the server delivers it no more.
NATS has no dead-letter mechanism of its own, so the same path serves both models, and a warning names the subscription that gave up.
The copy carries RETRY_COUNT_HEADER: on a Core subject it says how many deliveries the message had; on a JetStream consumer the server counted them, and the header reads 1.
A cap without a dead-letter subject terminates the spent JetStream delivery, and ends the Core one.
The dead-letter subject is an ordinary subject: a subscription of this service or of another one reads it.
It stays outside every pattern a subscription of the service reads, or the spent message arrives back at a handler.
Example
The dead-letter subject is read by an ordinary subscription.
- Macros
- Manual
/// The dead-letter subject is read by an ordinary subscription. The retry-count header says how
/// many deliveries the payment had before it was carried here.
#[subscriber("payments.dead")]
async fn on_dead_letter(payment: &Payment, ctx: &mut Context<'_>) -> HandlerOutcome {
let deliveries = ctx.headers().get_str(RETRY_COUNT_HEADER).unwrap_or("1");
tracing::error!(payment.id, deliveries, "payment dead-lettered");
HandlerOutcome::ack()
}
/// The dead-letter subject is read by an ordinary subscription. The retry-count header says how
/// many deliveries the payment had before it was carried here.
struct OnDeadLetter;
impl Handle<Payment> for OnDeadLetter {
fn handle(
&self,
payment: &Payment,
_outs: &(),
ctx: &mut Context<'_>,
) -> impl Future<Output = Result<(), HandlerOutcome>> {
let deliveries = ctx.headers().get_str(RETRY_COUNT_HEADER).unwrap_or("1");
tracing::error!(payment.id, deliveries, "payment dead-lettered");
ready(Ok(()))
}
}