In the Task.Supervisor
docs, it states
You can also start it by calling start_link/1 directly … But this is recommended only for scripting and should be avoided in production code. Generally speaking, processes should always be started inside supervision trees.
However, this is not elaborated on.
In an application I’m writing, my supervision tree contains some number of instances of a single GenServer
. This GenServer
will spawn several tasks during its lifetime whose return value I care about; they are not fire and forget. As part of the GenServer
’s state, I store the pid of a Task.Supervisor
that I start in GenServer.init/1
. In my mind, this makes sense, because if theTask.Supervisor
crashes (due to too many task failures or what have you), my GenServer
crashes and its supervisor restarts it.
If, however, I were to run the Task.Supervisor
and the GenServer
under the same supervision tree, I foresee race conditions where the GenServer
is trying to spawn a task on a currently restarting Task.Supervisor
(e.g. imagine that the Task.Supervisor
has crashed, and before its supervisor restarts it, the GenServer
attempts to spawn a task… this will surely fail). I can imagine this becoming exacerbated as more of the GenServer
s send tasks to this supervisor, as it will be even easier to trip the max_restarts
of the Task.Supervisor
,
Why do the docs say to prefer this approach?