def start(_type, _args) do
import Supervisor.Spec
# TODO
children = [
supervisor(MyApp123.Module1, []),
supervisor(MyApp123.Module2, []),
supervisor(MyApp123.Module3, []),
]
opts = [strategy: :one_for_one, name: MyApp123.Supervisor]
Supervisor.start_link(children, opts)
end
What’s a way to add a children MyApp123.Module4 to that list and launch it dynamically, at runtime? Say, after I click a button on a page in my web app.
Although you can also have MyApp123.Module1 define a child_spec/1 function returning that map. Then you can continue to have children = [MyApp123.Module1, ...] even if MyApp123.Module1 doesn’t use Supervisor.
To be noted also, use Supervisor isn’t the only one that defines a child_spec/1 in the module: GenServer for example does too. In other words, if MyApp123.Module1uses GenServer you can also have children = [MyApp123.Module1, ...] without doing any extra work.
Let’s say that module is called MyDynSup, and that you start it with the name: MyDynSup option. Then, you can Enum.each([MyApp123.Module1, MyApp123.Module2, MyApp123.Module3], fn mod -> DynamicSupervisor.start_child(MyDynSup, mod) end).
Later, to start a new child, simply call DynamicSupervisor.start_child(MyDynSup, MyApp123.Module3) (or DynamicSupervisor.start_child(MyDynSup, {MyApp123.Module3, []}) if you prefer).
Note that per the docs, the DynamicSupervisor starts without any children: they must be added after starting.
def start(_type, _args) do
children = [
{DynamicSupervisor, strategy: :one_for_one, name: MyApp123.DynamicSupervisor}
]
opts = [strategy: :one_for_one, name: MyApp123.Supervisor]
Supervisor.start_link(children, opts)
# MyApp123.ModuleX have to have a functional child_spec/1 to generate the detailed
# child specification
#
DynamicSupervisor.start_child(MyApp123.DynamicSupervisor, MyApp123.Module1 )
DynamicSupervisor.start_child(MyApp123.DynamicSupervisor, MyApp123.Module2 )
DynamicSupervisor.start_child(MyApp123.DynamicSupervisor, MyApp123.Module3 )
# ... or use Enum.each as above (or recursion ...)
# ... and personally I prefer a module based DynamicSupervisor rather than this ...
end
The generalized approach is to move the specifics of the child specification into the module implementing the process via module.child_spec(arg) rather than having to spell it out in detail in the children list.