Roux.Input (roux v0.2.2)

Copy Markdown View Source

External values that form the leaves of the dependency graph.

Inputs represent values provided from outside the computation — source file contents, configuration, environment variables. Setting an input advances the global revision counter with early cutoff: if the new value equals the old value, no revision advance occurs.

Input values are stored as memo entries with a {:input, input_name, key} query key, empty dependencies, and durability inherited from the input definition.

Early cutoff

When set/4 is called with a value identical to the current value, no revision advance occurs. This prevents cascading recomputation when a file is saved without changes. Equality uses a hash pre-check (D8) to avoid structural comparison on large terms when values differ.

Summary

Functions

Creates an input definition. Default durability is :medium.

Removes an input value and advances the revision counter.

Checks whether an input value has been set for the given key.

Reads an input value, returning {:ok, value} or :error.

Reads an input value.

Reads an input value along with the revision at which it last changed.

Lists all keys that have been set for an input.

Registers an input definition with the database.

Sets an input value with early cutoff.

Types

definition()

@type definition() :: Roux.Input.Definition.t()

Functions

define(name, opts \\ [])

@spec define(
  atom(),
  keyword()
) :: definition()

Creates an input definition. Default durability is :medium.

Options

  • :durability — :high, :medium, or :low (default: :medium)

delete(db, input_name, key)

@spec delete(Roux.Database.t(), atom(), term()) :: :ok

Removes an input value and advances the revision counter.

No-op if the key was not set. Uses :ets.take/2 to atomically remove and detect existence in a single operation (no TOCTOU gap).

Raises ArgumentError if the input is not registered.

exists?(db, input_name, key)

@spec exists?(Roux.Database.t(), atom(), term()) :: boolean()

Checks whether an input value has been set for the given key.

fetch(db, input_name, key)

@spec fetch(Roux.Database.t(), atom(), term()) :: {:ok, term()} | :error

Reads an input value, returning {:ok, value} or :error.

Unlike get/3, does not raise when the key has not been set.

get(db, input_name, key)

@spec get(Roux.Database.t(), atom(), term()) :: term()

Reads an input value.

Raises Roux.Input.NotSetError if the key has never been set. Dependency tracking is deferred to runtime integration.

get_with_revision(db, input_name, key)

@spec get_with_revision(Roux.Database.t(), atom(), term()) ::
  {term(), Roux.Revision.revision()}

Reads an input value along with the revision at which it last changed.

Raises Roux.Input.NotSetError if the key has never been set.

keys(database, input_name)

@spec keys(Roux.Database.t(), atom()) :: [term()]

Lists all keys that have been set for an input.

Returns an empty list if no keys have been set.

register(db, definition)

@spec register(Roux.Database.t(), definition()) :: :ok

Registers an input definition with the database.

Must be called before set/4 or get/3 for this input.

set(db, input_name, key, value, opts \\ [])

@spec set(Roux.Database.t(), atom(), term(), term(), keyword()) :: :ok

Sets an input value with early cutoff.

If the value is identical to the current value (hash pre-check, then structural equality), no revision advance occurs. Otherwise, the revision counter advances at the input's durability level.

:durability overrides the input definition's default FOR THIS KEY. Durability is otherwise a property of the whole input, which is too coarse for an editor: the file being typed in changes constantly while its neighbours do not, and one shared level means validation's durability check can never short-circuit. Marking the active buffer :low and leaving everything else :medium lets a keystroke advance only the low slot, so queries that do not read the edited file skip their dependency walk entirely.

Raises ArgumentError if the input is not registered.