# Send Command (/sdks/ruby/tutorials/command-send)



## Overview [#overview]

A **command** is KubeMQ's fire-and-confirm RPC pattern: you reach for it when you need to know that an action actually ran on the other end — "restart-service" — but you don't need any data back, just a yes/no on execution. It's the middle ground between one-way pub/sub, where you get no confirmation at all, and a query, where the handler returns a result payload. Commands turn "I hope that worked" into a definite outcome your caller can branch on.

This sample builds that lesson: `client.subscribe_to_commands(sub, ...)` registers the handler block, and `client.send_command(msg)` blocks until a response arrives or the `timeout` (in milliseconds) on `CommandMessage` expires. The handler builds its reply with `CommandResponseMessage.new(request_id: cmd.id, reply_channel: cmd.reply_channel, executed: true)` and sends it with `client.send_response` — that correlation is what routes the response back to the exact caller waiting on it.

**Gotchas:** if no handler is subscribed (or it's still starting up), `send_command` waits out the full `timeout` before failing — there's no fast "nobody's listening" error. A handler that omits `request_id`/`reply_channel` on the response leaves the caller hanging until timeout. And a command's response carries no business data — if you need the handler to return a value, use a query instead.

## 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-send'

begin
  client = KubeMQ::CQClient.new(address: address, client_id: 'cmd-sender')
  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 "Handler received command: #{cmd.metadata}"
    response = KubeMQ::CQ::CommandResponseMessage.new(
      request_id: cmd.id,
      reply_channel: cmd.reply_channel,
      executed: true
    )
    client.send_response(response)
  end
  sleep 1

  msg = KubeMQ::CQ::CommandMessage.new(
    channel: channel,
    timeout: 10_000,
    metadata: 'restart-service',
    body: 'service-name'
  )
  result = client.send_command(msg)
  puts "Command result: executed=#{result.executed}, error=#{result.error}"
rescue KubeMQ::Error => e
  puts "KubeMQ error: #{e.message}"
ensure
  cancel&.cancel
  client&.close
  puts 'Done'
end
```

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

* Commands follow a fire-and-confirm pattern — the handler processes and responds with execution status.
* The `timeout` field (in milliseconds) controls how long the sender waits for a response.
* The handler must call `send_response` with the matching `request_id` and `reply_channel`.
* 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)
* [Handle Command](/sdks/ruby/how-to/rpc/command-handle)
* [Command Timeout](/sdks/ruby/how-to/rpc/command-timeout)
