Argus.Facts (Panoptes v0.13.0)

Copy Markdown View Source

Schema-driven typed decoding of raw fact rows for in-process consumers.

Argus.Pipeline.Emit produces facts as lists of string fields — the right shape for Souffle .facts files, but stringly for Elixir consumers. This module decodes those rows against Argus.Schema: each row becomes a map keyed by the schema's field names, with values decoded by field kind (numbers and labels to integers, instruction IDs to Argus.InstrId structs).

Decoding is strict: a row that doesn't match its relation's schema (wrong arity, non-numeric number, malformed instruction ID) raises — such a row can only come from a bug in an emitter or extractor, and surfacing it loudly at the decode boundary beats consumers silently dropping it. Relations not in the schema (custom extractor output) pass through undecoded.

Eventually emission itself may become typed, with stringification pushed to the .facts writer; this decoder is the compatible first step.

Summary

Types

Interned rows: one tuple per row in schema field order, symbol-kinded fields as Argus.Symbols ids and numeric fields as integers. Relations the schema does not know hold their every field as a symbol.

t()

Functions

Decode a raw facts map (relation => [[String.t()]]) into typed rows.

Decode interned rows to the same typed rows decode/1 produces from raw ones. Instruction IDs come from the table's parse cache instead of being parsed per row.

Intern raw rows (relation => [[String.t()]]) against symbols.

The raw rows behind interned ones, field for field.

Types

interned()

@type interned() :: %{required(atom()) => [tuple()]}

Interned rows: one tuple per row in schema field order, symbol-kinded fields as Argus.Symbols ids and numeric fields as integers. Relations the schema does not know hold their every field as a symbol.

row()

@type row() :: %{required(atom()) => term()}

t()

@type t() :: %{required(atom()) => [row()]}

Functions

decode(raw)

@spec decode(%{required(atom()) => [[String.t()]]}) :: t()

Decode a raw facts map (relation => [[String.t()]]) into typed rows.

decode(interned, symbols)

@spec decode(interned(), Argus.Symbols.t()) :: t()

Decode interned rows to the same typed rows decode/1 produces from raw ones. Instruction IDs come from the table's parse cache instead of being parsed per row.

intern(raw, symbols)

@spec intern(%{required(atom()) => [[String.t()]]}, Argus.Symbols.t()) :: interned()

Intern raw rows (relation => [[String.t()]]) against symbols.

materialize(interned, symbols)

@spec materialize(interned(), Argus.Symbols.t()) :: %{
  required(atom()) => [[String.t()]]
}

The raw rows behind interned ones, field for field.