忽略Mix配置文件的缺失,我写了以下内容:
defmodule Test.Supervisor do
use Supervisor
def start_link do
#"name:" will show up in :observer...
Supervisor.start_link(__MODULE__, [], [name: :"root_supervisor"])
end
def init(args) do
children = [
worker(Test.Method, [], [function: :start, id: "my_root_process"]),
]
supervise(children, [strategy: :one_for_one, name: :root])
end
end
defmodule Test do
def start(_type, _args) do
Test.Supervisor.start_link()
end
end
defmodule Test.Method do
def start do
IO.puts("Expect to see me often... #{self}")
end
end
首次运行后崩溃(iex -S mix)而不重新启动应用程序。错误消息是:
=INFO REPORT==== 14-Jan-2016::22:34:04 ===
application: logger
exited: stopped
type: temporary
** (Mix) Could not start application mememe: Test.start(:normal, {}) returned
an error: shutdown: failed to start child: "my_root_process"
** (EXIT) :ok
但是,如果我更改Test.start()
直接致电Test.Method.start()
,请执行以下操作:
defmodule Test do
def start(_type, _args) do
Test.Method.start()
end
end
然后它运行正常,但然后代码将不受监督。 我很确定我在实施或理解方面犯了一个基本错误,但究竟是什么错误呢?
答案 0 :(得分:2)
我会尝试将Test.Method.start
函数更改为Test.Method.start_link
函数,并在您的opts中停止使用function: :start
到worker函数。默认情况下,主管会调用start_link
,并且没有理由破坏这些语义,因为主管将始终链接到受监督的进程。如果这不起作用那么至少我们已经在这方面排除了一个问题。
答案 1 :(得分:1)
您的代码存在一些问题。首先,你需要一个长期运行的功能来监督。类似的东西:
def loop do
receive do
_anything -> IO.puts "Expect to see me often"
end
loop
end
然后在Test.Method
模块中,你必须产生它。
def start do
IO.puts("Starting...")
pid = spawn_link(&loop/0)
{:ok, pid}
end
重要的是,start函数返回元组{:ok, pid_to_supervise}
。它崩溃了你的应用程序,因为主管期望一个进程监视,但只得到:ok
返回的原子IO.puts
。工作者规范不会产生新进程。它需要一个函数,它将返回生成进程的pid。
您还应该将主管与受监督的流程联系起来,因此最后将该功能重命名为start_link
,而不是像@Jason Harrelson所建议的那样将start
重命名。
这应该足以正确启动您的项目。请注意,您不会在观察者Applications
部分中看到您的流程。您没有使用Application
行为,因此您的root_supervisor
会在某处浮动。您可以在Processes
标签中找到它。 my_root_process
是与主管一起使用的ID,因此即使在Processes
标签中也无法显示。
这种方式的产卵过程很容易用于教育目的,但在现实世界系统中,您希望您的过程遵循OTP设计原则。这意味着reacting to system messages,更好logging, tracing and debugging。制作满足所有要求的流程非常困难,但您不必手动完成。所有行为都为您实施这些原则。
因此,不要使用循环生成进程,而是尝试使用GenServer
。