Elixir中

时间:2016-03-10 02:42:29

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

我创建了一个GameSupervisor监控模块,用于动态创建实例GameServer(GenServer)的子级。我可以看到GameServer的start_link方法在调用GameSupervisor.start函数时被调用,但它不能保持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

由于

1 个答案:

答案 0 :(得分:3)

根据the docs

  • 即使:permanent进程正常终止,也始终重新启动:transient进程。
  • 仅当:temporary进程异常终止时才会重新启动它。
  • 永远不会重新启动GameServer进程。

很可能,您的{:ok, pid}进程因某种原因而崩溃,并且主管正在以其配置方式处理重启。

要调试此操作,您需要检查日志(可能只输出到终端)以查看进程崩溃的原因。如果您能够获得handle_cast,那么它可能不会在init上崩溃,这意味着handle_callhandle_infohandle_cast子句负责崩溃。

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

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