Decode a server-sent event stream.
Glean streams agent runs as text/event-stream. This module turns a stream of
raw binary chunks into a stream of Gleanex.SSE.Event structs, reassembling
events that arrive split across chunk boundaries.
It is a plain function over an enumerable, so it can be tested with a list of binaries and used with anything that produces chunks.
Examples
iex> ["id: 1\nevent: message\ndata: {\"a\":1}\n\n"]
...> |> Gleanex.SSE.decode()
...> |> Enum.to_list()
[%Gleanex.SSE.Event{id: "1", event: "message", data: "{\"a\":1}", retry: nil}]
Summary
Functions
@spec decode(Enumerable.t()) :: Enumerable.t()
Turn a stream of binary chunks into a stream of events.
Events are separated by a blank line. A trailing event with no blank line after it, which is what a stream cut short looks like, is still emitted.
@spec json_data(Gleanex.SSE.Event.t()) :: {:ok, term()} | {:error, :not_json | :no_data}
Decode an event's data as JSON.
Returns {:ok, term}, or {:error, reason} when the payload is not JSON.
Glean sends a plain [DONE] sentinel on some streams, which is reported as
{:error, :not_json} rather than raising.
Examples
iex> Gleanex.SSE.json_data(%Gleanex.SSE.Event{data: ~s({"a": 1})})
{:ok, %{"a" => 1}}
iex> Gleanex.SSE.json_data(%Gleanex.SSE.Event{data: "[DONE]"})
{:error, :not_json}