I am trying to start the below workers in a Supervisor that I am calling in application module in mix.exs
Like this
defmodule AppStarter do
import Supervisor.Spec
def start(_type,_args) do
children=[
worker(TPMod1,[],[]),
worker(TPMod2,[],[])
]
opts=[strategy: :one_for_one, name: HelloVisor]
Supervisor.start_link(children,opts)
end
end
One of my module is GenServer and another I kept a simple listening process.
defmodule TPMod1 do
def start_link() do
IO.puts "started TPMod1"
listen()
end
def listen() do
receive do
_ -> :ok
end
listen()
end
def child_spec(opts) do
%{
id: __MODULE__,
start: {__MODULE__, :start_link, []},
type: :worker,
restart: :permanent,
shutdown: 500
}
end
end
Problem is it get stuck and doesn't start the worker 2 TPMod2
I tried doing in TPMod1
's start_link()
def start_link() do
IO.puts "started TPMod1"
Task.async(&listen/0)
end
But that give me this
** (Mix) Could not start application tproject: AppStarter.start(:normal, []) returned an error: shutdown: failed to start child: TPMod1 ** (EXIT) %Task{owner: #PID<0.143.0>, pid: #PID<0.144.0>, ref: #Reference<0.2187290957.3420192769.212288>}
I can make it GenServer and make it work but how can we start a simple worker? And why supervisor is not restarting it again? not infinitly but some times? It should have at least tried restarting and fail. Please suggest other improvements too if any.
The supervisor expects the children to return {:ok, pid}
, :ignore
or {:error, reason}
.
It hangs because when the supervisor runs the start_link
function on your worker, it executes (as himself), listen
which sets a receive
block, so it gets stuck there. When you use the gen_* module's start_link
and friends, it takes care of spawning, returning correctly etc.
In your case you could switch:
def start_link() do
IO.puts "started TPMod1"
listen()
end
to:
def start_link() do
pid = spawn(__MODULE__, :listen, [])
{:ok, pid}
end
And this should do it.