Channels

Publish messages to named topics and push them to browsers over SSE or WebSocket with channels::Hub.

A channels::Hub holds named topics. Pages subscribe to a topic over SSE or WebSocket; server code publishes to it — "a comment was added", "the import finished" (18.35.0):

use rust_web_server::app::App;
use rust_web_server::channels::Hub;

let hub = Hub::new();
let app = App::with_state(State { hub: hub.clone(), db })
    // EventSource("/posts/7/events").addEventListener("post-7", …)
    .get("/posts/:id/events", |_, params, _, state| {
        state.hub.sse(&format!("post-{}", params.get("id").unwrap_or("")))
    })
    // A chat room: every client gets what any of them sends.
    .websocket("/rooms/:room", |ws, params, state| {
        let room = params.get("room").unwrap_or("lobby").to_string();
        state.hub.serve_websocket(ws, &room, |hub, room, text| { hub.publish(room, text); });
    })
    .post("/posts/:id/comments", |request, params, _, state| {
        // … save the comment …
        state.hub.publish(&format!("post-{}", params.get("id").unwrap_or("")), "comment added");
        Response::text(STATUS_CODE_REASON_PHRASE.n201_created, "ok")
    });
Method What it does
publish(topic, message) Sends to every subscriber; returns how many it reached. SSE clients get an event named after the topic, WebSocket clients a text message
sse(topic) A streaming SSE response subscribed to topic — return it from the handler
serve_websocket(ws, topic, on_message) Subscribes a WebSocket connection and reads it until it closes, calling on_message(hub, topic, text) for each text message
subscribe_websocket(topic, sender) Subscribes a WebSocketSender you manage yourself
subscribe(topic) An in-process Receiver<String> (a worker thread, a test)
subscribers(topic), topics() What's subscribed

A Hub is cheap to clone; all clones share the topics. Delivery is best effort: a message that doesn't fit a slow SSE client's buffer is dropped for that client, and clients that have gone away are removed on the next publish to their topic. WebSocket messages are written by the publishing thread.

Channels are in-process: each replica has its own subscribers. Behind several replicas, publish where every replica hears it — consume a queue (Kafka, Redis) in each and call publish from there.

Last updated · Edit this page on GitHub · Markdown