如何在Elixir应用程序中找到工作人员?

时间:2015-03-03 20:45:09

标签: elixir otp

完成入门教程的Supervisor and Application部分,我正在为底部的监督树问题编写单元测试。我尝试启动顶级主管但是它因此错误而失败:

  1) test all buckets die if registry dies (KV.SupervisorTest)
     test/kv/supervisor_test.exs:4
     ** (EXIT from #PID<0.111.0>) shutdown: failed to start child: GenEvent
         ** (EXIT) already started: #PID<0.75.0>

显然应用程序已经启动,因此我需要访问其工作进程。如果我有主管,我可以使用Supervisor.which_children来获取它们。要做到这一点,也许有助于运行kv应用程序:

iex(28)> kvpid = :application.info[:running][:kv]
#PID<0.77.0>

所以现在我有应用程序的PID。是否有某种方法可以从中获取根管理程序进程,或者我是否必须手动将其注册到某处以从测试中获取它?

或者有没有办法直接从他们的名字中找到工人?我试过:erlang.whereis,但找不到工人:

iex(33)> :erlang.whereis KV.Registry
:undefined

我尝试直接使用模块的名称,但这也不起作用:

test "all buckets die if registry dies" do
    reg = KV.Registry
    KV.Registry.create(reg, "shopping")
    {:ok, shopping_bucket} = KV.Registry.lookup(reg, "shopping")

    Process.exit(reg, :shutdown)
    assert_receive {:exit, "shopping", ^shopping_bucket}
end

失败并出现此错误:

1) test all buckets die if registry dies (KV.SupervisorTest)
   test/kv/supervisor_test.exs:4
   ** (ArgumentError) argument error
   stacktrace:
     :erlang.send(KV.Registry, {:"$gen_cast", {:create, "shopping"}})
     (elixir) lib/gen_server.ex:424: GenServer.do_send/2
     test/kv/supervisor_test.exs:6

The code is up on github

3 个答案:

答案 0 :(得分:9)

你找不到KV.Registry,因为你的代码中有拼写错误。你打电话:

worker(KV.Registry, [@manager_name, [name: @registry_name]])

但定义是:

def start_link(event_manager, buckets_supervisor, opts \\ []) do

所以你将[name:KV.Registry]作为buckets_supervisor传递,opts是[],因此你的工人没有以KV.Registry的名义注册。

尝试此修补程序:https://github.com/mprymek/kv/commit/03ce2e4e5ab4287db2fab6de0bb1aeaf0226346f

 iex(1)> :erlang.whereis KV.Registry
 #PID<0.111.0>

答案 1 :(得分:6)

如果您启动主管给它一个名字,您可以让所有工人:

Supervisor.which_children(MyApp.Supervisor)

可能发生的是您尝试启动两个worker(GenEvent, ...)并且他们将有重复的事件。明确地传递:id选项可能会解决它。

答案 2 :(得分:1)

克隆你的回购后,我环顾四周。我无法启动该应用程序。通常,Elixir应用程序可以通过运行以下命令行启动:

iex -S mix

但是当我运行你的应用程序时,我收到以下错误:

** (Mix) Could not start application kv: exited in: KV.start(:normal, [])
** (EXIT) an exception was raised:
    ** (UndefinedFunctionError) undefined function: KV.Supervisor.start_link/0 (module KV.Supervisor is not available)
        KV.Supervisor.start_link()
        (kernel) application_master.erl:272: :application_master.start_it_old/4

这意味着在第5行的lib/kv.ex中,您的应用程序会调用名为KV.Supervisor的主管。我看了你的代码,没有模块有这个名字,但我看到你有模块使用名为KV.Bucket.Supervisor的主管行为。

您需要定义一个名为KV.Supervisor的模块来实现主管行为,或者更新lib/kv.ex中的第5行,以便它调用KV.Bucket.Supervisor.start_link而不是KV.Supervisor.start_link。< / p>

一旦你这样做,你应该能够通过调用这个来获得主管监督的所有过程:

Supervisor.which_children(KV.Supervisor) # Pass in the name of your supervisor module

希望这有帮助!