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
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'
endHow It Works
delay_secondsinQueueMessagePolicymakes 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.
Related
Was this page helpful?