# `Ramal.Supervisor`
[🔗](https://github.com/agustinrojas1/ramal/blob/v0.2.0/lib/ramal/supervisor.ex#L1)

The supervision tree of Ramal. Add it to the host application's tree:

    children = [
      MyApp.Repo,
      {Ramal.Supervisor, storage: Ramal.Storage.Postgres, repo: MyApp.Repo}
    ]

It starts a `Registry` keyed by branch id, a `DynamicSupervisor` for the branch processes, and owns the ETS
tables the library needs. There is one instance per node; its configuration lives in `:persistent_term`.

## Options

  * `:storage` - a `Ramal.Storage` module, default `Ramal.Storage.ETS`
  * `:idle_timeout` - milliseconds without a call before a branch persists and unloads, default five minutes
  * `:max_active_branches` - the most open and proposed branches one domain may have, default `nil` (no limit).
    `Ramal.branch/2` and `Ramal.fork/2` return `{:error, %Ramal.Error{reason: :limit_reached}}` at the limit. A soft
    limit: callers that create at the same moment can pass it by their own number. Counting asks the storage
    for a count (`c:Ramal.Storage.count/3`), so it costs one query with `Ramal.Storage.Postgres`.
  * `:branch_rate` - `{count, milliseconds}`: the most branches (created or forked) one domain may get in a window,
    default `nil`. Fixed windows, counted in memory on this node, and shared by `branch/2` and `fork/2`. Nodes do not
    add up: a cluster allows the rate on each node.
  * `:max_heap_size` - the heap limit of each branch process in words, default 25 million (200 MB on a 64-bit
    machine). A branch exceeding it is killed and its last persisted state remains.
  * any other option is the storage config, for example `:repo` for the Postgres backend

Both limits are off by default, so adding them is the only change; see ADR 0016 for why they exist (a client that can
reach `Ramal.fork/2`, such as the inspector, can otherwise start a process and a stored row per call).

`idle_timeout` and `max_heap_size` belong to the supervisor, not to a branch, because a per-branch value would be
forgotten when the branch is unloaded and loaded again.

## Example

    iex> opts = [storage: Ramal.Storage.ETS, idle_timeout: 1_000, repo: MyApp.Repo]
    iex> config = Ramal.Supervisor.build_config(opts)
    iex> {config.storage, config.idle_timeout, config.storage_config}
    {Ramal.Storage.ETS, 1000, [repo: MyApp.Repo]}

# `config`

```elixir
@type config() :: %{
  storage: module(),
  storage_config: keyword(),
  idle_timeout: timeout(),
  max_heap_size: pos_integer(),
  limits: %{
    max_active: pos_integer() | nil,
    rate: {pos_integer(), pos_integer()} | nil
  }
}
```

# `build_config`

```elixir
@spec build_config(keyword()) :: config()
```

Builds the runtime config from the supervisor options.

## Example

    iex> Ramal.Supervisor.build_config([]).idle_timeout
    300000

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

---

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