2017-04-27 133 views
1

假设我有以下设置:如何在OTP中启动Supervisor的子工时传入额外的参数?

defmodule NestedSupervisorTree do 
    # this will be the top line supervisor 
    use Supervisor 

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

    def init(:ok) do 
    children = [ 
     supervisor(BranchSupervisor, [], restart: :temporary) 
     #worker(TreeWorker, [], restart: :temporary) 
    ] 

    supervise(children, strategy: :simple_one_for_one) 

    end 

    def start_branch(args) do 
    {_, branch_id} = Supervisor.start_child(__MODULE__, [args]) 
    end 
end 

defmodule BranchSupervisor do 
    # this will be the top line supervisor 
    use Supervisor 

    def start_link(args), do: Supervisor.start_link(__MODULE__, [args], name: __MODULE__) 

    def init(args) do 
    IO.puts "branch init args:" 
    IO.inspect args 
    children = [ 
     worker(TreeWorker, [args], restart: :temporary) 
    ] 

    supervise(children, strategy: :simple_one_for_one) 
    end 

    def start_worker do 
    {_, wid} = Supervisor.start_child(__MODULE__, [3]) 
    end 
end 

defmodule TreeWorker do 
    def start_link(args) do 
    IO.puts "worker args:" 
    IO.inspect args 
    #IO.puts String.codepoints raw 
    {:ok, spawn(fn -> loop end)} 
    end 

    def loop do 
    receive do 
     :stop -> :ok 

     msg -> 
     IO.inspect msg 
     loop 
    end 
    end 
end 

假设我发出在下列顺序IEX终端下面的命令:

iex> {_, pid} = NestedSupervisorTree.start_link 
iex> {_, cid} = NestedSupervisorTree.start_branch(2) 
iex> BranchSupervisor.start_worker 
# returns: 
{:error, 
{:EXIT, 
    {:undef, 
    [{TreeWorker, :start_link, [[2], 3], []}, 
    {: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]}]}}} 

如何在调用注入“额外的参数” BranchSupervisor.start_worker?如果我删除{_, wid} = Supervisor.start_child(__MODULE__, [3])中的“3”作品。这甚至是正确的事情吗?

这主要是一个学习练习。

回答

3

这里的[3]被附加到在argsBranchSupervisor.init/1,这是[[2]]传递给worker,使得最终参数[[2]] ++ [3] =>[[2], 3]。由于名单是二元长,监督员然后调用TreeWorker.start_link/2TreeWorker.start_link([2], 3),所以如果你想接受两个参数这样,你只需要改变start_link接受两个参数:

defmodule TreeWorker do 
    def start_link(arg1, arg2) do 
    # `arg1 == [2]` and `arg2 == 3` here 
    ... 
    end 
end 

此行为被记录在案在Supervisor.start_child/2

:simple_one_for_one的情况下, 定义的子规范监督者的使用和代替child_spec,术语的任意列表 预期。子进程将通过 开始,将给定列表附加到 子规范中的现有函数参数。

+1

谢谢,这种类型的东西通常在文档中被称为某处?我查看了Supervisor.start_child,也许我错过了它,因为它已经晚了...... – Nona

+1

是的,它记录在'Supervisor.start_child/2'中。我在答案中添加了一个链接和相关的引用。 – Dogbert

相关问题