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:
MasterSupervisorstarts;MasterSupervisortransparently startsMasterNodeas a worker with a:one_for_onestrategy;MasterNodeacts exactly as it does now;MasterNodedies, which is fine;MasterNodehas died,MasterSupervisorwill automatically restart it due to it’s strategy.To keep track of
GenServerdespite whether is was respawned or not, one should use named servers instead of just operatingPIDs: