KubeMQ
Client SDKsC#How-to guidesRPC

Command Timeout

Handle KubeMQ command execution timeouts gracefully using the C# SDK RPC client.

Overview

A command timeout is the deadline you attach to a single RPC call so a caller never blocks forever waiting on a handler that isn't there or isn't responding. Commands are synchronous by design — the sender is parked until a reply arrives — so without a bound, a missing subscriber or a crashed handler turns one request into an indefinite hang that ties up an awaited task and cascades into upstream timeouts.

The timeout is set per call with TimeoutInSeconds on CommandMessage, and it's enforced by the broker itself, not by client-side polling: the broker tracks the deadline server-side and fails the request the moment it expires, regardless of what the calling task is doing. When the window elapses with no response, SendCommandAsync throws a KubeMQTimeoutException — a specific exception type that's your signal to retry or fall back.

Gotchas: a slow-but-alive handler and a completely absent one produce the same timeout behavior, so you can't tell them apart from the exception alone; setting TimeoutInSeconds too short under normal load turns transient latency into false failures; and command/query calls are not retried on timeout (they're non-idempotent), so a KubeMQTimeoutException here means the SDK gave up after this one attempt, not after a hidden retry loop.

Prerequisites

  • KubeMQ server running on localhost:50000
  • C# SDK installed (dotnet add package KubeMQ.SDK.CSharp)

Code

Program.cs
// KubeMQ .NET SDK — Commands: Timeout Handling
//
// This example demonstrates how command timeouts work. A command is sent with
// a short timeout and no handler is running, so it times out. The SDK surfaces
// this as a KubeMQTimeoutException.
//
// Prerequisites:
//   - KubeMQ server running on localhost:50000
//   - Do NOT start a command handler — this example expects a timeout
//   - dotnet run

using KubeMQ.Sdk.Client;
using KubeMQ.Sdk.Commands;
using KubeMQ.Sdk.Exceptions;
using System.Text;

await using var client = new KubeMQClient(new KubeMQClientOptions
{
    Address = "localhost:50000",
    ClientId = "csharp-commands-command-timeout-client",
});
await client.ConnectAsync();
Console.WriteLine("Connected to KubeMQ server");

int[] timeouts = [2, 5];

foreach (var timeout in timeouts)
{
    Console.WriteLine($"\nSending command with {timeout}s timeout (no handler running)...");
    try
    {
        var response = await client.SendCommandAsync(new CommandMessage
        {
            Channel = "csharp-commands.command-timeout",
            Body = Encoding.UTF8.GetBytes($"action-with-{timeout}s-timeout"),
            TimeoutInSeconds = timeout,
        });

        Console.WriteLine($"  Executed: {response.Executed}");
        if (!string.IsNullOrEmpty(response.Error))
        {
            Console.WriteLine($"  Error: {response.Error}");
        }
    }
    catch (KubeMQTimeoutException ex)
    {
        Console.WriteLine($"  Caught KubeMQTimeoutException: {ex.Message}");
    }
    catch (KubeMQException ex)
    {
        Console.WriteLine($"  Caught KubeMQException: {ex.Message}");
    }
}

Console.WriteLine("\nDone.");

How It Works

  • No handler is running for this channel, so both commands time out as expected. The first command waits 2 seconds; the second waits 5 seconds.
  • A timed-out command or query always raises KubeMQTimeoutException — the second catch (KubeMQException) is a defensive fallback for other operation errors (e.g. validation), not an alternate timeout path.
  • TimeoutInSeconds is the maximum time the broker waits for a handler to respond. Set it based on the expected processing time of your handler plus network latency.
  • To test successful command execution, start the Handle Command example in a separate terminal before running this program.

Was this page helpful?

On this page