Reputation: 11
I have 2 modules, one is the supervisor and the other is its worker. I have calculated something in the 2nd (child) module, how do I send that value to the parent (supervisor) module?
defmodule VampSupervisor do
use Supervisor
def start_link(init_arg) do
Supervisor.start_link(__MODULE__, init_arg)
end
def init(init_arg) do
Process.flag(:trap_exit, true)
[start,last] = init_arg
nodes = Enum.chunk_every(start..last, 10)
children = Enum.map(nodes, fn(chunk_list) ->
worker(FACT, [chunk_list], [id: List.first(chunk_list), restart: :permanent])
end)
supervise(children, strategy: :one_for_one)
end
end
defmodule FACT do
use GenServer
def start_link(init_arg) do
pid = spawn_link(__MODULE__,:init,[init_arg])
{:ok,pid}
end
def init(init_arg) do
Enum.each(init_arg, fn(x)->
spawn(__MODULE__,:main,[x])
end)
end
def main(n) do
list = make_factor(n,round(:math.sqrt(n)),[])
{:ok,pid}=GenServer.start_link(VampServer, list)
Enum.each(list, fn(_)->
{x,[head,tail]} = GenServer.call(pid,{:check_vampire,n})
if x==n do
IO.puts("#{x} #{head} #{tail}") **This has be sent back to supervisor**
end
end)
end
Upvotes: 0
Views: 880
Reputation: 121000
There are many issues with your approach.
Supervisor.Spec.supervisor/3
and Supervisor.Spec.worker/3
are deprecated and should be avoided; one should use child specs instead.Supervisor
is not meant to receive user callbacks. The only callback it has is Supervisor.init/1
. The processes that are supposed to receive user messages are to be made workers.GenServer
for doing the simple function call in VampServer
.Instead of this
{:ok, pid} = GenServer.start_link(VampServer, list)
Enum.each(list, fn _ ->
GenServer.call(pid, {:check_vampire, n})
end)
one should implement a plain old good function Vamp.check_vampire/1
and call it explicitly instead, like
Enum.each(list, fn _ ->
Vamp.check_vampire(n)
end)
GenServer.call/3
is synchronous and does [almost] exactly what the plain function would do.
The summing up. Start a VampSupervisor
as Supervisor
with two workers: FACT
that will do calculations and FACTConsumer
that will receive messages from FACT
when needed.
Upvotes: 3
Reputation: 2010
It looks like you're using a supervisor and workers to do some transient work and then report back.
Normally, you start Supervisor
and DynamicSupervisor
within your application tree, and these supervisors get named so you can refer to them across the node just by their name. These supervisors are meant to be long-lived, and are probably not a good fit for your use case.
A better solution might be to try Task.async/1
. (See also the guides on Task
.) This will let you fire off a bunch of computations in parallel and have them join back together.
Alternatively, you can define a module to spin up tasks that are supervised under a TaskSupervisor
, which get the caller's pid with self()
when created. However, I think Task.async/1
might be your best option in this case.
Upvotes: 0