KubeMQ
Client SDKsNode.jsHow-to guidesRPC

Command Group

Load-balance KubeMQ commands across a group of handlers in Node.js so each command is processed by one available worker.

Overview

A command consumer group turns a single command handler into a scalable worker pool: run multiple identical processes subscribed with the same group name, and the broker load-balances each incoming command to exactly one member instead of broadcasting it to all of them. This is how you add capacity to handle a growing command volume — start more processes in the same group — without changing anything on the caller's side.

Every subscriber passes the same group alongside channel to subscribeToCommands(); the broker tracks membership and picks one live member per command. sendCommand on the caller side is unaware groups exist — it just awaits a response, which comes back from whichever handler happened to process it via sendCommandResponse.

Gotchas: group membership is scoped per channel — subscribers on the same channel with different group names each get their own full copy of every command (fan-out), which looks like a bug when you expected load-balancing. A slow handler still holds up the caller's timeout, since only one worker is ever picked. And if every member of the group is offline when a command arrives, the send simply fails or times out — commands aren't queued or replayed for a group that has no active listener.

Prerequisites

  • KubeMQ server running on localhost:50000
  • Node.js SDK installed (npm install kubemq-js)

Code

command-group.ts
import { KubeMQClient, createCommand } from 'kubemq-js';

async function main() {
  const client = await KubeMQClient.create({
    address: 'localhost:50000',
    clientId: 'js-rpc-command-group-client',
  });

  try {
    const sub = client.subscribeToCommands({
      channel: 'js-rpc.command-group',
      group: 'handlers',
      onCommand: async (cmd) => {
        console.log('Handler received command:', cmd.id);
        await client.sendCommandResponse({ id: cmd.id, replyChannel: cmd.replyChannel, executed: true });
      },
      onError: (err) => {
        console.error('Sub error:', err.message);
      },
    });

    await new Promise((r) => setTimeout(r, 500));
    const resp = await client.sendCommand(
      createCommand({ channel: 'js-rpc.command-group', body: 'do-work', timeoutInSeconds: 5 }),
    );
    console.log('Command executed:', resp.executed);

    sub.cancel();
  } finally {
    await client.close();
  }
}

main().catch(console.error);

How It Works

  • group: 'handlers' in subscribeToCommands() places this handler in the handlers consumer group; KubeMQ delivers each command to exactly one group member, enabling horizontal scaling.
  • The 500 ms setTimeout ensures the subscription is registered on the server before the sender issues the command — without it, the command may arrive before any handler is ready.
  • await client.sendCommandResponse(...) must be called from the onCommand callback before timeoutInSeconds elapses; the async (cmd) => ... signature ensures the await is properly chained.
  • To scale out, start multiple processes each subscribing with the same group name; KubeMQ round-robins commands across all active members.

Was this page helpful?

On this page