Nack All
Negative-acknowledge all queue messages for redelivery.
Overview
Bulk nack rejects an entire polled batch of queue messages in a single call instead of settling each one individually. It's the operation you reach for when a failure affects the whole batch at once — a downstream dependency is down, a shared resource lock couldn't be acquired, or a transient error means none of the messages can be processed right now — and retrying them one-by-one would just be extra round-trips for the same outcome.
It works with manual-ack polling: receiver.poll with auto_ack: false returns the batch over the downstream stream without settling it, and poll.nack_all() sends one batch NackAll settlement request that settles every message in that batch, returning them all to the queue for redelivery.
Gotchas: the receive count increments on every message in the batch, so an unbounded retry loop is one bad nack_all() away — pair it with a max-receive-count and a dead-letter policy. nack_all() is all-or-nothing: you can't use it to keep a few messages and reject the rest — that needs per-message settlement. And calling it on an empty batch is a wasted round-trip.
Prerequisites
- KubeMQ server running on
localhost:50000 - Rust SDK installed (
cargo add kubemq)
Code
use kubemq::prelude::*;
use kubemq::{PollRequest, QueueMessageBuilder};
#[tokio::main]
async fn main() -> kubemq::Result<()> {
let client = KubemqClient::builder()
.host("localhost")
.port(50000)
.build()
.await?;
let channel = "rust-queues.nack-all";
let msg = QueueMessageBuilder::new()
.channel(channel)
.body(b"nack-this".to_vec())
.build();
client.send_queue_message(msg).await?;
println!("Sent message to queue");
let mut receiver = client.new_queue_downstream_receiver().await?;
let poll = receiver.poll(PollRequest {
channel: channel.to_string(),
max_items: 10,
wait_timeout_seconds: 5,
auto_ack: false,
}).await?;
println!("Polled {} messages", poll.messages.len());
poll.nack_all().await?;
println!("Nacked all — messages returned to queue for redelivery");
receiver.close().await?;
client.close().await?;
Ok(())
}How It Works
new_queue_downstream_receiver()opens a persistent bidirectional gRPC stream for transactional polling.poll()withauto_ack: falsefetches messages without consuming them, leaving settlement to the caller.nack_all()sends a batchNackAllsettlement request over the stream, returning all messages to the queue so they can be redelivered.- Review timeouts, channel names, and client IDs before running against shared environments.
- Run the program while the server from the prerequisites is available.
Related
Was this page helpful?