【问题标题】:Dynamic Supervisor Spec in ElixirElixir 中的动态主管规范
【发布时间】:2016-06-24 17:09:09
【问题描述】:

我创建了一个 GameSupervisor 监督模块,用于动态创建实例 GameServer (GenServer) 的子级。我可以看到在调用 GameSupervisor.start 函数时调用了 GameServer 的 start_link 方法,但它不会使 pid 保持活动状态。如果重启策略设置为临时,iex 中的 Process.alive?(pid) 总是返回 false。如果我将重启设置为瞬态或永久,当我在该 pid 上调用 GenServer.cast 时,它最终会再次调用 GameServer.start_link。

调用 start_child 是否不会自动将 pid 添加到监督树并使其保持活动状态?

GameSupervisor.ex

defmodule Prest.GameSupervisor do

  alias Prest.GameServer
  use Supervisor

  @name :game_sup

  def start_link() do
    IO.puts "start link"
    Supervisor.start_link(__MODULE__, [], [name: @name])
  end

  def start(uid) do
    IO.puts "start bucket"
    {:ok, child} = Supervisor.start_child(@name, [uid])
  end

  def init([]) do
    IO.puts "init sup"
    children = [
      worker(GameServer, [], restart: :transient)
    ]

    supervise(children, strategy: :simple_one_for_one)
  end

end

GameServer.ex

  defmodule Prest.GameServer do
  use GenServer

  # Client API

  def start_link(uid) do
    IO.puts "start game server"
    GenServer.start_link(__MODULE__, uid, [])
  end

  def post(pid, event_id) do
    :gen_server.cast(pid, {:event, event_id})
  end

  # Server API

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

  def handle_cast({:event, event_id}, state) do
    #state = [event_id|state]
    {:noreply, "ok", state}
  end
end

谢谢

【问题讨论】:

    标签: elixir phoenix-framework erlang-otp erlang-supervisor gen-server


    【解决方案1】:

    the docs

    • :permanent 进程总是重新启动,即使它正常终止。
    • :transient 进程只有在异常终止时才会重新启动。
    • :temporary 进程永远不会重新启动。

    您的GameServer 进程很可能由于某种原因而崩溃,并且主管正在按照其配置方式处理重启。

    要对此进行调试,您需要检查您的日志(可能仅输出到终端)以了解进程崩溃的原因。如果您能够为其获取{:ok, pid},那么它可能不会在初始化时崩溃,这意味着handle_casthandle_callhandle_info 子句是导致崩溃的原因。

    没有代码,很难提供更具体的帮助。

    在这种情况下,您的 handle_cast 的返回值看起来很糟糕。它should return{:noreply, state},但正在返回{:noreply, "ok", state}。这通常是由于将handle_call 更改为handle_cast 并忘记删除回复值造成的。

    【讨论】:

    • 这是非常简单的代码 - 很难看出会出现什么错误。你有github链接吗?今晚我很高兴进行一些调试。
    • 实际上,我确实看到了错误。 handle_cast 的返回值错误。 elixir-lang.org/docs/stable/elixir/GenServer.html#c:handle_cast/…
    • 具体来说,它应该返回{:noreply, state}而不是{:noreply, "ok", state}
    • 做到了。之前是 handle_call 但忘记更改参数。谢谢!
    猜你喜欢
    • 2019-04-27
    • 2011-07-14
    • 1970-01-01
    • 2017-10-10
    • 1970-01-01
    • 1970-01-01
    • 2019-01-14
    • 2021-03-18
    • 1970-01-01
    相关资源
    最近更新 更多