KubeMQ
Client SDKsElixirHow-to guidesQueues

Ack Range

Selectively acknowledge specific messages by sequence.

Overview

A single poll response often bundles several messages into one batch, but "successfully processed" rarely applies to all of them uniformly — one handler might fail while its siblings succeed. Settling the whole batch together forces an all-or-nothing outcome: either you redeliver work you already finished, or you silently drop work you didn't. Range acknowledgment lets you settle exactly the subset that actually succeeded, in one call.

KubeMQ.PollResponse.ack_range/2 takes the poll response and a list of broker-assigned sequence numbers — read from each message's attributes.sequence — and acknowledges all of them together. Any sequence you leave out of the list is left unsettled and returns to the queue for redelivery once the visibility window expires.

Gotchas: the sequences you pass must be numbers your handler actually received in that poll — passing a stale or unknown sequence isn't a safe no-op you can rely on. Messages you never include in any ack_range call aren't implicitly skipped forever; they come back for redelivery once the timeout elapses, so forgetting to settle a message isn't "done," it's "will retry." And selective settlement only works when the poll isn't using auto-ack — with auto-ack on, the broker settles the whole batch the moment it's delivered.

Prerequisites

  • KubeMQ server running on localhost:50000
  • Elixir SDK installed ({:kubemq, "~> 1.0"} in mix.exs)

Code

main.exs
channel = "elixir-queues.ack-range"
{:ok, client} = KubeMQ.Client.start_link(address: "localhost:50000", client_id: "elixir-qs-ackrange")

for i <- 1..5 do
  {:ok, _} = KubeMQ.Client.send_queue_message(client,
    KubeMQ.QueueMessage.new(channel: channel, body: "Message #{i}"))
end

IO.puts("Sent 5 messages")

case KubeMQ.Client.poll_queue(client,
       channel: channel,
       max_items: 5,
       wait_timeout: 5_000
     ) do
  {:ok, poll} ->
    IO.puts("Polled #{length(poll.messages)} messages")

    sequences =
      poll.messages
      |> Enum.filter(& &1.attributes)
      |> Enum.map(& &1.attributes.sequence)

    ack_seqs = Enum.take(sequences, 3)
    IO.puts("Acking sequences: #{inspect(ack_seqs)}")

    case KubeMQ.PollResponse.ack_range(poll, ack_seqs) do
      :ok -> IO.puts("Range ack successful!")
      {:error, err} -> IO.puts("Ack range failed: #{err.message}")
    end

  {:error, err} ->
    IO.puts("Poll failed: #{err.message}")
end

KubeMQ.Client.close(client)

How It Works

  • PollResponse.ack_range/2 acknowledges only the specified sequence numbers
  • Unacknowledged messages remain in the queue for later processing
  • Sequence numbers are available via message.attributes.sequence

Was this page helpful?

On this page