I have a mix project with as simple as possible a Supervisor and GenServer. When I call from iex:
EchoCmd.Supervisor.start_link([:Hello])
GenServer.call(:echoserver, :echo)
GenServer.call(:echoserver, :mumble)
GenServer.call(:echoserver, :echo)
The :mumble call raises an exception, then the GenServer is restarted and the second :echo call works ok.
If I run the code in any other way the Supervisor fails to restart the GenServer. For example, I create an escript of the project with the main module as follows:
defmodule EchoCmd.Echo do
def main(args) do
EchoCmd.Supervisor.start_link([:Hello])
GenServer.call(:echoserver, :echo)
GenServer.call(:echoserver, :mumble)
GenServer.call(:echoserver, :echo)
end
end
The :mumble call raises an exception and the escript terminates without the Supervisor restarting the GenServer.
I've not included the Supervisor and Server modules code because they work fine when called from iex, so I'm guessing they're not needed here.
Do I have a conceptual misunderstanding? Is this not possible, or am I doing something wrong?
The problem lies not in your server and supervisor, but in the way you're calling them. If the server exits while another process is waiting for a reply to
GenServer.call
, the calling process exits too, so the last call never happens. The reason for this is the process couldn't possibly continue in an invalid state if a synchronous call failed (GenServer.call
is synchronous as opposed toGenServer.cast
). If you're doing this just to test the supervisor, then you can try:The reason it works in
iex
is thatiex
traps the exit and allows you to type in another line.