3 ms·
I'm talking about the behavior of the one_for_one supervisor: defmodule Testing.Application do use Application @impl Application def sta
by dqv 2y ago
I'm talking about the behavior of the one_for_one supervisor:
defmodule Testing.Application do
use Application
@impl Application
def start(_type, _args) do
children = []
opts = [strategy: :one_for_one, name: Testing.Supervisor]
Supervisor.start_link(children, opts)
end
end
defmodule Testing.Server do
use GenServer
def start_link(_), do: GenServer.start_link(__MODULE__, [])
@impl GenServer
def init(_), do: {:ok, nil}
end
When you try to start more than one child, it fails:
Erlang/OTP 25 [erts-13.2.2.11] [source] [64-bit] [smp:14:14] [ds:14:14:10] [async-threads:1] [jit:ns]
Interactive Elixir (1.17.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Supervisor.start_child(Testing.Supervisor, {Testing.Server, []})
{:ok, #PID<0.135.0>}
iex(2)> Supervisor.start_child(Testing.Supervisor, {Testing.Server, [:x]})
{:error, {:already_started, #PID<0.135.0>}}
But defining a child spec that sets the id:
defmodule Testing.Server do
use GenServer
def start_link(_), do: GenServer.start_link(__MODULE__, [])
def child_spec(arg) do
id = Keyword.get(arg, :id)
%{id: id, start: {__MODULE__, :start_link, [[]]}}
end
@impl GenServer
def init(_), do: {:ok, nil}
end
solves the problem:
Erlang/OTP 25 [erts-13.2.2.11] [source] [64-bit] [smp:14:14] [ds:14:14:10] [async-threads:1] [jit:ns]
Interactive Elixir (1.17.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Supervisor.start_child(Testing.Supervisor, {Testing.Server, id: 1})
{:ok, #PID<0.135.0>}
iex(2)> Supervisor.start_child(Testing.Supervisor, {Testing.Server, id: 1})
{:error, {:already_started, #PID<0.135.0>}}
iex(3)> Supervisor.start_child(Testing.Supervisor, {Testing.Server, id: 2})
{:ok, #PID<0.136.0>}
- simoncion 2y ago> I'm talking about the behavior of the one_for_one supervisor: Oh, sure, you can vary the ID in non-'simple_one_for_one' supervisors there to make that work. Apologies for inducing you to write out all that transcript and code. But, OP's claim was: > - a lot of knowledge is implicit (try checking if you can dynamically add children to a Supervisor) which is just not fucking true no matter how you slice it. It's true that the relevant documentation doesn't literally say "Calling 'start_child/2' is valid for any kind of 'supervisor'. That's why it's here... to dynamically add children to a 'supervisor'.", but if one bothers to read the docs on supervisors and the function in question it's clear that that's the entire point of 'start_child/2'.