Elixir - 基本管理程序设置崩溃,而不是重新启动子进程

时间:2016-01-14 22:40:40

标签: concurrency elixir otp supervisor

忽略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

然后它运行正常,但然后代码将不受监督。 我很确定我在实施或理解方面犯了一个基本错误,但究竟是什么错误呢?

2 个答案:

答案 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