# `Macaw.Data.Schema.Cache`
[🔗](https://github.com/dcoai/macaw_data/blob/v0.5.3/lib/macaw/data/schema/cache.ex#L1)

Schemas by `{feed, version}`, as a value (spec/01 §1.12, visualize D-136).

A delivery names the version of its feed's schema (`Macaw.Data.Delivery`); a
version already held costs a lookup, and one not seen before is asked of the feed
once. The cache is not a process and not a table: whatever owns the feeds — a board's
process, or a page's sources — holds it in its own state, passes
it in and keeps the grown cache it gets back. A feed is any term that names one.

## Examples

    iex> alias Macaw.Data.Schema
    iex> schema = Schema.new!(%{v: %{type: :number, unit: "ms"}})
    iex> cache = Schema.Cache.new([{:latency, schema}])
    iex> {:ok, ^schema, ^cache} = Schema.Cache.resolve(cache, :latency, Schema.version(schema), nil)
    iex> Schema.Cache.resolve(cache, :latency, "0000", nil)
    {:error, {:unknown_schema, :latency, "0000"}, cache}

# `describe`

```elixir
@type describe() :: (feed() -&gt; {:ok, Macaw.Data.Schema.t()} | {:error, term()}) | nil
```

The pull side of a feed: its present schema, or why it has none.

# `feed`

```elixir
@type feed() :: term()
```

# `reason`

```elixir
@type reason() ::
  {:unknown_schema, feed(), String.t()}
  | {:describe, feed(), term()}
  | {:schema_version, feed(), String.t(), String.t()}
```

Why `resolve/4` has no schema for a version (spec/01 §1.12).

# `t`

```elixir
@type t() :: %Macaw.Data.Schema.Cache{
  entries: %{required({feed(), String.t()}) =&gt; Macaw.Data.Schema.t()}
}
```

# `fetch`

```elixir
@spec fetch(t(), feed(), String.t()) :: {:ok, Macaw.Data.Schema.t()} | :error
```

A feed's schema at a version, or `:error` when the cache does not hold it.

# `new`

```elixir
@spec new() :: t()
```

The empty cache.

# `new`

```elixir
@spec new([{feed(), Macaw.Data.Schema.t()}]) :: t()
```

A cache holding each `{feed, schema}` pair under the schema's own version.

# `put`

```elixir
@spec put(t(), feed(), Macaw.Data.Schema.t()) :: t()
```

The cache with a feed's schema added under its version.

# `resolve`

```elixir
@spec resolve(t(), feed(), String.t(), describe()) ::
  {:ok, Macaw.Data.Schema.t(), t()} | {:error, reason(), t()}
```

A feed's schema at a version (spec/01 §1.12): the cached one without calling anything,
else `describe`'s answer, asked once and cached.

`describe` answering a schema of another version is `{:schema_version, feed, version,
got}`, with the answer cached under its own version; `{:error, reason}` from it is
`{:describe, feed, reason}`; no `describe` for a version the cache lacks is
`{:unknown_schema, feed, version}`. The cache comes back in every case.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
