March Docs

Bastion.PubSub

lib/pubsub.march — In-process publish/subscribe for Bastion.

PubSub provides topic-based broadcast within a single node. It is the delivery layer for Channel broadcasts and any other real-time fan-out the framework or user code needs.

Subscriptions are stored in a Vault table keyed by "topic:sub_id". The value is the send_fn callback. To iterate all subs for a topic, we use Vault.all() and filter by the topic prefix.

── Usage ─────────────────────────────────────────────────────────────────────

-- Subscribe to a topic (typically done inside a WebSocket loop):
let sub_id = "conn:" ++ conn_id ++ ":" ++ topic
Bastion.PubSub.subscribe(topic, sub_id, fn event -> fn payload_json ->
  WebSocket.send_frame(ws, TextFrame(make_frame(topic, event, payload_json)))
)

-- Broadcast from a channel handler:
Bastion.PubSub.broadcast("room:42", "message:new", "{\"body\":\"hello\"}")

-- Broadcast excluding the sender:
Bastion.PubSub.broadcast_from(conn_id, "room:42", "typing", "{}")

Functions

fnbroadcastbroadcast(topic : String, event : String, payload_json : String)#

Broadcast an event to all subscribers of a topic.

    Bastion.PubSub.broadcast("room:42", "message:new", "{\"body\":\"hi\"}")
fnbroadcast_frombroadcast_from(exclude_sub_id : String, topic : String, event : String, payload_json : String)#

Broadcast an event to all subscribers of a topic, excluding one subscriber.

    Bastion.PubSub.broadcast_from(sub_id, "room:42", "typing:start", "{}")
fnhas_subscribershas_subscribers(topic : String) : Bool#

Return true if any subscriber is registered for a topic.

fnsubscribesubscribe(topic : String, sub_id : String, send_fn)#

Subscribe to a topic with a delivery callback.

sub_id    — unique string identifying this subscription (e.g. "conn:abc123:room:42")
send_fn   — fn(event)(payload_json) called on each broadcast to this topic

If sub_id is already subscribed, the old send_fn is replaced.
fnsubscriber_countsubscriber_count(topic : String) : Int#

Return the number of active subscribers for a topic.

fnunsubscribeunsubscribe(topic : String, sub_id : String)#

Unsubscribe from a topic. No-op if sub_id is not registered.

fnunsubscribe_allunsubscribe_all(conn_id : String)#

Remove all subscriptions held by a connection across every topic. Call this when a WebSocket connection closes to avoid stale send_fns.