Supervisors

If restarts exceed max_restarts within max_seconds, the supervisor itself exits (escalation up the tree).

33.1 Starting a supervisor

defmodule MyApp.Application do
  use Application

  @impl true
  def start(_type, _args) do
    children = [
      {Stack, [:initial]},                      # calls Stack.start_link([:initial])
      {Task.Supervisor, name: MyApp.TaskSup},
      {Registry, keys: :unique, name: MyApp.Registry},
      MyApp.Cache                               # same as {MyApp.Cache, []}
    ]

    opts = [strategy: :one_for_one, name: MyApp.Supervisor, max_restarts: 3, max_seconds: 5]
    Supervisor.start_link(children, opts)
  end
end

33.2 Strategies

When a child dies...

restart only that child restart all children restart that child and all children started after it

If restarts exceed max_restarts within max_seconds, the supervisor itself exits (escalation up the tree).

33.3 Child specs

use GenServer, restart: :transient customizes the generated child_spec/1.

only on abnormal exit

%{
  id: MyWorker,
  start: {MyWorker, :start_link, [arg]},
  restart: :permanent,      # :permanent | :temporary | :transient
  shutdown: 5_000,          # ms, or :brutal_kill, or :infinity (for supervisors)
  type: :worker             # :worker | :supervisor
}

33.4 Module-based supervisor

defmodule MyApp.WorkerSup do
  use Supervisor
  def start_link(arg), do: Supervisor.start_link(__MODULE__, arg, name: __MODULE__)

  @impl true
  def init(_arg) do
    children = [{Worker, 1}, {Worker, 2} |> Supervisor.child_spec(id: :worker2)]
    Supervisor.init(children, strategy: :one_for_one)
  end
end

33.5 Supervision tree design

Principles: start order matters (dependencies first), put volatile processes deeper in the tree, group things that must restart together.

MyApp.Supervisor (one_for_one)
├── MyApp.Repo
├── MyApp.PubSub
├── MyApp.Cache.Supervisor (rest_for_one)
│   ├── MyApp.Cache.Table   (owns ETS)
│   └── MyApp.Cache.Janitor
├── MyApp.SessionSupervisor (DynamicSupervisor)
└── MyAppWeb.Endpoint

33.6 Inspecting

Supervisor.which_children(MyApp.Supervisor)
Supervisor.count_children(MyApp.Supervisor)
Supervisor.terminate_child / restart_child / delete_child
:observer.start()   # GUI view of the tree