KubeMQ
Client SDKsRubyHow-to guidesQueues

Delayed Messages

Send KubeMQ queue messages with a delivery delay in Ruby so consumers receive them only after the specified time elapses.

Which to use

This is the task-oriented guide for sending delayed messages — send one with a delivery delay, confirm it's hidden, then receive it once the delay expires. For the QueueMessagePolicy / delay_seconds object reference, see Delay Policy.

Overview

A delivery delay holds a queue message out of consumers' reach for a fixed window after it's sent — the message is accepted and persisted immediately, but invisible to pollers until the delay expires. It's the building block for scheduled work — a reminder to fire in an hour, a retry with back-off, a task queued for off-peak processing — without standing up a separate scheduler or cron service.

Set it with delay_seconds on QueueMessagePolicy before sending; the broker does the waiting. A poll via the downstream receiver against the channel before the delay elapses simply returns zero messages — it isn't hidden in a separate place, it's the same queue, just not yet eligible for delivery. Once the delay window passes, the next poll retrieves it normally.

Gotchas: the delay is set once at send time, per message, and can't be extended or shortened afterward — if you need a different wait, send a new message. A long delay still counts as an in-flight, persisted message, so it survives a broker restart, but it also occupies queue storage for the whole waiting period. Don't confuse this with a visibility timeout after delivery — that's a separate mechanism for redelivery on failed acknowledgment, not initial availability.

Prerequisites

  • KubeMQ server running on localhost:50000
  • Ruby SDK installed (gem install kubemq)

Code

main.rb
require 'kubemq'

address = ENV.fetch('KUBEMQ_ADDRESS', 'localhost:50000')
channel = 'ruby-queues.delayed-messages'

begin
  client = KubeMQ::QueuesClient.new(address: address, client_id: 'qstream-delay-example')
  puts "Connected to #{address}"

  policy = KubeMQ::Queues::QueueMessagePolicy.new(delay_seconds: 3)
  msg = KubeMQ::Queues::QueueMessage.new(
    channel: channel,
    metadata: 'delayed-3s',
    body: 'process-later',
    policy: policy
  )
  result = client.send_queue_message(msg)
  puts "Sent message with delay=3s: id=#{result.id}"

  receiver = client.create_downstream_receiver
  request = KubeMQ::Queues::QueuePollRequest.new(channel: channel, max_items: 1, wait_timeout: 1)
  response = receiver.poll(request)
  puts "Immediate poll: #{response.messages.size} messages (should be 0)"

  puts 'Waiting for delay to expire...'
  sleep 4

  response2 = receiver.poll(request)
  puts "After delay: #{response2.messages.size} message(s)"
  response2.messages.each do |m|
    puts "  #{m.metadata}: #{m.body}"
    m.ack
  end
rescue KubeMQ::Error => e
  puts "KubeMQ error: #{e.message}"
ensure
  receiver&.close
  client&.close
  puts 'Done'
end

How It Works

  • delay_seconds in QueueMessagePolicy makes the message invisible until the delay expires.
  • Polling before the delay returns no messages.
  • Review timeouts, channel names, and client IDs before running against shared environments.

Was this page helpful?

On this page