如何在Elixir应用程序中找到工作人员?
通过入门教程的一部分,我正在为底部的监督树问题编写一个单元测试。我尝试启动顶级主管,但失败,出现以下错误:如何在Elixir应用程序中找到工作人员?,elixir,otp,Elixir,Otp,通过入门教程的一部分,我正在为底部的监督树问题编写一个单元测试。我尝试启动顶级主管,但失败,出现以下错误: 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 ** (EXI
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>
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
现在我有了应用程序的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
** (EXIT from #PID<0.111.0>) shutdown: failed to start child: GenEvent
** (EXIT) already started: #PID<0.75.0>
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
.克隆完你的回购协议后,我四处看看。我无法启动应用程序。通常,可以通过运行以下命令行启动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\u link
而不是KV.Supervisor.start\u link
一旦您这样做,您应该能够通过调用以下命令获得主管正在监督的所有流程:
Supervisor.which_children(KV.Supervisor) # Pass in the name of your supervisor module
希望这有帮助 您找不到KV.Registry,因为您的代码中有输入错误。你打电话:
worker(KV.Registry, [@manager_name, [name: @registry_name]])
但定义是:
def start_link(event_manager, buckets_supervisor, opts \\ []) do
因此,您通过[name:KV.Registry]作为您的主管,opts为[],因此您的工人没有以KV.Registry的名义注册
请尝试此修补程序:
iex(1)>:erlang.whereis KV.Registry
#PID
如果你给主管起了一个名字,那么你可以让所有工人都有:
Supervisor.which_children(MyApp.Supervisor)
可能发生的情况是,您正在尝试启动两个
worker(GenEvent,…)
,它们将有重复的事件。明确传递:id
选项很可能会解决此问题。KV.Supervisor的定义从第42行开始:。我不确定我是否理解。克隆回购协议还有一步。您还必须签出分支:git checkout-b s_o_问题来源/s_o_查找_工作人员_问题。要获取此问题的分支,您必须添加以下步骤:$git checkout-b s_o_问题来源/s_查找_工作人员_问题
P.s。如果您的代码正确运行取决于某个参数,那么它可能是强制性的。如果您将函数定义为“def start_link(event_manager,bucket_supervisor,opts)”,则不会发生这种情况。更改工作线程做到了这一点:worker(KV.Registry,[@manager_name,@bucket_sup_name,[@Registry_name])
发生的情况如下:iex(1)>supervisor。哪个子级(KV.supervisor)**(退出)退出:GenServer.call(KV.Supervisor,:哪个子级,:无穷大)**(退出)无进程(elixir)lib/gen_server.ex:356:GenServer.call/3
,即使我可以看到KV.Supervisor已从日志消息启动。我只有一个对工作者(GenEvent,…)的调用
。啊,我明白了。我需要将KV.Supervisor.start\u链接主体更改为Supervisor.start\u链接(\uu模块\uuuuuu,:好,[name:KV.Supervisor])
。现在您的代码片段可以工作了。