erlang - Obtener un proceso de hermanos en Elixir
otp (2)
Tengo un árbol de proceso de Elixir / Erlang:
parent (Supervisor)
├── child1 (GenServer)
└── child2 (GenServer)
child1 (un cliente DB) tiene información que child2 necesita usar. ¿Cuál es una buena manera de pasar una referencia del proceso del Supervisor a child2 para que child2 siempre tenga una referencia válida para child1? ¿Solo necesito reestructurar mi aplicación para que child2 sea supervisado por child1?
No uso Elixir, pero utilizo Erlang, y creo que mi respuesta es válida en ambos casos.
Si sus procesos de tipo child1 son permanentes, y en número fijo, entonces la solución más simple es registrarlos (game_server, event_server, ...)
Pero si tienen vida transitoria, su número no es fijo, o existirán muchos procesos del mismo tipo (un proceso de jugador en un juego, por ejemplo). Sugiero usar otra organización:
- El supervisor de nivel superior inicia 2 procesos, un servidor y un supervisor.
- El servidor, al menos, mantendrá una lista de todos los procesos "hijo1" vivientes con algunas características (identificación de jugador ...) que permiten acceder a ellos. En general, también usará el proceso de supervisor para iniciar, matar ... los procesos "hijo1".
El supervisor es una fábrica simple que creará y supervisará el "niño1", utilizando una estrategia simple_one_for_one.
parent (Supervisor) ├── child2 (GenServer) └── Client_supervisor(Supervisor) ├── Client_server(registered GenServer) └── Client_factory(registered Supervisor) ├── Child1(GenServer) ├── Child1''(GenServer) └── ...
La forma más simple sería probablemente que child1
y child1
se registraran bajo alias locales. Puede hacerlo al iniciar su GenServer
al pasar la opción de name
:
defmodule Child1 do
use GenServer
def start_link do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
end
end
En este caso, un proceso respaldado por el módulo Child1
se registrará localmente con un alias Child1
. Luego, si desea enviar mensajes, puede usar ese alias en lugar de un 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
Si desea una solución más compleja donde, por ejemplo, se pueden registrar muchos procesos diferentes del mismo tipo, eche un vistazo a la biblioteca de gproc