The Elixir runner SDK — the runner-as-handle surface over flz_core, the
runtime every Flezha SDK runs on. A runner reaches its controller one way,
over UDS (transport: :uds, the default) or QUIC (transport: :quic),
wherever the controller runs: in this BEAM, on this machine or on another.
A handle accumulates its declared factory set with no connection or process;
start/1 claims the process-wide runner slot (a named singleton) and
connects; run/1 is start/1 then await_termination/1. Authoring and
connection failures are named error tuples returned at the call site (never a
raise) and propagate through a pipe. child_spec/1 wraps the same sequence for
a host application's supervision tree.
The connection settings are read from the OS environment first, then config :flezha_sdk, .... A controller that enforces
authorization asks every runner for a credential: pass it as
namespace_secret:, or set FLEZHA_NAMESPACE_SECRET.
Summary
Functions
Block until the runner terminates.
Call the entry channel channel of relay_id with value, through the
controller under the same role check as send/5, answering what the relay
answers: {:ok, answer} with a JSON value, a string for text, the bytes for
the binary formats, or %{"accepted" => true} from a channel no output
answers. value is encoded as an output with no serializer of its own
encodes it.
A child spec wrapping create → register → start for the host application's
supervision tree: namespace:, relays:, transport: and
namespace_secret:. The supervised process is the runner. A runner runs
once per BEAM: one that stops or crashes ends its session, and the restart
that follows is refused, so the failure reaches
the node, which is the unit to restart. The controller moves the relays
meanwhile.
Ship each relay's state, end the session and release the slot. A runner
runs once per BEAM: a later start in this node is refused as
runtime.core_shut_down. A never-started handle is a no-op.
Create a runner handle. No connection, no slot claim, no processes.
Declare a relay: a module of the Flezha.SDK.Relay behaviour. Legal
before and after start/1.
The ids of the relay instances bound on this runner now, a partition member by its member id, read without the controller.
start/1 then await_termination/1.
Send message to the entry channel channel of relay_id.
The live runner process behind a handle: runtime.runner_not_started before
start/1, and a refused handle's own error unchanged.
Claim the runner slot and connect. The loser gets runtime.runner_already_running
naming the namespace.
Remove a declared relay — the inverse of register_factory/2, taking what it took.
Types
Functions
@spec await_termination(result()) :: :ok | {:error, Flezha.SDK.Error.t()}
Block until the runner terminates.
@spec call(result() | pid() | atom(), String.t(), String.t(), term()) :: {:ok, term()} | {:error, Flezha.SDK.Error.t()}
Call the entry channel channel of relay_id with value, through the
controller under the same role check as send/5, answering what the relay
answers: {:ok, answer} with a JSON value, a string for text, the bytes for
the binary formats, or %{"accepted" => true} from a channel no output
answers. value is encoded as an output with no serializer of its own
encodes it.
runner is a handle, or the runner server's pid or name.
A child spec wrapping create → register → start for the host application's
supervision tree: namespace:, relays:, transport: and
namespace_secret:. The supervised process is the runner. A runner runs
once per BEAM: one that stops or crashes ends its session, and the restart
that follows is refused, so the failure reaches
the node, which is the unit to restart. The controller moves the relays
meanwhile.
@spec close(result()) :: :ok
Ship each relay's state, end the session and release the slot. A runner
runs once per BEAM: a later start in this node is refused as
runtime.core_shut_down. A never-started handle is a no-op.
Create a runner handle. No connection, no slot claim, no processes.
Declare a relay: a module of the Flezha.SDK.Relay behaviour. Legal
before and after start/1.
Its declaration is judged here by flz_core, the check every SDK's builder
is judged by, and declared to the live core when the runner is started.
@spec relays(result() | pid() | atom()) :: {:ok, [String.t()]} | {:error, Flezha.SDK.Error.t()}
The ids of the relay instances bound on this runner now, a partition member by its member id, read without the controller.
@spec run(result()) :: :ok | {:error, Flezha.SDK.Error.t()}
start/1 then await_termination/1.
@spec send(result() | pid() | atom(), String.t(), String.t(), String.t(), keyword()) :: {:ok, term()} | {:error, Flezha.SDK.Error.t()}
Send message to the entry channel channel of relay_id.
Through the controller by default, under the same role check as
Flezha.SDK.Control, answering its verdict: {:ok, %{"to" => relay, "verdict" => "delivered" | "absorbed" | "suspended"}}. Options:
msg_id:the message's id, stamped asflz.msg_id: a relay whose input log still holds an input of this id absorbs the repeat.key:the partition key whose member of a partition group takes it.local: truein process, without the controller: the message is on no disk, is lost if the runner stops before handling it, and a relay's input log does not cover it. Answers{:ok, nil}; refused withruntime.relay_not_localfor a relay this runner does not hold, and withusage.options_conflictbesidemsg_id:orkey:.
runner is a handle, or the runner server's pid or name.
The live runner process behind a handle: runtime.runner_not_started before
start/1, and a refused handle's own error unchanged.
The one place a caller outside this module reads the handle's server, so the struct's shape stays this module's business.
Claim the runner slot and connect. The loser gets runtime.runner_already_running
naming the namespace.
Remove a declared relay — the inverse of register_factory/2, taking what it took.