The feed behaviour: what fills a chart's source slot, asked for rows (spec/08 §11, D-140).
A feed is a struct whose module implements this behaviour. describe/1 answers the
feed's schema, its version and supports, the capabilities it honors among
[:window, :region, :latest, :budget, :push]; fetch/3 answers a
Visualize.Data.Delivery for a window and a budget; subscribe/2 and unsubscribe/2
are for a feed that pushes. Only rows are required. A window — nil, [from, to]
or a box of ranges that may ask for each identity's latest row (spec/08 §11.1, D-168) —
and a budget are requests: where a feed does not honor one, finish/3 trims and
reduces for it, and a budget reduction records reduced_by: :visualize.
Every callback answers {:error, reason} rather than raising, so a feed that is down is
a value a cell shows.
A push feed sends {:visualize_feed, ref, {:schema, version, schema}} before the first
delivery naming version, then {:visualize_feed, ref, {:delivery, delivery}}, each a
delivery of the rows new since the last (spec/08 §11.3). Visualize.Feed.Monitor runs
the loop over many feeds; Visualize.Feed.Combine makes one feed of several by window.
Examples
iex> alias Visualize.Data.{Delivery, Schema}
iex> schema = Schema.new!(%{t: %{type: :number, window: true}, v: %{type: :number}, s: %{type: :category}})
iex> rows = for t <- 1..10, s <- ["a", "b"], do: %{t: t, v: rem(t * 7, 5), s: s}
iex> delivery = Visualize.Feed.finish(Delivery.new(rows), schema, supports: [], budget: 8)
iex> {length(delivery.rows), delivery.reduced_by}
{8, :visualize}
Summary
Types
nil, or the most rows a cell wants.
What a feed honors (spec/08 §11.1).
A feed: a struct whose module implements Visualize.Feed.
nil, [from, to] over the feed's window field, either bound nil for open, or a box of
ranges that may ask for each identity's latest row (spec/08 §11.1, D-168).
Callbacks
The feed's present schema, its version and the capabilities it honors.
The rows for a window and a budget, both requests.
The feed's pushes sent to pid, tagged with the answered reference.
A subscription stopped.
Functions
The five capabilities a feed may honor, in the order of spec/08 §11.1.
The feed's {version, schema, supports}, or {:error, reason}.
A map of feeds by name as the describe function of spec/08 §10.3, for
Visualize.Data.Schema.Cache.resolve/4 and Visualize.Chart.apply/2's describe:.
A name not in the map is {:error, :no_feed}.
fetch(feed, window, budget): {:ok, delivery} or {:error, reason}.
A delivery finished for a request (spec/08 §11.2), each part where supports: lacks it:
trimmed to the window field's range of window: (:window) and to a box's other ranges
(:region), reduced to each identity's latest row (:latest, spec/08 §11.1), and
reduced to budget: by reduce: (:lttb or :m4) when there are more rows than the
budget (:budget), recording reduced_by: :visualize. A delivery that needs none of
them comes back as it is.
The feed's pushes sent to pid (spec/08 §11.3): {:ok, ref}, or {:error, :no_push}
for a feed whose module does not implement subscribe/2.
A subscription stopped; :ok for a feed that does not push.
The schema's window field (spec/08 §10.1, §11.2, D-154): the field a window is over, by
which rows are ordered, trimmed and routed. It is the field described window: true,
else the schema's one :time field when it does not say window: false; nil when
there is neither.
The type of the schema's window field, :time or :number, or nil when it has none:
the kind of window that applies to it (Visualize.Feed.Window.applies?/2).
Types
@type budget() :: pos_integer() | nil
nil, or the most rows a cell wants.
@type capability() :: :window | :region | :latest | :budget | :push
What a feed honors (spec/08 §11.1).
@type t() :: struct()
A feed: a struct whose module implements Visualize.Feed.
@type window() :: Visualize.Feed.Window.t() | %{optional(:ranges) => map(), optional(:latest) => boolean()}
nil, [from, to] over the feed's window field, either bound nil for open, or a box of
ranges that may ask for each identity's latest row (spec/08 §11.1, D-168).
Callbacks
@callback describe(feed :: t()) :: {String.t(), Visualize.Data.Schema.t(), [capability()]} | {:error, term()}
The feed's present schema, its version and the capabilities it honors.
@callback fetch(feed :: t(), window(), budget()) :: {:ok, Visualize.Data.Delivery.t()} | {:error, term()}
The rows for a window and a budget, both requests.
The feed's pushes sent to pid, tagged with the answered reference.
A subscription stopped.
Functions
@spec capabilities() :: [capability(), ...]
The five capabilities a feed may honor, in the order of spec/08 §11.1.
@spec describe(t()) :: {String.t(), Visualize.Data.Schema.t(), [capability()]} | {:error, term()}
The feed's {version, schema, supports}, or {:error, reason}.
@spec describer(%{required(term()) => t()}) :: (term() -> {:ok, Visualize.Data.Schema.t()} | {:error, term()})
A map of feeds by name as the describe function of spec/08 §10.3, for
Visualize.Data.Schema.Cache.resolve/4 and Visualize.Chart.apply/2's describe:.
A name not in the map is {:error, :no_feed}.
@spec fetch(t(), window(), budget()) :: {:ok, Visualize.Data.Delivery.t()} | {:error, term()}
fetch(feed, window, budget): {:ok, delivery} or {:error, reason}.
@spec finish(Visualize.Data.Delivery.t(), Visualize.Data.Schema.t(), keyword()) :: Visualize.Data.Delivery.t()
A delivery finished for a request (spec/08 §11.2), each part where supports: lacks it:
trimmed to the window field's range of window: (:window) and to a box's other ranges
(:region), reduced to each identity's latest row (:latest, spec/08 §11.1), and
reduced to budget: by reduce: (:lttb or :m4) when there are more rows than the
budget (:budget), recording reduced_by: :visualize. A delivery that needs none of
them comes back as it is.
Raises ArgumentError for a box Visualize.Feed.Window.check/2 refuses against the
schema: the request is the caller's.
The feed's pushes sent to pid (spec/08 §11.3): {:ok, ref}, or {:error, :no_push}
for a feed whose module does not implement subscribe/2.
A subscription stopped; :ok for a feed that does not push.
@spec window_field(Visualize.Data.Schema.t()) :: Visualize.Data.Schema.name() | nil
The schema's window field (spec/08 §10.1, §11.2, D-154): the field a window is over, by
which rows are ordered, trimmed and routed. It is the field described window: true,
else the schema's one :time field when it does not say window: false; nil when
there is neither.
iex> alias Visualize.Data.Schema
iex> Visualize.Feed.window_field(Schema.new!(%{t: %{type: :time}, v: %{type: :number}}))
:t
iex> Visualize.Feed.window_field(Schema.new!(%{tick: %{type: :number, window: true}, v: %{type: :number}}))
:tick
iex> Visualize.Feed.window_field(Schema.new!(%{a: %{type: :time}, b: %{type: :time}}))
nil
@spec window_type(Visualize.Data.Schema.t()) :: :time | :number | nil
The type of the schema's window field, :time or :number, or nil when it has none:
the kind of window that applies to it (Visualize.Feed.Window.applies?/2).