Supervisor.start_child() already exists ?

880 views
Skip to first unread message

mraptor

unread,
Nov 4, 2015, 6:46:42 PM11/4/15
to elixir-lang-talk
What I'm doing wrong :

iex(19)> Supervisor.start_child s, worker(Registry,[[name: :reg2]])
{:error, {:already_started, #PID<0.111.0>}}

I want to dynamically start more Registries ?

PS>
the docs mention child_spec but there is no explanation how does it look.
I got the above example from an old thread.

Scott Thompson

unread,
Nov 5, 2015, 10:33:24 AM11/5/15
to elixir-lang-talk
I believe what you want to do is set the restart strategy of your supervisor to :simple_one_for_one and you probably want to set the restart attribute of your worker to "transient".

That way your supervisor will only start the child when you ask it to and if the child ends normally it won't be automatically restarted.

Scott Thompson

unread,
Nov 5, 2015, 10:36:47 AM11/5/15
to elixir-lang-talk
Don't try creating the child spec on your own.  Elixir provides convenient mechanisms to do that for you.  Please see the documentation of the Supervisor.Spec module and in particular the "worker" method in that module.  You will often see that used in something like this:

  def start(_type, _args) do
   
import Supervisor.Spec


    children
= [
      worker
(Adventure.Game, id: :game)
   
]


   
Supervisor.start_link(children, strategy: :one_for_one)
 
end

mraptor

unread,
Nov 5, 2015, 2:07:23 PM11/5/15
to elixir-lang-talk
I already do that.
What I want is to start more new children's on the fly at runtime.

Alexei Sholik

unread,
Nov 5, 2015, 2:10:19 PM11/5/15
to elixir-l...@googlegroups.com
Look more closely at the spec and what the docs have to say about Supervisor.start_child when the strategy is :simple_one_for_one. http://elixir-lang.org/docs/stable/elixir/Supervisor.html#start_child/2

--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-talk/ca0ad65c-5bc6-499a-8cce-6c7ec8687641%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

mraptor

unread,
Nov 5, 2015, 2:39:32 PM11/5/15
to elixir-lang-talk
I see !!!
It uses the arguments (i.e. :name) that I provided in the configuration instead the one I pass in start_child() call if the strategy  is :simple_one_for_one !
But why would it do that ? It does not make any logical sense to disregard the argument you pass and instead use some other arguments you've buried in the config.
It make more sense to be the opposite the most specific call should win !?! puzzled...

Should I change the strategy to :one_for_one instead.
I'll try it.

thanks.

Alexei Sholik

unread,
Nov 5, 2015, 4:01:18 PM11/5/15
to elixir-l...@googlegroups.com
You misunderstood. If you have a :simple_one_for_one supervisor with a spec like worker(MyModule, [arg1]), then the call

  Supervisor.start_child(my_supervisor, [arg2, arg3])

it will start a new child by calling

  MyModule.start_link(arg1, arg2, arg3)

A :simple_one_for_one supervisor always uses the single child spec that you provided when you started the supervisor itself. You can still pass additional arguments to the start_child() call. This is very useful for spawning many instances of a single type of process (in other words, backed by a single implementation module).

When using any other strategy, you pass a spec to start_child() and it gets appended to the list of specs the supervisor has, where each spec defines a different kind of process.

mraptor

unread,
Nov 5, 2015, 6:21:09 PM11/5/15
to elixir-lang-talk
Then how did you create new children ?!

PS> BtW I checked I use :one_to_one, not :simple_one_to_one

mraptor

unread,
Nov 5, 2015, 6:28:07 PM11/5/15
to elixir-lang-talk
here is my current config :

defmodule Ae.Supervisor do

   use Supervisor

   def start_link do
      Supervisor.start_link(__MODULE__, :ok)
   end

   @registry :registry

   def init(:ok) do
      children = [ worker(Registry, [[name: @registry]]) ]
      supervise children, strategy: :one_for_one
   end

end

and when I do :

iex(1)> {:ok, s} = Ae.Supervisor.start_link
{:ok, #PID<0.91.0>}
iex(2)> import Supervisor.Spec
nil
iex(3)> Supervisor.start_child s, worker(Registry,name: :reg2)   
{:error, {:already_started, #PID<0.92.0>}}

iex(4)> Supervisor.which_children s
[{Registry, #PID<0.92.0>, :worker, [Registry]}]

dennis zhuang

unread,
Nov 5, 2015, 6:39:30 PM11/5/15
to elixir-l...@googlegroups.com

--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
庄晓丹
Email:        killm...@gmail.com xzh...@avos.com
Site:           http://fnil.net
Twitter:      @killme2008


mraptor

unread,
Nov 5, 2015, 7:32:08 PM11/5/15
to elixir-lang-talk
  def init(:ok) do
      children = [ worker(Registry, []) ]
      supervise children, strategy: :simple_one_for_one
  end

-------------

iex(1)> {:ok,s} = Ae.Supervisor.start_link

{:ok, #PID<0.91.0>}
iex(2)> import Supervisor.Spec
nil
iex(3)> Supervisor.start_child s, worker(Registry,[[name: :reg2]])
{:error,
 {:EXIT,
  {:badarg,
   [{:erlang, :apply,
     [Registry, :start_link,
      {Registry, {Registry, :start_link, [[name: :reg2]]}, :permanent, 5000,
       :worker, [Registry]}], []},
    {:supervisor, :do_start_child_i, 3, [file: 'supervisor.erl', line: 359]},
    {:supervisor, :handle_call, 3, [file: 'supervisor.erl', line: 384]},
    {:gen_server, :try_handle_call, 4, [file: 'gen_server.erl', line: 629]},
    {:gen_server, :handle_msg, 5, [file: 'gen_server.erl', line: 661]},
    {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 240]}]}}}

iex(4)> Supervisor.which_children s
[]


--------
If it is :one_for_one ... I need name to start the Registry (by design).

iex(1)> {:ok,s} = Ae.Supervisor.start_link
** (EXIT from #PID<0.98.0>) shutdown: failed to start child: Registry
    ** (EXIT) {:err, "You need to specify :name to start a new registry"}

mraptor

unread,
Nov 5, 2015, 7:34:43 PM11/5/15
to elixir-lang-talk
I've got it :

iex(7)> Supervisor.start_child s, [[name: :reg2]]
{:ok, #PID<0.98.0>}
iex(8)> Supervisor.start_child s, [[name: :reg3]]
{:ok, #PID<0.100.0>}
iex(9)> Supervisor.which_children s
[{:undefined, #PID<0.98.0>, :worker, [Registry]},
 {:undefined, #PID<0.100.0>, :worker, [Registry]}]
iex(10)>
Reply all
Reply to author
Forward
0 new messages