Reputation: 6403
I have an Elixir/Erlang process tree:
parent (Supervisor)
├── child1 (GenServer)
└── child2 (GenServer)
child1 (a DB client) has information that child2 needs to use. What's a good way to pass a reference from the Supervisor process to child2 so that child2 will always have a valid reference to child1? Do I just need to restructure my app so that child2 is supervised by child1?
Upvotes: 7
Views: 692
Reputation: 23164
The simplest way would probably be for child1
and child2
to be registered under local aliases. You can do that while starting your GenServer
by passing the name
option:
defmodule Child1 do
use GenServer
def start_link do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
end
end
In this case a process backed by the Child1
module will be registered locally under an alias Child1
. Then if you want to send it messages you can use that alias instead of a PID
.
defmodule Child1 do
# ...
def get_data do
GenServer.call(__MODULE__, :get_data)
end
def handle_call(:get_data, _from, state) do
{:reply, extract_data_from_state(state), state}
end
end
If you want a more complex solution where for example many different processes of the same type may be registered, take a look at the gproc library
Upvotes: 8
Reputation: 14042
I don't use Elixir, but I use Erlang, and I think that my answer is valid in both cases.
If your processes of type child1 are permanent, and in fixed number, then the simplest solution is to register them (game_server, event_server, ...)
But if they have transient life, their number is not fixed, or many process of the same kind will exist (a player process in a game for example) I suggest to use another organization:
The supervisor is a simple factory that will create and supervise the "child1", using a simple_one_for_one strategy.
parent (Supervisor)
├── child2 (GenServer)
└── Client_supervisor(Supervisor)
├── Client_server(registered GenServer)
└── Client_factory(registered Supervisor)
├── Child1(GenServer)
├── Child1'(GenServer)
└── ...
Upvotes: 5