KubeMQ
Client SDKsRustHow-to guidesEvents

Multiple Subscribers

Fan out KubeMQ Events to multiple subscribers on the same channel so each receives every event, in Rust.

Overview

Fan-out delivery lets several independent consumers each get their own copy of every event published on a channel — the pattern behind broadcasting a notification to every connected service or feeding the same stream to a cache invalidator and a metrics collector at once. Reach for it whenever multiple, unrelated pieces of code all need to react to the same event, rather than compete for it.

It works by calling subscribe_to_events more than once for the same channel while passing an empty group string (""). Each call opens its own subscription, and the broker treats every subscriber with no group as broadcast: publishing one event delivers it to every open subscription — the opposite of a consumer group, where subscribers sharing a group name split events among themselves for load balancing.

Gotchas: Events pub/sub has no durability — a subscriber that hasn't finished subscribing yet, or that disconnects, simply misses events published in that window; there's no redelivery. Passing a non-empty group to one subscriber on the same channel silently turns broadcast into load-balancing for it. Both subscriptions here share one KubemqClient, so a fatal connection error affects every subscriber at once.

Prerequisites

  • KubeMQ server running on localhost:50000
  • Rust SDK installed (cargo add kubemq)

Code

main.rs
use kubemq::prelude::*;
use kubemq::EventBuilder;
use std::time::Duration;

#[tokio::main]
async fn main() -> kubemq::Result<()> {
    let client = KubemqClient::builder()
        .host("localhost")
        .port(50000)
        .build()
        .await?;

    let channel = "rust-events.multiple-subscribers";

    let sub1 = client
        .subscribe_to_events(
            channel,
            "",
            |event| {
                Box::pin(async move {
                    println!(
                        "Subscriber-1 received: body={}",
                        String::from_utf8_lossy(&event.body)
                    );
                })
            },
            None,
        )
        .await?;

    let sub2 = client
        .subscribe_to_events(
            channel,
            "",
            |event| {
                Box::pin(async move {
                    println!(
                        "Subscriber-2 received: body={}",
                        String::from_utf8_lossy(&event.body)
                    );
                })
            },
            None,
        )
        .await?;

    tokio::time::sleep(Duration::from_millis(500)).await;

    let event = EventBuilder::new()
        .channel(channel)
        .body(b"broadcast-message".to_vec())
        .build();
    client.send_event(event).await?;
    println!("Event published to channel: {}", channel);

    tokio::time::sleep(Duration::from_secs(2)).await;

    sub1.unsubscribe().await;
    sub2.unsubscribe().await;
    client.close().await?;
    Ok(())
}

How It Works

  • Both subscribers use an empty group "", so each receives every event (fan-out).
  • This is the default delivery mode — contrast with Consumer Group for load-balancing.
  • Review timeouts, channel names, and client IDs before running against shared environments.
  • Run the program while the server from the prerequisites is available.

Was this page helpful?

On this page