I’m a complete beginner to Elixir and I’m having a problem that I’m hoping is quite obvious to a more experienced eye. I’m working through the OTP chapter of Chris McCord’s Programming Phoenix (the beta). There is an exercise which has you set up a supervised GenServer to maintain a countdown, but I’ve been having trouble getting my Supervisor to restart my Counter.
My application.ex looks like:
defmodule InfoSys.Application do
# See https://hexdocs.pm/elixir/Application.html
# for more information on OTP Applications
@moduledoc false
use Application
def start(_type, _args) do
# List all child processes to be supervised
children = [
# Starts a worker by calling: InfoSys.Worker.start_link(arg)
{InfoSys.Counter, 3}
]
# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: InfoSys.InfoSupervisor]
Supervisor.start_link(children, opts)
end
end
and my counter.ex looks like:
defmodule InfoSys.Counter do
use GenServer
def inc(pid), do: GenServer.cast(pid, :inc)
def dec(pid), do: GenServer.cast(pid, :dec)
def val(pid), do: GenServer.call(pid, :val)
def start_link(initial_val) do
GenServer.start(__MODULE__, initial_val)
end
def init(initial_val) do
Process.send_after(self(), :tick, 1000)
{:ok, initial_val}
end
def handle_info(:tick, val) when val <= 0, do: raise "boom!"
def handle_info(:tick, val) do
IO.puts("tick #{val}")
Process.send_after(self(), :tick, 1000)
{:noreply, val - 1}
end
def handle_cast(:inc, val) do
{:noreply, val + 1}
end
def handle_cast(:dec, val) do
{:noreply, val - 1}
end
def handle_call(:val, _from, val) do
{:reply, val, val}
end
end
When I run my application in iex (with iex -S mix
), it counts down from 5 and raises, but the Supervisor does not restart the Counter. When I look at my supervision tree in the observer, my counter never appears at all (though it is clearly running). Here is the stacktrace:
Interactive Elixir (1.7.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> tick 3
tick 2
tick 1
[error] GenServer #PID<0.131.0> terminating
** (RuntimeError) boom!
(info_sys) lib/info_sys/counter.ex:19: InfoSys.Counter.handle_info/2
(stdlib) gen_server.erl:637: :gen_server.try_dispatch/4
(stdlib) gen_server.erl:711: :gen_server.handle_msg/6
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: :tick
State: 0
I am on Elixir 1.7.4 and running this application from underneath an Umbrella project. I’m happy to post more project details if it appears they might be useful. Does anyone have any ideas why my Counter isn’t restarting?