Continuum.DurableTerm (continuum v0.8.1)

Copy Markdown View Source

Validates values before they cross a Continuum journal boundary.

ETF can encode node-local identities, but decoding them during replay does not make them meaningful on another process or node. This validator rejects those identities recursively and reports their exact location.

Summary

Functions

Non-raising decode!/1.

Decode a term Continuum wrote across a journal boundary.

Types

path()

@type path() :: [path_segment()]

path_segment()

@type path_segment() ::
  atom() | {:field, term()} | {:index, non_neg_integer()} | :tail

Functions

decode(binary)

@spec decode(binary()) :: {:ok, term()} | {:error, Continuum.DurableTermError.t()}

Non-raising decode!/1.

decode!(binary)

@spec decode!(binary()) :: term()

Decode a term Continuum wrote across a journal boundary.

Decoding is :safe, so it refuses to create atoms from journal bytes. On a cold node, Continuum loads the modules declared by the node's loaded OTP applications and retries once; this makes atoms from deployed workflow, activity, and runtime code available without trusting database text. A final refusal means one of three things: the stored bytes are corrupt, they were written by code this node does not have, or workflow code journaled a dynamically constructed atom — which was never replay-durable, because the atom does not exist on a node that has not run the same input.

Raises Continuum.DurableTermError rather than leaking ArgumentError from :erlang.binary_to_term/2.

validate(term, root \\ :value)

@spec validate(term(), atom()) :: :ok | {:error, Continuum.DurableTermError.t()}

validate!(term, root \\ :value)

@spec validate!(term(), atom()) :: term()