I’m having an issue with the syntax for adding a process (let’s say an Agent)
to a DynamicSupervisor supervision tree.
The issue is that I don’t know how to create a map with the correct specs for a
child that support a named global process (Agent in this case, but should work
with process).
# Create the DynamicSupervisor.
{:ok, dyn_sup} = DynamicSupervisor.start_link(DynamicSupervisor, strategy: :one_for_one, name: :dyn_sup)
# Prepare the child_spec map
child_spec = %{
id: "new agent",
# This works, `start_child/2` works with this map
# start: {Agent, :start_link, [fn -> %{im_global: true} end]},
# This does not work. `start_child/2` does not work with this map
start: {Agent, :start_link, [fn -> %{im_global: true} end, name: {:global, "im global child spec"}]},
shutdown: 5_000,
restart: :permanent,
type: :worker,
}
# This fails
{:ok, child} = DynamicSupervisor.start_child(dyn_sup, child_spec)
# Proof that the child_spec was created successfully is that we could do:
%{im_global: true} = Agent.get({:global, "im global child spec"}, & &1)
Do you have any insight on how I should organize the args
in the start
key
in child_spec
?
Thank you,
Paulo
Sample app
Here is an example app that showcases the behavior I am talking about. Run mix test
and you should see the failure.

Try
child_spec = %{
id: "new agent",
+ start: {Agent, :start_link, [fn -> %{im_global: true} end, [name: {:global, "im global child spec"}]]},
- start: {Agent, :start_link, [fn -> %{im_global: true} end, name: {:global, "im global child spec"}]},
shutdown: 5_000,
restart: :permanent,
type: :worker,
}
Keyword lists are tricky!
2 Likes
Here’s the “diff” that makes the test pass
diff --git a/test/supervisor_example_app_test.exs b/test/supervisor_example_app_test.exs
index fe2021d..4fd09ed 100644
--- a/test/supervisor_example_app_test.exs
+++ b/test/supervisor_example_app_test.exs
@@ -21,10 +23,12 @@ defmodule SupervisorExampleAppTest do
# This works, `start_child/2` works with this map
# start: {Agent, :start_link, [fn -> %{im_global: true} end]},
# This does not work. `start_child/2` does not work with this map
- start: {Agent, :start_link, [fn -> %{im_global: true} end, name: {:global, "im global child spec"}]},
+ start:
+ {Agent, :start_link,
+ [fn -> %{im_global: true} end, [name: {:global, "im global child spec"}]]},
shutdown: 5_000,
restart: :permanent,
type: :worker,
}
# Based on the `start` config above, the below fails
@@ -34,6 +38,6 @@ defmodule SupervisorExampleAppTest do
assert %{im_global: true} = Agent.get(child, & &1)
# I want the following to work eventually
- assert %{im_global: true} = Agent.get("im global child spec", & &1)
+ assert %{im_global: true} = Agent.get({:global, "im global child spec"}, & &1)
end
end
2 Likes
Fantastic! Thank you @idi527! (I feel bad writing your username…
)
2 Likes