Спецификация динамического супервизора в Эликсире

Я создал модуль наблюдения GameSupervisor, который использую для динамического создания дочернего элемента экземпляра GameServer (GenServer). Я вижу, что метод start_link GameServer вызывается при вызове функции GameSupervisor.start, но он не поддерживает активный pid. Process.alive? (Pid) в iex всегда возвращает false, если стратегия перезапуска задана как временная. Если я установил временный или постоянный перезапуск, он снова вызывает GameServer.start_link, когда я вызываю GenServer.cast для этого pid.

Не вызывает ли запуск 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

Спасибо


person ed1t    schedule 10.03.2016    source источник


Ответы (1)


Согласно документам:

  • :permanent процесс всегда перезапускается, даже если он завершается нормально.
  • :transient процесс перезапускается только в случае аварийного завершения.
  • :temporary процесс никогда не перезапускается.

Скорее всего, ваш GameServer процесс по той или иной причине дает сбой, и супервизор выполняет перезапуски в соответствии с настройками.

Чтобы отладить это, вы захотите проверить свои журналы (которые могут выводиться только на терминал), чтобы узнать причину сбоя процесса. Если вы можете получить за него {:ok, pid}, то, вероятно, он не дает сбой при инициализации, что означает, что за сбой отвечает предложение handle_cast, handle_call или handle_info.

Без кода трудно предложить более конкретную помощь.

В этом случае похоже, что ваш handle_cast имеет неверное возвращаемое значение. Он должен вернуться {:noreply, state}, но возвращается {:noreply, "ok", state} . Это часто вызвано изменением handle_call на handle_cast и забвением удаления значения ответа.

person Cody Poll    schedule 10.03.2016
comment
Это довольно простой код - трудно понять, как будут появляться какие-либо ошибки. У вас есть ссылка на github? Я счастлив сегодня вечером заняться отладкой. - person Cody Poll; 10.03.2016
comment
На самом деле я вижу ошибку. handle_cast имеет неверное возвращаемое значение. elixir-lang.org/docs/stable/elixir/ GenServer.html # c: handle_cast / - person Cody Poll; 10.03.2016
comment
В частности, он должен возвращать {:noreply, state} вместо {:noreply, "ok", state} - person Cody Poll; 10.03.2016
comment
Это сделало это. Раньше это был handle_call, но аргументы забыли изменить. Спасибо! - person ed1t; 10.03.2016