Virtual sources where feeds run (spec/15 §14, D-194): a value the board process holds beside its feed monitor and calls from its own callbacks, as it holds the monitor (spec/08 §11.4, D-140).
new/2 defines the sources — every input resolved, cycles refused by name, ranks
assigned. push/4 shows the engine the feeds' latest deliveries: a feed that changed
marks the sources that read it, and the first mark makes a pulse due debounce:
milliseconds later. run/2 runs a due pulse: the marked sources in rank order, each at
most once, every call bounded (Visualize.VirtualSource.Sandbox.run/3). A source that
fails keeps its last good output, and the pulse goes no further along it.
iex> alias Visualize.VirtualSource
iex> alias Visualize.VirtualSource.Engine
iex> alias Visualize.Data.{Delivery, Schema}
iex> count = VirtualSource.new!(id: :count, from: [hosts: nil],
...> schema: %{n: %{type: :number}}, elixir: "fn %{hosts: rows} -> [%{n: Enum.count(rows)}] end")
iex> {:ok, engine} = Engine.new(%{[:count] => count}, feeds: [:hosts], debounce: 0)
iex> hosts = Schema.new!(%{host: %{type: :category}})
iex> engine = Engine.push(engine, %{hosts: Delivery.new([%{host: "a"}, %{host: "b"}])}, %{hosts: hosts}, 0)
iex> engine = Engine.run(engine, 0)
iex> Engine.outputs(engine)[["count"]].rows
[%{"n" => 2}]
iex> Engine.status(engine)
%{["count"] => :live}
Summary
Types
A definition fault: the source's path, where in it, and why (spec/15 §14.1).
A source's fault (spec/15 §14.3): its kind and its detail, never a value.
Functions
The monotonic millisecond the next pulse is due, or nil (spec/15 §14.2).
Every failing source's fault by path, %{kind: kind, detail: detail} (spec/15 §14.3).
The engine over virtual sources by path, defined (spec/15 §14.1): {:ok, engine}, or
{:error, errors} — every input that resolves to nothing, every host function the
registry lacks, then every cycle by name. Options: feeds: (the feeds' names, []),
functions: (the registry, %{}), debounce: (milliseconds, 0), timeout: and
max_heap: (each call's limits, spec/08 §10.5.4).
Every source's last good output, a %Visualize.Data.Delivery{}, by path.
The feeds' latest deliveries and their schemas shown to the engine at the owner's
monotonic millisecond now (spec/15 §14.2): every source that reads a feed whose
delivery is not the one last seen is marked, and the first mark makes the next pulse
due debounce later.
What a name read from a scope names (spec/15 §14.5): {:source, path} for a virtual
source, resolved from the inside out, else {:feed, name} for a name feeds holds,
else :error.
The due pulse run at now (spec/15 §14.2): the marked sources in rank order, each at
most once; a changed answer marks its readers, which run later in the same pulse. The
engine is returned as it is when no pulse is due.
How many times each source has run, by path.
Every source's output schema, by path.
Every source's state by path (spec/15 §14.3): :loading before its first answer,
:live after, and {:down, {:virtual_source, id, kind}} while it fails.
Types
A definition fault: the source's path, where in it, and why (spec/15 §14.1).
A source's fault (spec/15 §14.3): its kind and its detail, never a value.
@type path() :: [atom(), ...]
@type t() :: %Visualize.VirtualSource.Engine{ cache: term(), checked: term(), compiled: term(), debounce: term(), due: term(), faults: term(), feed_schemas: term(), feeds: term(), functions: term(), inputs: term(), marked: term(), order: term(), outputs: term(), ranks: term(), readers: term(), run_opts: term(), runs: term(), seen: term(), sources: term() }
Functions
The monotonic millisecond the next pulse is due, or nil (spec/15 §14.2).
Every failing source's fault by path, %{kind: kind, detail: detail} (spec/15 §14.3).
@spec new(%{required(path()) => Visualize.VirtualSource.t()}, keyword()) :: {:ok, t()} | {:error, [error(), ...]}
The engine over virtual sources by path, defined (spec/15 §14.1): {:ok, engine}, or
{:error, errors} — every input that resolves to nothing, every host function the
registry lacks, then every cycle by name. Options: feeds: (the feeds' names, []),
functions: (the registry, %{}), debounce: (milliseconds, 0), timeout: and
max_heap: (each call's limits, spec/08 §10.5.4).
@spec outputs(t()) :: %{required(path()) => Visualize.Data.Delivery.t()}
Every source's last good output, a %Visualize.Data.Delivery{}, by path.
@spec push( t(), %{required(term()) => Visualize.Data.Delivery.t()}, %{required(term()) => Visualize.Data.Schema.t()}, integer() ) :: t()
The feeds' latest deliveries and their schemas shown to the engine at the owner's
monotonic millisecond now (spec/15 §14.2): every source that reads a feed whose
delivery is not the one last seen is marked, and the first mark makes the next pulse
due debounce later.
What a name read from a scope names (spec/15 §14.5): {:source, path} for a virtual
source, resolved from the inside out, else {:feed, name} for a name feeds holds,
else :error.
The due pulse run at now (spec/15 §14.2): the marked sources in rank order, each at
most once; a changed answer marks its readers, which run later in the same pulse. The
engine is returned as it is when no pulse is due.
@spec runs(t()) :: %{required(path()) => non_neg_integer()}
How many times each source has run, by path.
@spec schemas(t()) :: %{required(path()) => Visualize.Data.Schema.t()}
Every source's output schema, by path.
Every source's state by path (spec/15 §14.3): :loading before its first answer,
:live after, and {:down, {:virtual_source, id, kind}} while it fails.