Snodo.Subscription.Hub (snodo v0.1.0)

Copy Markdown View Source

An opt-in, application-supervised Snodo.Subscription.Source.

A hub broadcasts protocol-neutral Snodo.Subscription.Event values to every listener whose accepted filter selects the event. Each listener has its own bounded queue, so a client that stops reading cannot make the hub's memory usage grow without limit. The default overflow policy keeps the newest information by dropping the oldest queued event; applications may instead configure overflow: :drop_newest.

The hub is application state, not router state. Start it under the application's supervision tree and pass source/1 as the :subscription_source option of a server's runtime/1 or of Snodo.Server.Runtime.new/1:

children = [{Snodo.Subscription.Hub, name: MyApp.SubscriptionHub}]

runtime =
  MyServer.runtime(
    subscription_source: Snodo.Subscription.Hub.source(MyApp.SubscriptionHub)
  )

Publishers may send an existing event with publish/2 or use the core event helpers such as notify_tools_list_changed/2. Extensions publish their own Snodo.Subscription.Event.extension/4 values through the same publish/2 function; the negotiated extension remains responsible for filter admission and wire shaping.

Summary

Functions

Returns a specification to start this module under a supervisor.

Gracefully completes every listener currently attached to the hub.

Publishes a prompt-list change event.

Publishes an update event for one absolute resource URI.

Publishes a resource-list change event.

Publishes a tool-list change event.

Publishes one protocol-neutral event to every matching listener.

Returns a source configuration for the :subscription_source runtime option.

Starts an application-owned subscription hub.

Returns bounded-queue and listener counts for operational inspection.

Types

delivery_report()

@type delivery_report() :: %{
  matched: non_neg_integer(),
  delivered: non_neg_integer(),
  buffered: non_neg_integer(),
  dropped: non_neg_integer()
}

overflow_policy()

@type overflow_policy() :: :drop_oldest | :drop_newest

server()

@type server() :: GenServer.server()

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

complete(hub)

@spec complete(server()) :: :ok

Gracefully completes every listener currently attached to the hub.

notify_prompts_list_changed(hub, opts \\ [])

@spec notify_prompts_list_changed(server(), keyword()) ::
  {:ok, delivery_report()} | {:error, {:invalid_event, String.t()}}

Publishes a prompt-list change event.

notify_resource_updated(hub, uri, opts \\ [])

@spec notify_resource_updated(server(), String.t(), keyword()) ::
  {:ok, delivery_report()} | {:error, {:invalid_event, String.t()}}

Publishes an update event for one absolute resource URI.

notify_resources_list_changed(hub, opts \\ [])

@spec notify_resources_list_changed(server(), keyword()) ::
  {:ok, delivery_report()} | {:error, {:invalid_event, String.t()}}

Publishes a resource-list change event.

notify_tools_list_changed(hub, opts \\ [])

@spec notify_tools_list_changed(server(), keyword()) ::
  {:ok, delivery_report()} | {:error, {:invalid_event, String.t()}}

Publishes a tool-list change event.

publish(hub, event)

@spec publish(server(), Snodo.Subscription.Event.t()) ::
  {:ok, delivery_report()} | {:error, {:invalid_event, String.t()}}

Publishes one protocol-neutral event to every matching listener.

The report distinguishes events delivered directly to a blocked pull from events placed in a listener queue. :dropped counts per-listener overflow, so one publication can be dropped more than once.

source(hub)

@spec source(server()) :: {module(), server()}

Returns a source configuration for the :subscription_source runtime option.

start_link(opts \\ [])

@spec start_link(keyword()) :: GenServer.on_start()

Starts an application-owned subscription hub.

Options are:

  • :name - a standard GenServer registered name;
  • :max_buffer - the positive per-listener queue bound, defaulting to 100;
  • :overflow - either :drop_oldest (the default) or :drop_newest.
  • :instrumentation - an optional Snodo.Instrumentation sink.

stats(hub)

@spec stats(server()) :: %{
  subscriptions: non_neg_integer(),
  closing: non_neg_integer(),
  queued: non_neg_integer(),
  dropped: non_neg_integer(),
  max_buffer: pos_integer(),
  overflow: overflow_policy()
}

Returns bounded-queue and listener counts for operational inspection.