I am reading through the The Little Elixir and OTP GuideBook and working on the example where you create a worker pool similar to Erlang’s Poolboy library. Since the book was published before DynamicSupervisor was created, the text has you create a Supervisor with the deprecated :simple_one_for_one strategy for managing a dynamic worker pool. I decided to try to port the code in the book to Elixir 1.6 code and used a DynamicSupervisor instead.
At this point everything was making sense, use a regular Supervisor when you have a static known list of children and use a DynamicSupervisor when you want to dynamically start/stop children. However, just a couple pages later in the book the sample code has you call Supervisor.start_child from a GenServer on a supervisor that is NOT using the :simple_one_for_one strategy, but rather the :one_for_all strategy. At this point I was confused. If you can call Supervisor.start_child with an arbitrary child spec on a supervisor that is neither a DynamicSupervisor nor a :simple_one_for_one supervisor, what is the purpose of the DynamicSupervisor?
I went to the Elixir docs and the function signature for Supervisor.start_child/2 and DynamicSupervisor.start_child/2 are identical. Can someone please explain the difference between the two?
The GenServer is responsible for starting worker supervisor and workers if I do recall correctly.
It stores sup, and worker_sup.
It uses sup to start worker_sup, as one_for_all
It uses worker_sup to start workers, as single_one_for_one
Which sup do You mean?
The difference between them is not on the
start_child/2 function but on how they manage children. For example, because there isn’t an intrinsic ordering, the DynamicSupervisor shuts all children down concurrently, while a regular Supervisor always assume an ordering. Similarly, on restart, the DynamicSupervisor is always empty, while the regular Supervisor usually starts with a tree, etc.
Yeah, sorry for the confusion. There is Pooly.Supervisor, which starts Pooly.Server (a GenServer) in its init callback. Pooly.Server then starts Pooly.WorkerSupervisor as a child under Pooly.Supervisor (e.g. Supervisor.start_child(pooly_dot_supervisor_pid, spec_for_pooly_dot_workersupervisor)
Thanks for the response José! So is it fair to say that there is nothing stopping one from dynamically starting/stopping children from a standard Supervisor? Is it just more idiomatic/safe to do it with a DynamicSupervisor?