1stSolo
Horde.DynamicSupervisor bypasses Registry?
Hi. My application uses Horde.DynamicSupervisor to spawn processing tasks for unique objects. User should be able to abort the task, and for that purpose I am trying to lookup the task in Horde.Registry to then use Horde.DynamicSupervisor.terminate_child(pid). However the Registry seems to be unaware of the started task.
Startup
In my application.ex, I have
children = [
...
{Horde.Registry, [name: DataImportRegistry, keys: :unique, members: :auto]},
{Horde.DynamicSupervisor, [
name: DataImportSupervisor,
strategy: :one_for_one,
restart: :transient,
distribution_strategy: Horde.UniformQuorumDistribution,
max_restarts: 0,
max_seconds: 1,
members: :auto#supervisor_members()
]}
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
Then in the main process:
{:ok, pid} = Horde.DynamicSupervisor.start_child(
DataImportSupervisor,
%{
id: my_data_object.uuid,
start: {Task, :start_link, [DataImportWorker, :process_data_import, [my_data_object, current_user.id, client_ip]]}
})
But when I do Horde.Registry.lookup(DataImportRegistry, my_data_object.uuid) the output is [].
So what am I missing? Why is Horde’s DynamicSupervisor not registering the Task in the Registry?
If I do Horde.DynamicSupervisor.which_children(DataImportSupervisor) the return value is [{:undefined, #PID<0.2240.0>, :worker, [Task]}] while the task is running. What does :undefined mean?
Thanks! ![]()
Marked As Solved
al2o3cr
The value put in id here is irrelevant, as it’s immediately overwritten by Horde.DynamicSupervisor before starting the child:
It used to be used as an identifier in terminate_child, but that was removed back in 2019:
https://github.com/derekkraan/horde/pull/122
The documentation doesn’t mention this (the third argument is typed as term()), what motivated this observation?
trap_exit is a flag set on the current process; you might use it to, for instance, handle errors arising inside of ImportWorker without crashing the Task.
A pretty standard approach would be to have another process that monitors these Tasks and handles the resulting exit messages.
HOWEVER
You’re teetering on the edge of rolling your own job-tracking system here. Consider picking an off-the-shelf alternative like Verk or Oban that’s already solved a lot of these problems.
Also Liked
al2o3cr
Tasks don’t have a built-in API to register with names because Tasks don’t usually process unsolicited messages from other processes (unlike GenServer, for instance); you’d need to explicitly call receive inside the Task.
That doesn’t stop you from calling Horde.Registry.register/3 in your Task, though:
Task.start(fn ->
Horde.Registry.register(DataImportRegistry, some_uuid, [])
... do stuff ...
end)
Then you can refer to that Task with the tuple {:via, DataImportRegistry, some_uuid} in APIs like Process.whereis.









