Built-in workflow execution infrastructure.
Provides supervision, persistence, registry, and lifecycle management for running workflows as managed processes.
Starting a Runner
{:ok, _pid} = Runic.Runner.start_link(name: MyApp.Runner)Store Ownership
If no :store is configured, the Runner starts its built-in ETS store as
part of the supervision tree. This preserves the zero-configuration,
in-memory execution path.
If :store is configured explicitly, the Runner assumes that store's
supervision and lifecycle are managed elsewhere. This applies to custom
adapters and to built-in stores when you want to own their startup in your
application's supervision tree.
For adapters backed by an externally supervised dependency such as an Ecto repo:
{:ok, _pid} =
Runic.Runner.start_link(
name: MyApp.Runner,
store: MyApp.SQLiteStore,
store_opts: [repo: MyApp.Repo]
)To use the built-in ETS store explicitly, start it before the Runner:
children = [
{Runic.Runner.Store.ETS, runner_name: MyApp.Runner},
{Runic.Runner, name: MyApp.Runner, store: Runic.Runner.Store.ETS}
]Running Workflows
{:ok, pid} = Runic.Runner.start_workflow(MyApp.Runner, :my_workflow, workflow)
:ok = Runic.Runner.run(MyApp.Runner, :my_workflow, input)
{:ok, results} = Runic.Runner.get_results(MyApp.Runner, :my_workflow)
# Structured results using output port contracts
{:ok, %{total: value}} = Runic.Runner.get_results(MyApp.Runner, :my_workflow, [])
# Select specific components
{:ok, %{price: p}} = Runic.Runner.get_results(MyApp.Runner, :id, components: [:price])
Summary
Functions
Triggers an explicit checkpoint for a running workflow.
Returns a specification to start this module under a supervisor.
Decodes a workflow snapshot produced by encode_snapshot/1.
Encodes a workflow snapshot for stores implementing Runic.Runner.Store.
Returns the raw productions from a running workflow.
Returns structured results from a running workflow.
Returns the {store_module, store_state} tuple for this runner.
Returns the full workflow struct from a running workflow.
Lists all active workflow IDs managed by this runner.
Looks up the PID of a running workflow by ID.
Resumes a workflow from persisted state.
Feeds input to a running workflow.
Starts a new workflow under this runner.
Stops a running workflow.
Returns the via tuple for addressing a worker through the registry.
Functions
Triggers an explicit checkpoint for a running workflow.
Persists the current workflow state to the store regardless of
the configured checkpoint strategy. Useful with checkpoint_strategy: :manual.
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec decode_snapshot(binary()) :: {:ok, Runic.Workflow.t()} | {:error, :invalid_snapshot | {:unsupported_snapshot, term()}}
Decodes a workflow snapshot produced by encode_snapshot/1.
@spec encode_snapshot(Runic.Workflow.t()) :: binary()
Encodes a workflow snapshot for stores implementing Runic.Runner.Store.
The encoded format is tagged and versioned so resume/3 can distinguish
Runic workflow snapshots from legacy adapter-specific blobs.
Returns the raw productions from a running workflow.
For structured results using port contracts, use get_results/3.
Returns structured results from a running workflow.
Options
:components— list of component names to extract. Whennil(default), uses the workflow's output port contract.:facts— whentrue, returns%Fact{}structs. Defaultfalse.:all— whentrue, returns all produced values as lists. Defaultfalse.
Examples
# Use output port contract
{:ok, %{total: 42.50}} = Runner.get_results(runner, :order_pipeline, [])
# Explicit component selection
{:ok, %{price: 42.50}} = Runner.get_results(runner, :order_pipeline, components: [:price])
# All values as facts
{:ok, %{total: [%Fact{}, ...]}} = Runner.get_results(runner, :id, facts: true, all: true)
Returns the {store_module, store_state} tuple for this runner.
The store state is initialized lazily on first access and cached in persistent_term.
Returns the full workflow struct from a running workflow.
Lists all active workflow IDs managed by this runner.
Looks up the PID of a running workflow by ID.
Returns pid or nil.
Resumes a workflow from persisted state.
Loads persisted workflow state from the configured store and starts a new
Worker. Event-sourced stores are replayed through Workflow.from_events/2.
Stores that implement snapshots plus cursor-aware replay can resume from a
saved workflow snapshot and replay only events after its cursor.
Options
:rehydration— Controls how fact values are loaded during recovery.:full(default) — All fact values are loaded into memory.:hybrid— Uses lean replay to createFactRefvertices, classifies hot/cold facts, then resolves only hot values from the fact store. Requires a store that implementssave_fact/3andload_fact/2.:lazy— All facts stay asFactRefstructs, resolved on demand during dispatch. Maximum memory savings, but requires resolution before any fact value can be used.
Feeds input to a running workflow.
Options
:run_context- A map of external values keyed by component name, made available to components that usecontext/1expressions. Supports a:_globalkey for values available to all components.
Starts a new workflow under this runner.
Returns {:ok, pid} or {:error, {:already_started, pid}}.
Stops a running workflow.
Options:
persist: true(default) — saves final state to the store before stoppingpersist: false— stops without saving
Returns the via tuple for addressing a worker through the registry.