I am making an master-worker application. The Master code is as follows. This code asynchronously calls workers in start_link
. Once the workers are done with their work, they report to master using handle_cast
asynchronous call. After this I intend keep the master actor 'ON' so that it can re-spawn the new worker Actors(like it did in first start_link
call.). However, the master stops once all the worker actors are done with their work. This stackoverflow post mentions using recursive call but I am not able to do it with Genserver
. Is there any method in Genserver
to achieve it?
defmodule Bitcoin.MasterNode do
use GenServer
def start_link(opts) do
{:ok, pid} = GenServer.start_link(__MODULE__,:ok, opts)
start_workers(----perform some task asynchronously----)
{:ok, pid}
end
def set_message(server, name) do
GenServer.cast(server, {:set_message, name})
end
#callbacks
def init(:ok) do
names = []
{:ok, names}
end
def handle_cast({:set_message, name},names) do
names = names ++ name
IO.puts name
{:noreply,names}
end
end
Edit: I am running application on distributed mode i.e, master is also connected to external worker nodes. If Master dies, the connections also dies out. The intention is to keep the master node with same PID to run infinite times.
If I properly understood your intent, you want to restart the whole process as soon as all children are done. If that’s true, one should use OTP features instead of inventing their own wheels :)
Just extend the supervision tree with one more supervisor, that would be supervising your “master” (
Bitcoin.MasterNode
,) and you are all set.What will happen:
MasterSupervisor
starts;MasterSupervisor
transparently startsMasterNode
as a worker with a:one_for_one
strategy;MasterNode
acts exactly as it does now;MasterNode
dies, which is fine;MasterNode
has died,MasterSupervisor
will automatically restart it due to it’s strategy.To keep track of
GenServer
despite whether is was respawned or not, one should use named servers instead of just operatingPID
s: