ack_wait
ack_wait is how long the server waits for a settlement; a delivery left unsettled comes back after it and counts as an attempt.
It is a setting of the consumer, so JetStreamSubject carries it, and the server keeps it with the consumer it creates at startup.
The default is 30 seconds.
The window opens when the server hands out a delivery and closes when the handler's outcome reaches it as an acknowledgement.
A delivery still unsettled at the end of the window is delivered again: the handler took longer than the window, or the process stopped before it settled.
The handler then sees the same message a second time, with its delivery count raised, while the first run may still be going on.
So the window is set longer than the slowest run of the handler.
A redelivery after the window counts toward max_attempts, because the count is the server's own.
The value is a NonZeroDuration: a literal written with nonzero! is checked while the crate compiles, so a window of zero does not build.
Example
Rendering a long invoice takes up to a minute, so the consumer waits two minutes for the settlement.
- Macros
- Manual
/// Rendering a long invoice takes up to a minute, so the consumer waits two minutes for the
/// settlement before it delivers the request again.
#[subscriber(
JetStreamSubject::new("billing.requested", "BILLING_REQUESTS")
.durable("invoicer")
.ack_wait(NonZeroDuration::from_secs(nonzero!(120)))
)]
async fn render(invoice: &Invoice) -> HandlerOutcome {
match render_pdf(invoice).await {
Ok(pages) => {
tracing::info!(invoice.id, pages, "invoice rendered");
HandlerOutcome::ack()
}
Err(err) => {
tracing::warn!(invoice.id, %err, "invoice not rendered");
HandlerOutcome::drop()
}
}
}
/// Rendering a long invoice takes up to a minute, so the consumer waits two minutes for the
/// settlement before it delivers the request again.
fn invoices() -> JetStreamSubject {
JetStreamSubject::new("billing.requested", "BILLING_REQUESTS")
.durable("invoicer")
.ack_wait(NonZeroDuration::from_secs(nonzero!(120)))
}
struct Render;
impl Handle<Invoice> for Render {
async fn handle(
&self,
invoice: &Invoice,
_outs: &(),
_ctx: &mut Context<'_>,
) -> Result<(), HandlerOutcome> {
match render_pdf(invoice).await {
Ok(pages) => {
tracing::info!(invoice.id, pages, "invoice rendered");
Ok(())
}
Err(err) => {
tracing::warn!(invoice.id, %err, "invoice not rendered");
Err(HandlerOutcome::drop())
}
}
}
}