Flezha.SDK (flezha_sdk v0.1.0)

Copy Markdown View Source

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.

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

result()

@type result() :: t() | {:error, Flezha.SDK.Error.t()}

t()

@type t() :: %Flezha.SDK{
  modules: term(),
  namespace: term(),
  namespace_secret: term(),
  server: term(),
  transport: term()
}

Functions

await_termination(handle)

@spec await_termination(result()) :: :ok | {:error, Flezha.SDK.Error.t()}

Block until the runner terminates.

call(runner, relay_id, channel, value)

@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.

child_spec(opts)

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.

close(arg1)

@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_runner(namespace, opts \\ [])

@spec create_runner(String.t(), keyword()) :: result()

Create a runner handle. No connection, no slot claim, no processes.

namespace(sdk)

@spec namespace(t()) :: String.t()

register_factory(e, module)

@spec register_factory(result(), module()) :: result()

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.

relays(runner)

@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.

run(e)

@spec run(result()) :: :ok | {:error, Flezha.SDK.Error.t()}

start/1 then await_termination/1.

send(runner, relay_id, message, channel, opts \\ [])

@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 as flz.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: true in 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 with runtime.relay_not_local for a relay this runner does not hold, and with usage.options_conflict beside msg_id: or key:.

runner is a handle, or the runner server's pid or name.

server(server)

@spec server(result() | pid() | atom()) ::
  {:ok, pid() | atom()} | {:error, Flezha.SDK.Error.t()}

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.

start(e)

@spec start(result()) :: result()

Claim the runner slot and connect. The loser gets runtime.runner_already_running naming the namespace.

unregister_factory(e, module)

@spec unregister_factory(result(), module()) :: result()

Remove a declared relay — the inverse of register_factory/2, taking what it took.