【问题标题】:Elixir simple_one_for_one supervisor's start_child terminates with undefined handle_call/3Elixir simple_one_for_one 主管的 start_child 以未定义的 handle_call/3 终止
【发布时间】:2017-05-08 17:45:09
【问题描述】:

我正在尝试使用 gproc 为进程注册表创建一个主管。以下代码定义了主管:

defmodule QueueSupervisor do
    use Supervisor

    def start_link do
        GenServer.start_link(__MODULE__, [], name: :model_queue)
    end

    def create_queue(name) do
        Supervisor.start_child(:model_queue, [name])
    end

    def init([]) do
        children = [
            worker(ModelQueueWriter, [])
        ]

        supervise(children, strategy: :simple_one_for_one)
    end

    def terminate(reason,_state) do
        Logger.info "terminating: #{inspect self}: #{inspect reason}"
        :ok
    end
end

主管一开始就很有魅力。但是,当调用create_queue(:some_name) 时,我得到一个未定义的函数错误:

function QueueSupervisor.handle_call({:start_child, [:some_name]}, {#PID<0.2278.0>, #Reference<0.0.3.3361>}, {{:simple_one_for_one, 3, 5}, [{ModelQueueWriter, {ModelQueueWriter, :start_link, []}, :permanent, 5000, :worker, [ModelQueueWriter]}]}

ModelQueueWriter是一个简单的genserver,使用gproc进行命名:

defmodule ModelQueueWriter do
    use GenServer

    def start_link(queue_name) do
        GenServer.start_link(__MODULE__, [], name: via_tuple(queue_name))
    end

    defp via_tuple(queue_name) do
        {:via, :gproc, {:n, :l, {:model_queue, queue_name}}}
    end

    def init(_), do: %{:ok, []}
end

我正在使用 elixir 1.4 并按照主管的文档,加上这个example

我错过了什么?


根据要求提供完整的错误消息:

** (exit) exited in: GenServer.call(:model_queue, {:start_child, [:some_name]}, :infinity)
    ** (EXIT) an exception was raised:
        ** (UndefinedFunctionError) function QueueSupervisor.handle_call/3 is undefined or private
        (ecohesion_web) QueueSupervisor.handle_call({:start_child, [:model_queue]}, {#PID<0.2278.0>, #Reference<0.0.1.8826>}, {{:simple_one_for_one, 3, 5}, [{ModelQueueWriter, {ModelQueueWriter, :start_link, []}, :permanent, 5000, :worker, [ModelQueueWriter]}]})
        (stdlib) gen_server.erl:629: :gen_server.try_handle_call/4
        (stdlib) gen_server.erl:661: :gen_server.handle_msg/5
        (stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
11:01:17.094 [error] GenServer :model_queue terminating
** (UndefinedFunctionError) function QueueSupervisor.handle_call/3 is undefined or private
(ecohesion_web) QueueSupervisor.handle_call({:start_child, [:model_queue]}, {#PID<0.2278.0>, #Reference<0.0.1.8826>}, {{:simple_one_for_one, 3, 5}, [{ModelQueueWriter, {ModelQueueWriter, :start_link, []}, :permanent, 5000, :worker, [ModelQueueWriter]}]})
(stdlib) gen_server.erl:629: :gen_server.try_handle_call/4
(stdlib) gen_server.erl:661: :gen_server.handle_msg/5
(stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Last message: {:start_child, [mode_queue]}
State: {{:simple_one_for_one, 3, 5}, [{ModelQueueWriter, {ModelQueueWriter, :start_link, []}, :permanent, 5000, :worker, [ModelQueueWriter]}]}
       (elixir) lib/gen_server.ex:737: GenServer.call/3
(ecohesion_web) lib/ecohesion_web/archive_writer/queue_supervisor.ex:28: QueueSupervisor.create_queue/1

【问题讨论】:

  • 你能发布完整的错误消息,包括堆栈跟踪吗?
  • 我编辑了帖子。
  • QueueSupervisor.start_link 中的错字:GenServer.start_link 应为 Supervisor.start_link
  • 哇哦。太遗憾了。这实际上解决了问题,我感到羞耻!为什么这甚至可以正确启动主管?如果您创建一个答案,我会接受它。

标签: elixir erlang-supervisor


【解决方案1】:

您将在 QueueSupervisor.start_link/0 中启动 GenServer 而不是 Supervisor。这应该有效:

defmodule QueueSupervisor do
  def start_link do
    Supervisor.start_link(__MODULE__, [], name: :model_queue)
  end
end

为什么这甚至可以正确启动主管?

它开始一个GenServer;只是您使用的参数与Supervisor.start_link/3GenServer.start_link/3 兼容。

【讨论】:

    猜你喜欢
    • 2017-02-21
    • 2014-12-09
    • 2011-10-11
    • 2019-12-17
    • 2013-03-21
    • 2016-01-16
    • 2012-11-04
    • 2016-04-28
    • 1970-01-01
    相关资源
    最近更新 更多