Search code examples
erlang-otpelixirerlang-supervisorgen-serverelixir-mix

How to run Elixir Supervisor in escript


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?


Solution

  • 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 to GenServer.cast). If you're doing this just to test the supervisor, then you can try:

    defmodule EchoCmd.Echo do
        def main(args) do
            EchoCmd.Supervisor.start_link([:Hello])
            GenServer.cast(:echoserver, :echo)
            GenServer.cast(:echoserver, :mumble)
            GenServer.cast(:echoserver, :echo)
        end
    end
    

    The reason it works in iex is that iex traps the exit and allows you to type in another line.