A subscriptions/listen stream opened with Snodo.Client.listen/3.
The struct is the handle: accepted is the filter the server acknowledged,
id the request ID (the subscription ID on the wire), ref the tag of the
messages the stream sends, owner the process that opened it, and pid the
transport process that receives the stream.
Messages
The owner receives {:snodo_subscription, ref, payload} with one of:
{:notification, method, params}: one event, as the server sent it.methodis the notification's method, for example"notifications/resources/updated","notifications/tools/list_changed", or an extension's such as"notifications/tasks";paramsis its params map,"_meta"included.{:dropped, count}:countevents were discarded because the buffer was full. It precedes the next delivered event.{:closed, reason}: the stream ended.:completeis the server's terminal result;{:error, %Snodo.Error{}}is its terminal error response, or a failure of the connection. Nothing follows it.
Demand and the buffer
Events are sent to the owner only while it has asked for them. demand/2
asks for n more, next/2 asks for one and waits for it, and stream/1
wraps next/2 as an Enumerable. Events that arrive without demand wait in
the transport process, at most :max_buffer of them (100 by default). A
full buffer follows the :overflow policy given to Snodo.Client.listen/3:
:drop_oldest (the default) discards the oldest queued event, :drop_newest
discards the arriving one. Either way the owner is told with {:dropped, n}.
{:closed, reason} is delivered after the queued events.
Ending the stream
close/1 ends the stream from the client side; the server sees a
cancellation. The owner's exit does the same. No message follows close/1;
events delivered before it stay in the owner's mailbox.
Summary
Types
Why a stream ended: the server's terminal result, or an error.
What the owner receives inside {:snodo_subscription, ref, payload}.
Functions
Ends the stream.
Asks for n more events, which arrive as messages to the owner.
Asks for one event and waits for the next message.
The stream's payloads as an Enumerable, ending with {:closed, reason}.
Types
@type close_reason() :: :complete | {:error, Snodo.Error.t()}
Why a stream ended: the server's terminal result, or an error.
@type payload() :: {:notification, String.t(), map()} | {:dropped, pos_integer()} | {:closed, close_reason()}
What the owner receives inside {:snodo_subscription, ref, payload}.
Functions
@spec close(t()) :: :ok
Ends the stream.
The server is sent a cancellation: stdio writes notifications/cancelled,
HTTP closes the connection, and the direct client closes the source. Returns
:ok, also for a stream that has already ended.
@spec demand(t(), pos_integer()) :: :ok
Asks for n more events, which arrive as messages to the owner.
Demand accumulates: queued events are sent at once, up to n, and later
events are sent as they arrive until the demand is used up.
Asks for one event and waits for the next message.
Returns the payload: {:notification, method, params}, {:dropped, n}, or
{:closed, reason}. Returns {:error, :timeout} when nothing arrives in
timeout milliseconds; the demand stays, so that event arrives as a message
later and the next call returns it. If the transport process exits, returns
{:closed, {:error, %Snodo.Error{}}}. Must be called by the owner.
@spec stream(t()) :: Enumerable.t()
The stream's payloads as an Enumerable, ending with {:closed, reason}.
Each element is fetched with next/2, so the stream runs in the owner.
Stopping early leaves the subscription open; call close/1.