hecate_pubsub (macula v10.5.3)

View Source

Realm-scoped PubSub state + dispatch (Part 6 §6).

Holds the topic-to-subscriber index for one realm and converts incoming SUBSCRIBE / UNSUBSCRIBE / EVENT frames into local state mutations + delivery instructions. The wire layer that actually transmits frames lives elsewhere — typically hecate_plumtree for intra-realm fan-out.

Pipeline

  • Local subscribesubscribe/3 adds the subscriber to the topic's set. The wrapper builds a SUBSCRIBE frame for upstream propagation if needed.
  • Local publishbuild_event/3 takes a PUBLISH spec and produces a signed EVENT frame the wrapper hands to Plumtree for fan-out. The publisher signs the EVENT once; intermediate hops do NOT re-sign, so every subscriber can verify authenticity end-to-end (Part 6 §6.4).
  • Receive EVENTdeliver_event/2 returns the list of local subscribers whose subscription matches the event's topic + realm. The wrapper notifies each via the application channel.
  • Receive SUBSCRIBE / UNSUBSCRIBEprocess/3 updates local state.

State is per realm: an instance handles one realm's topics only. Cross-realm leakage is impossible — the realm is baked into the state and every dispatch checks it.

Reference: plans/PLAN_MACULA_V2_PART6_PROTOCOL.md §6; plans/PLAN_PHASE_5_BREAKDOWN.md Session 5.5.

Summary

Functions

Match an incoming EVENT frame to local subscribers. Returns an empty list if the realm doesn't match (defensive — the transport should already route by realm) or no-one is subscribed.

Types

state/0

-type state() :: #{realm := <<_:256>>, subscriptions := #{topic() => sets:set(subscriber())}}.

subscriber/0

-type subscriber() :: macula_identity:pubkey().

topic/0

-type topic() :: binary().

Functions

build_event(_, _, Identity)

deliver_event(State, Frame)

-spec deliver_event(state(), macula_frame:frame()) -> [subscriber()].

Match an incoming EVENT frame to local subscribers. Returns an empty list if the realm doesn't match (defensive — the transport should already route by realm) or no-one is subscribed.

is_subscribed(_, Topic, Sub)

-spec is_subscribed(state(), topic(), subscriber()) -> boolean().

new(Realm)

-spec new(<<_:256>>) -> state().

process(State, From, F)

-spec process(state(), macula_identity:pubkey(), macula_frame:frame()) -> {state(), [subscriber()]}.

realm(_)

subscribe(State, Topic, Sub)

-spec subscribe(state(), topic(), subscriber()) -> state().

subscriber_count(_)

-spec subscriber_count(state()) -> non_neg_integer().

subscribers(_, Topic)

-spec subscribers(state(), topic()) -> [subscriber()].

topic_count(_)

-spec topic_count(state()) -> non_neg_integer().

topics(_)

-spec topics(state()) -> [topic()].

unsubscribe(State, Topic, Sub)

-spec unsubscribe(state(), topic(), subscriber()) -> state().