Issue creating a `child_spec` map when adding to a `DynamicSupervisor` (or any supervisor)

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.

:wave:

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… :frowning: )

2 Likes