Skip to main content

Attempts

On a subscription with a dead-letter policy a delivery reports its attempt number in the pubsub-delivery-attempt header.

Pub/Sub counts the deliveries of a message only where its subscription has a dead-letter policy. There each delivery carries the count, the first delivery being attempt 1, and the crate puts it in the header pubsub-delivery-attempt. A subscription without a policy reports no count, and the header is absent. A handler reads it with ctx.headers().get_str(DELIVERY_ATTEMPT_HEADER) and branches on it, for example to give a message up before the cap. The count is the service's estimate: it may miss a delivery, and it may start over from zero. The crate also reads it to tell the last allowed delivery, where drop nacks instead of acknowledging.

Example​

An order without stock waits through two redeliveries and is given up on the third attempt, before the cap of five.

/// Waits for stock through two redeliveries, then gives the order up on the third attempt.
#[subscriber(GooglePubSub::new("orders-workers").create_with_topic("orders"))]
async fn reserve(order: &Order, ctx: &mut Context<'_>) -> HandlerOutcome {
let attempt: u32 = ctx
.headers()
.get_str(DELIVERY_ATTEMPT_HEADER)
.and_then(|attempt| attempt.parse().ok())
.unwrap_or(1);
if order.in_stock {
return HandlerOutcome::ack();
}
if attempt >= 3 {
tracing::error!(order.id, attempt, "no stock, order given up");
return HandlerOutcome::drop();
}
tracing::warn!(order.id, attempt, "no stock yet");
HandlerOutcome::retry()
}