# Handle Query (/sdks/ruby/how-to/rpc/query-handle)



## Overview [#overview]

A query handler is the answering side of KubeMQ's request/response RPC pattern — the code that does real work and sends back data, unlike a Command handler, which only acknowledges receipt. Reach for it whenever a caller needs an actual answer — a lookup result, a computed value, a status object — not just confirmation that a message arrived.

Registering a handler with `subscribe_to_queries` opens a subscription; the broker delivers every matching query to your block as it arrives. The block builds a `QueryResponseMessage` carrying the original query's correlation id (`request_id`/`reply_channel`) back to the broker, so the answer routes to the specific caller blocked waiting, and sets `body` with the real result before calling `send_response`.

**Gotchas:** if the handler never sends a response, the caller blocks until its own timeout elapses and fails with a timeout, not a fast error. An exception inside the block doesn't automatically become a failure reply, so uncaught errors can leave the sender hanging. And because every matching query lands on the same background thread, slow handler code delays every other in-flight caller.

## 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-rpc.query-handle'

begin
  client = KubeMQ::CQClient.new(address: address, client_id: 'query-handler')
  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 "Received query: id=#{query.id}, metadata=#{query.metadata}"

    response = KubeMQ::CQ::QueryResponseMessage.new(
      request_id: query.id,
      reply_channel: query.reply_channel,
      executed: true,
      body: "response-to-#{query.metadata}",
      metadata: 'query-result'
    )
    client.send_response(response)
    puts "Sent response for query #{query.id}"
  end

  puts "Listening for queries on '#{channel}'. Press Ctrl+C to stop."
  cancel.wait
rescue Interrupt
  puts "\nShutting down..."
rescue KubeMQ::Error => e
  puts "KubeMQ error: #{e.message}"
ensure
  cancel&.cancel
  client&.close
  puts 'Done'
end
```

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

* `subscribe_to_queries` delivers incoming queries to the block on a background thread.
* The handler must call `send_response` for each query with data in the `body` and `metadata`.
* Review timeouts, channel names, and client IDs before running against shared environments.

## Related [#related]

* [Pattern overview](/learn/rpc/getting-started)
* [Ruby SDK Reference](/sdks/ruby/reference)
* [Send Query](/sdks/ruby/tutorials/query-send)
* [Cached Query](/sdks/ruby/how-to/rpc/query-cached)
