A feed's schema: what each of its fields means (spec/08 §10.1, D-136).
A schema maps a field — named as the feed's rows name it, an atom or a string — to a
description: its type, and as much of unit, quantity, label, order,
status, polarity, target, continuity and window as the feed knows. It says what
the numbers are, whoever draws them, and never how they are drawn: a description has
no colour key, since colour is the theme's to choose from the meaning (#533). A :time
field holds instants; a feed whose clock is a number describes it :number and
window: true, the field its windows are over (D-154).
A schema is identified by its version, a content hash (spec/08 §10.2): the same
schema has the same version on every node and under every release, and any change of
content is a new version. A Visualize.Data.Delivery names the version its rows were
produced under; Visualize.Data.Schema.Cache holds schemas by {feed, version}.
Examples
iex> {:ok, schema} =
...> Visualize.Data.Schema.new(%{
...> t: %{type: :time},
...> latency: %{type: :number, unit: "s", quantity: :duration, label: "Request time"},
...> state: %{type: :category, order: ["ok", "warn", "fail"],
...> status: %{"ok" => :good, "warn" => :warning, "fail" => :bad}}
...> })
iex> Visualize.Data.Schema.fetch(schema, "latency", :unit)
{:ok, "s"}
iex> String.length(Visualize.Data.Schema.version(schema))
64
iex> Visualize.Data.Schema.new(%{state: %{type: :category, colors: %{"ok" => "#0a0"}}})
{:error, [{[:state, :colors], {:colour_key, :colors}}]}
Summary
Functions
The ten description keys, :type first (spec/08 §10.1).
A field's description, by either spelling of its name (spec/08 §6.2).
One attribute of a field's description; :error when the field or the attribute is absent.
One fault of new/1 as a line a person reads.
The schema of a map of field descriptions, or every fault of it by path (spec/08 §10.1).
The schema of a map of field descriptions, or ArgumentError naming every fault.
The schema's version: the SHA-256 of its canonical encoding as 64 lowercase hex digits
(spec/08 §10.2), computed once by new/1.
Types
@type description() :: %{ :type => :time | :number | :category | :text, optional(:unit) => String.t(), optional(:quantity) => atom(), optional(:label) => String.t(), optional(:order) => [String.t() | atom() | number(), ...], optional(:status) => %{required(term()) => atom()}, optional(:polarity) => :higher_is_better | :lower_is_better | :neutral, optional(:target) => number(), optional(:continuity) => number(), optional(:window) => boolean() }
What one field means (spec/08 §10.1).
@type error() :: {[name() | atom() | non_neg_integer() | term()], term()}
A fault of new/1: the path from the schema to the value, and why.
A field name, as the feed's rows spell it.
@type t() :: %Visualize.Data.Schema{ fields: %{required(name()) => description()}, version: String.t() }
Functions
@spec attributes() :: [atom(), ...]
The ten description keys, :type first (spec/08 §10.1).
@spec fetch(t(), name()) :: {:ok, description()} | :error
A field's description, by either spelling of its name (spec/08 §6.2).
iex> schema = Visualize.Data.Schema.new!(%{"v" => %{type: :number}})
iex> Visualize.Data.Schema.fetch(schema, :v)
{:ok, %{type: :number}}
iex> Visualize.Data.Schema.fetch(schema, :w)
:error
One attribute of a field's description; :error when the field or the attribute is absent.
One fault of new/1 as a line a person reads.
iex> Visualize.Data.Schema.format_error({[:latency, :unit], {:invalid_for, :category}})
"latency.unit: is not a key a :category field takes"
The schema of a map of field descriptions, or every fault of it by path (spec/08 §10.1).
iex> Visualize.Data.Schema.new(%{v: %{type: :category, unit: "s"}})
{:error, [{[:v, :unit], {:invalid_for, :category}}]}
The schema of a map of field descriptions, or ArgumentError naming every fault.
The schema's version: the SHA-256 of its canonical encoding as 64 lowercase hex digits
(spec/08 §10.2), computed once by new/1.