# Request-Reply (/sdks/ruby/how-to/request-reply)



## Overview [#overview]

Request-reply gives you synchronous RPC on top of KubeMQ's messaging fabric: a caller sends a query and blocks until the handler actually processing the request sends back a real answer — not just an acknowledgment. Reach for it whenever the caller needs a return value to proceed — a lookup, a computed result, a status check — the same shape as an HTTP call, but routed by KubeMQ instead of a service mesh or DNS.

A handler block passed to `subscribe_to_queries` builds a `QueryResponseMessage` with `request_id: query.id` and `reply_channel: query.reply_channel` before calling `send_response` — copying those fields is what lets KubeMQ route the response to the one caller waiting, not broadcast it. The caller's `send_query` blocks until that reply arrives or its `timeout` elapses, returning a result with a `body`.

**Gotchas:** if no subscriber is listening — or the handler crashes before replying — `send_query` simply times out; there's no way to distinguish "no handler" from "handler is slow" from the timeout alone. `request_id` and `reply_channel` must echo back the incoming query's values unchanged, or the reply is silently dropped or misrouted. If you don't actually need a return value, use commands instead — they only need an ack, so they don't tie up a caller waiting on a round trip.

## Prerequisites [#prerequisites]

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

## Code [#code]

```ruby title="main.rb"
require 'kubemq'

address = ENV.fetch('KUBEMQ_ADDRESS', 'localhost:50000')
channel = 'ruby-patterns.request-reply'

begin
  client = KubeMQ::CQClient.new(address: address, client_id: 'rpc-pattern-example')
  puts "Connected to #{address}"

  cancel = KubeMQ::CancellationToken.new

  sub = KubeMQ::CQ::QueriesSubscription.new(channel: channel)
  client.subscribe_to_queries(sub, cancellation_token: cancel, on_error: ->(e) { puts "Error: #{e.message}" }) do |query|
    puts "Handler received query: #{query.metadata}"
    response = KubeMQ::CQ::QueryResponseMessage.new(
      request_id: query.id,
      reply_channel: query.reply_channel,
      executed: true,
      body: "answer-to-#{query.metadata}"
    )
    client.send_response(response)
  end
  sleep 1

  %w[get-user get-settings].each do |action|
    msg = KubeMQ::CQ::QueryMessage.new(channel: channel, timeout: 10_000, metadata: action, body: 'request')
    result = client.send_query(msg)
    puts "Reply: #{result.body}"
  end
rescue KubeMQ::Error => e
  puts "KubeMQ error: #{e.message}"
ensure
  cancel&.cancel
  client&.close
  puts 'Done'
end
```

## How It Works [#how-it-works]

* The request-reply pattern uses queries for synchronous RPC with data responses.
* The server subscribes and responds; the client sends queries and receives replies.
* Review timeouts, channel names, and client IDs before running against shared environments.

## Related [#related]

* [Ruby SDK Reference](/sdks/ruby/reference)
* [Send Query](/sdks/ruby/tutorials/query-send)
* [Work Queue](/sdks/ruby/how-to/work-queue)
