KubeMQ
Client SDKsRustHow-to guidesQueues

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

main.rs
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() with auto_ack: false fetches messages without consuming them, leaving settlement to the caller.
  • nack_all() sends a batch NackAll settlement 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.

Was this page helpful?

On this page