Ниже показан английский оригинал.
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.
- Macros
- Manual
/// 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()
}
/// Waits for stock through two redeliveries, then gives the order up on the third attempt.
struct Reserve;
impl Handle<Order> for Reserve {
fn handle(
&self,
order: &Order,
_outs: &(),
ctx: &mut Context<'_>,
) -> impl Future<Output = Result<(), 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 ready(Ok(()));
}
if attempt >= 3 {
tracing::error!(order.id, attempt, "no stock, order given up");
return ready(Err(HandlerOutcome::drop()));
}
tracing::warn!(order.id, attempt, "no stock yet");
ready(Err(HandlerOutcome::retry()))
}
}