I have created a GameSupervisor supervision module that I use to dynamically create a child of instance GameServer (GenServer). I can see GameServer's start_link method is invoked when GameSupervisor.start function is called but it doesn't keep the pid alive. Process.alive?(pid) in iex always return false if the restart strategy is set to temporary. If I set the restart to transient or permanent it ends up calling GameServer.start_link again when I call GenServer.cast on that pid.
Is invoking start_child not automatically add the pid to the supervision tree and keep it alive?
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
Thanks
According to the docs:
:permanent
process is always restarted, even if it terminates normally. :transient
process is restarted only if it terminates abnormally. :temporary
process is never restarted.More than likely, your GameServer
process is crashing for one reason or another, and the supervisor is handling restarts the way it's configured to.
To debug this, you'll want to check your logs (which may only be output to the terminal) to see the reason why the process is crashing. If you're able to get an {:ok, pid}
for it, then it's probably not crashing on init, which means a handle_cast
, handle_call
, or handle_info
clause is responsible for the crash.
Without code, it's hard to offer more specific help.
In this case, it looks like your handle_cast
has a bad return value. It should return {:noreply, state}
, but is returning {:noreply, "ok", state}
. This is often caused by changing a handle_call
to handle_cast
, and forgetting to remove the reply value.