Finding ids of children in DynamicSupervisor

I am trying to run a list of tasks under a Dynamic Supervisor. Imagine that it is a URL downloader. I need to know if they are still running, and maybe talk to them to change their configuration in-flight.

In order to talk to them, each task is registered as {Download, "www.example.com"} in a global registry. Now, the application runs a dynamic number of sub-applications, so that there is

  • {DynamicSupervisor “customer-a”}
  • {DynamicSupervisor “customer-b”}

So I basically want to know which Download modules are running under {DynamicSupervisor "customer-a"} - so I call it and get a list of children like:

[{:undefined, #PID<0.14119.0>, :worker, [Downloader]},
{:undefined, #PID<0.14123.0>, :worker, [Downloader]}]

The issue is that only the module is reported back, so I cannot know which one it is - I can get the PID, get all the pids out of Registry, and keep the ones that match both, so I can look up the same information. But this seems quite a mouthful.

Is there a way to change the name of the module in the output, or tag it somehow? The first field is supposed to be the :id and it would be perfect, but in DynamicSupervisor, as per the docs (why?) it is always :Undefined.

1 Like

Can you show how have you defined the DynamicSupervisor in your application file as a start?

I would register tasks with {client_id, url} in the registry.
So you can use Registry.match to filter keys for a given client_id.

Note that you may not need multiple supervisors, you can start all downloaders under the same. Except if your “sub applications” are OTP applications.

2 Likes

Take a look at the DynamicSupervisor’s extra_arguments. I use it all the time in combo with a via_tuple function and child_spec function on the children to namespace the child processes within the registry. You could use the customer id for example.

The other option is to manually register the children into another registry during the init with the customer id passed by the extra_argument.

Let me know if you need an example. I’m just on a tablet, or I’d have posted one

2 Likes

This sounds interesting - I was able to force the :modules field, and that’s what I get displayed in:

iex(13)> DynamicSupervisor.which_children(pp)
[{:undefined, #PID<0.1234.0>, :worker, [Pizza, Pineapple]}]

So that would be perfect for my use-case - if not that the code only allows atoms in there: https://github.com/elixir-lang/elixir/blob/7e4fbe657dbf9c3e19e3d2bd6c17cc6d724b4710/lib/elixir/lib/dynamic_supervisor.ex#L379

What I don’t get is - why can’t you just have an id, or the parameters, available in the list I get from which_children?

As to why is it :undefined, and why can’t it be set, it’s because DynamicSupervisor doesn’t enforce the id.

In a normal Supervisor, the id is used to ensure that if you’re supervising the same type of process multiple times (imagine like a connection pooler), that it can manage them separately, start them in the correct order, restart them in the correct order, or do other necessary steps for other supervision strategies. That id has to be known before the child process is started, because the a typical Supervisor has to be able to make those decisions for the strategy as part of the children startup.

In a DynamicSupervisor, there’s no concept of other supervision strategies, because all the children are essentially independent of one another, so you don’t need to worry about distinguishing them prior to their startup, since you start them up later, after the DynamicSupervisor is already up (or at least in a handle_continue, after the init)

Some questions that’ll help me better understand your use-case

  • What’s the actual reason you need know which children are running under a given DynamicSupervisor?
  • Do you need to be able to “know” value/domain of the Downloader before calling it? or is just having the list of children enough
  • It seems like you’re wanting to know if multiple Download processes are for the same domain, but different customers. Do you only want to run one but have it be “linked” to multiple customers? Do you want to have multiple processes but just need to be able to quickly check for the existence of other Download processes for the same domain?
1 Like