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 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 the
Task.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
GenServers send tasks to this supervisor, as it will be even easier to trip the
max_restarts of the
Why do the docs say to prefer this approach?