Skip to main content

retry_after

retry_after(delay) asks for the delivery back no sooner than the delay, for a condition that will pass.

It is one of the outcomes, next to an immediate retry(). A broker with native delayed redelivery holds the delivery and returns it after the delay. The in-memory broker is one: the delivery comes back to the same subscriber, and nothing is published. On a broker without it, the runtime drops the delivery and publishes a copy back to the subscription after the delay, through the Retry slot. That copy carries the RETRY_COUNT_HEADER (x-ruststream-retry-count), incremented on every copy. The copy is at most once over the delay: a process that exits before the timer fires loses it. A graceful shutdown waits for pending copies within the app's shutdown_timeout. A zero delay redelivers at once, as retry() does; write retry() when no delay is meant. A batch body sets a delay per element, and only those elements come back. A test runs on a paused clock (#[tokio::test(start_paused = true)]), and tb.advance(delay) brings the delivery back, as the advance page shows. How many times a delivery may come back is the registration's declaration, max_attempts.

Example​

const RECHECK: Duration = Duration::from_secs(5);

#[subscriber("payments")]
async fn reconcile(
payment: &Payment,
ctx: &mut Context<'_, (), Arc<Ledger>>,
) -> HandlerOutcome {
if !ctx.state().is_cleared(payment.id) {
// The bank has not cleared it yet: an immediate redelivery would only spin.
return HandlerOutcome::retry_after(RECHECK);
}
tracing::info!(payment.id, "reconciled");
HandlerOutcome::ack()
}

Per element of a batch​

const RECHECK: Duration = Duration::from_secs(30);

/// One outcome per element: a cleared payment is acked, a pending one alone comes back.
#[subscriber("payments")]
async fn reconcile(
payments: &[Payment],
ctx: &mut Context<'_, (), Arc<Ledger>>,
) -> Vec<HandlerOutcome> {
payments
.iter()
.map(|payment| {
if ctx.state().is_cleared(payment.id) {
HandlerOutcome::ack()
} else {
HandlerOutcome::retry_after(RECHECK)
}
})
.collect()
}