hecate_pubsub_server (macula v10.21.0)
View SourcePubSub gen_server wrapping hecate_pubsub state for one realm namespace.
Activates the dormant hecate_pubsub pure-state module by giving it a process identity. One server instance owns the topic-to-subscriber index for a single realm tag; the realm is an opaque 32-byte namespace key, not validated against any authority. Multi-tenancy comes from running multiple servers under different realm tags — the station does not arbitrate which realm tags are "real" (Sprint A: realm identity lives outside infrastructure).
Phase 1 scope (this commit)
State mutations + frame processing only. The publish path builds the signed EVENT frame and returns the matched LOCAL subscribers, but does NOT fan out across the cluster — that requires the Plumtree wire layer (hecate_plumtree) and the DHT topic-discovery integration which land in subsequent commits.
Sequencing
- This commit: server in isolation, no integration with station listener or DHT.
- Next: per-realm-namespace registry under
hecate_overlay_supso the listener can route inbound SUBSCRIBE / UNSUBSCRIBE / EVENT frames to the right server. - Then: Plumtree fan-out for cross-station delivery.
- Then: DHT integration for topic-mesh discovery.
Summary
Functions
Process an inbound EVENT frame received from the wire. Returns the matched local subscribers; the caller delivers.
Generic frame dispatch — handles subscribe / unsubscribe / event uniformly. Returns the matched subscribers for event frames, empty list for subscribe / unsubscribe.
Build a signed EVENT frame for Topic/Payload and return it together with the set of LOCAL subscribers that match. The caller is responsible for handing the frame to the cross-station delivery layer (Plumtree, future commit) and for delivering to the matched local subscribers via the application channel.
Remove Sub from every topic this server holds, dropping any topic that empties out as a result. See hecate_pubsub:purge_subscriber/2.
Relay an inbound PUBLISH frame from a remote daemon. The server builds an EVENT frame signed by THIS server's identity (intermediate hop re-signing — Phase 1 simplification; Phase 2 tightens to publisher-end-to-end auth via UCAN), preserves the original publisher pubkey + seq inside the EVENT, and returns the matched local subscribers. The caller (typically the peer observer) is responsible for sending EventFrame on each subscriber's peering connection.
Types
-type opts() :: #{realm := <<_:256>>, identity := macula_identity:key_pair()}.
Functions
-spec deliver_event(pid(), macula_frame:frame()) -> [<<_:256>>].
Process an inbound EVENT frame received from the wire. Returns the matched local subscribers; the caller delivers.
-spec process_frame(pid(), <<_:256>>, macula_frame:frame()) -> [<<_:256>>].
Generic frame dispatch — handles subscribe / unsubscribe / event uniformly. Returns the matched subscribers for event frames, empty list for subscribe / unsubscribe.
-spec publish(pid(), binary(), binary()) -> {macula_frame:frame(), [<<_:256>>]}.
Build a signed EVENT frame for Topic/Payload and return it together with the set of LOCAL subscribers that match. The caller is responsible for handing the frame to the cross-station delivery layer (Plumtree, future commit) and for delivering to the matched local subscribers via the application channel.
-spec purge_subscriber(pid(), <<_:256>>) -> ok.
Remove Sub from every topic this server holds, dropping any topic that empties out as a result. See hecate_pubsub:purge_subscriber/2.
-spec realm(pid()) -> <<_:256>>.
-spec relay_publish(pid(), macula_frame:frame()) -> {macula_frame:frame(), [<<_:256>>]} | {error, realm_mismatch}.
Relay an inbound PUBLISH frame from a remote daemon. The server builds an EVENT frame signed by THIS server's identity (intermediate hop re-signing — Phase 1 simplification; Phase 2 tightens to publisher-end-to-end auth via UCAN), preserves the original publisher pubkey + seq inside the EVENT, and returns the matched local subscribers. The caller (typically the peer observer) is responsible for sending EventFrame on each subscriber's peering connection.
Returns {error, realm_mismatch} when the publish frame's realm does not match this server's realm. The registry routes by realm so this should never fire in practice — defensive check.
-spec stop(pid()) -> ok.
-spec subscriber_count(pid()) -> non_neg_integer().
-spec topic_count(pid()) -> non_neg_integer().