# Handle Command (/sdks/ruby/how-to/rpc/command-handle)



## Overview [#overview]

A **command handler** is the receiving side of KubeMQ's Commands pattern — the code that actually does the work a caller is blocked waiting on. Instead of building your own request-routing layer on top of a queue, you register a handler once with `subscribe_to_commands`, and KubeMQ delivers every matching command on that channel to it as a long-lived subscription running on a background thread, turning the channel into a synchronous RPC endpoint.

Handling happens inside the block: you read the command's `id`, `metadata`, and `body`, run your business logic, then build a reply with `KubeMQ::CQ::CommandResponseMessage.new(request_id: cmd.id, reply_channel: cmd.reply_channel, executed: ...)` and send it with `send_response`. Copying `request_id` and `reply_channel` from the received command is what lets the broker correlate the reply back to the exact caller blocked on the send — nothing else identifies which request the response belongs to.

**Gotchas:** you must call `send_response` for every command or the sender times out waiting; the block runs on the subscription's background thread, so slow or blocking business logic head-of-line blocks the next command; and `cancel.wait` only unblocks the main thread — it doesn't stop the handler thread, which is why cleanup happens in `ensure`.

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

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

  cancel = KubeMQ::CancellationToken.new

  sub = KubeMQ::CQ::CommandsSubscription.new(channel: channel)
  client.subscribe_to_commands(sub, cancellation_token: cancel, on_error: ->(e) { puts "Error: #{e.message}" }) do |cmd|
    puts "Received command: id=#{cmd.id}, metadata=#{cmd.metadata}, body=#{cmd.body}"

    executed = cmd.metadata != 'fail'
    response = KubeMQ::CQ::CommandResponseMessage.new(
      request_id: cmd.id,
      reply_channel: cmd.reply_channel,
      executed: executed,
      error: executed ? nil : 'Simulated failure'
    )
    client.send_response(response)
    puts "Sent response: executed=#{executed}"
  end

  puts "Listening for commands 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_commands` runs a background thread that delivers incoming commands to the block.
* The handler must call `send_response` for each command — otherwise the sender times out.
* `cancel.wait` blocks the main thread until the token is cancelled (e.g., by Ctrl+C).
* 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 Command](/sdks/ruby/tutorials/command-send)
* [Command Group](/sdks/ruby/how-to/rpc/command-group)
