# `Flezha.SDK.Local`
[🔗](https://github.com/flezha/flezha_elixir_sdk/blob/v0.1.0/lib/flezha/sdk/local.ex#L1)

Running a declared relay graph in this process, with no controller.

`start/2` takes the `Flezha.SDK.Relay` module you deploy and runs the graph
its `channels/1` already declares on `flz_core`'s local run, the same
runtime a deployed relay runs on: entry decode, edge transforms and keying,
one Cell per resolved key with its own mailbox, the retry ladder. Nothing
about the class changes: no local-mode callback, no second declaration.

What a local run has not got: durability of any kind, plugins, placement and
migration, the dead-letter queue, observability export, authz and
multi-runner scale. Every one of those needs a controller, and every run says
so through `Logger` before it does any work. A class that runs in steps, or under
the effectively-once tier, is refused as `runtime.local_needs_controller`.

## Running a graph

    {:ok, run} = Flezha.SDK.Local.start(WordCount)
    :ok = Flezha.SDK.Local.on_output(run, "counts", &IO.puts(&1.payload))
    :ok = Flezha.SDK.Local.feed(run, "lines", "The quick brown fox")
    :ok = Flezha.SDK.Local.feed(run, "lines", "the lazy dog")
    :ok = Flezha.SDK.Local.run_until_idle(run, 5_000)
    :ok = Flezha.SDK.Local.close(run)

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `close`

```elixir
@spec close(pid()) :: :ok
```

Close the run, delivering what it already released. A run whose starter has
already gone is stopped by that exit; asking again is answered, never raised.

# `feed`

```elixir
@spec feed(pid(), String.t(), term()) :: :ok | {:error, Flezha.SDK.Error.t()}
```

Feed one value to a declared entry channel: the bytes a controller would
forward, decoded by that channel's own parser. A value that is not a binary
is encoded as an output with no serializer of its own encodes it. Refuses a
name the declaration does not carry as an entry.

# `on_output`

```elixir
@spec on_output(pid(), String.t(), (Flezha.SDK.Local.Output.t() -&gt; any())) ::
  :ok | {:error, Flezha.SDK.Error.t()}
```

Deliver every value released on the output `channel` to `fun`, in release
order. Refuses a name the declaration does not carry as an output.

# `run_until_idle`

```elixir
@spec run_until_idle(pid(), non_neg_integer()) :: :ok | {:error, Flezha.SDK.Error.t()}
```

Block until the graph has nothing left to do and every value it released
has been delivered, or `budget_ms` elapses — which is reported rather than
passed off as done.

# `start`

```elixir
@spec start(module(), keyword()) :: {:ok, pid()} | {:error, Flezha.SDK.Error.t()}
```

Start `module`'s declared graph in this process. Refuses a declaration the
core refuses, and one that asks for something only a controller can answer.
`:relay_id` names the run (default `"<factory_id>-local"`).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
