I was digging into child specs a bit to re-orient myself around how to write a nice-to-write and nice-to-read supervision tree. I find module based supervisors can get a bit hard to parse at a glance as the structure can end up spread across files.
So with the Supervisor.Spec helpers deprecated since last I looked I figured I need to get familiar with child specs in more depth.
Something that tripped me up was that Supervisor doesn’t seem to follow the child spec convention. So I can’t use:
{Supervisor, [my_children, my_opts]}
(edit: corrected example tuple)
Is there a nice and clean way of setting up a Supervisor, without a module, in the tree, beyond writing a full child_spec map? I find them visually a bit noisy, though they are quite simple and work well.
The only supported versions in the list of children are module(), {module, arg} or :supervisor.child_spec(). There’s no tuple-3 option at all. I blogged about that system in more detail yesterday: Child Specs in Elixir
So you need to send everything in one arg to be sent to child_spec/1. You could do something like this:
defmodule MySupervisor do
def child_spec(init_arg) do
{children, opts} = extract_from_init_arg(init_arg)
%{
id: __MODULE__
start: {Supervisor, :start_link, [children, opts]}
type: :supervisor
}
end
end
Which would allow for {MySupervisor, some_children_and_opts_format}. If that’s actually cleaner than a private function building the child_spec manually I’m not so sure about, given that the list of children is unlikely just some small argument to place in the tuple format.
Thanks, brainfart on the 3-tuple. Edited that. As it wasn’t the point of the question.
But that MySupervisor approach was something I was thinking about, which yes. It would be cleaner to me. I’m not certain why Supervisor doesn’t offer it? But then again child_spec/2 does something fairly different. So maybe to avoid confusion?
I was annoyed by this too and at previous company wrote a helper supervisor/2 function, so I could write supervisor(children, opts) directly as a child. Perhaps submit a proposal to elixir-lang-core.
As an aside and self-ad, Parent.Supervisor supports {Parent.Supervisor, {children, opts}} and since Parent doesn’t have the concept of strategy, I think I should also support {Parent.Supervisor, children}.