Runtime helpers shared by AshWorkflow.Changes.RecordEvent and the
generated state_at/2 and history/1 code interface functions.
Kept out of the generated functions themselves so the injected code (via
Spark.Dsl.Transformer.eval/3) stays a thin delegate, and so this logic is
directly unit-testable.
Summary
Functions
Drops every row that a later undo reversed.
Returns the most recent row representing an actual state change, or nil if
there is none.
Returns the transition log rows for record, ordered by occurred_at
ascending.
Returns the state record was in at at, resolved by walking its
transition log in Elixir. Portable across data layers because it does not
rely on a "latest row per record" query.
Returns the undoes self-referencing foreign key on log_resource, or nil
if the log does not declare one.
Functions
@spec effective([Ash.Resource.record()]) :: [Ash.Resource.record()]
Drops every row that a later undo reversed.
An undo row carries undoes_id pointing at the row it reverses, so the
superseded set is just the non-nil undoes_id values. Redo falls out of the
same rule without a special case: undoing an undo marks the undo row itself
superseded, which leaves the redo row — and the state it lands on — standing.
@spec head_state_change(Ash.Resource.record()) :: Ash.Resource.record() | nil
Returns the most recent row representing an actual state change, or nil if
there is none.
Rows where from_state == to_state are skipped: an action timeout writes one
to record that it fired, and it did not move the workflow anywhere, so it is
not what an undo should reverse.
@spec history(Ash.Resource.record(), Keyword.t()) :: [Ash.Resource.record()]
Returns the transition log rows for record, ordered by occurred_at
ascending.
Raises if the resource has no transition_log configured.
Options
:effective— whentrue, omits rows that a later undo reversed, leaving the corrected account of what stands rather than the full record of what happened. Defaults tofalse.
@spec state_at(Ash.Resource.record(), DateTime.t(), Keyword.t()) :: atom() | nil
Returns the state record was in at at, resolved by walking its
transition log in Elixir. Portable across data layers because it does not
rely on a "latest row per record" query.
Returns nil if at is before the earliest logged row.
Options
:effective— whentrue, answers from the corrected account rather than the literal one: rows reversed by a later undo are ignored, so a state the workflow briefly occupied and then rewound out of is not reported. Every known correction is applied regardless of when it happened, so this is "what we now say was true atat", not "what the log said atat". Defaults tofalse.
@spec undoes_foreign_key(Ash.Resource.t()) :: atom() | nil
Returns the undoes self-referencing foreign key on log_resource, or nil
if the log does not declare one.