2015-06-07 7 views
5

Ich habe ein Elixir/Erlang Prozessbaum:Erste ein Geschwister Prozess in Elixir

parent (Supervisor) 
├── child1 (GenServer) 
└── child2 (GenServer) 

child1 (ein DB-Client) Informationen hat, dass child2 verwenden muss. Was ist eine gute Möglichkeit, eine Referenz vom Supervisor-Prozess an child2 zu übergeben, sodass child2 immer einen gültigen Verweis auf child1 hat? Muss ich meine App einfach neu strukturieren, damit child2 von child1 überwacht wird?

Antwort

7

Der einfachste Weg wäre wahrscheinlich, dass child1 und child2 unter lokalen Aliasen registriert werden. Sie können das tun, während die GenServer, indem man die name Option Start:

defmodule Child1 do 
    use GenServer 

    def start_link do 
    GenServer.start_link(__MODULE__, [], name: __MODULE__) 
    end 
end 

In diesem Fall wird ein Prozess durch den Child1 Modul gesichert werden lokal unter einem Pseudonym Child1 registriert werden. Wenn Sie dann Nachrichten senden möchten, können Sie diesen Alias ​​anstelle von PID verwenden.

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 

Wenn Sie eine komplexere Lösung wollen, wo beispielsweise viele verschiedene Prozesse des gleichen Typs registriert sein können, werfen Sie einen Blick auf die gproc library

4

I Elixir nicht verwenden, aber ich benutze Erlang, und ich denke, dass meine Antwort in beiden Fällen gültig ist.

Wenn Ihre Prozesse vom Typ child1 dauerhaft sind, und in feste Zahl, dann ist die einfachste Lösung ist, sie zu registrieren (game_server, event_server, ...)

Aber wenn sie vergänglich das Leben haben, ihre Zahl nicht ist behoben, oder es gibt viele Prozesse derselben Art (ein Spielerprozess in einem Spiel zum Beispiel). Ich schlage vor, eine andere Organisation zu verwenden:

  • Der oberste Supervisor startet 2 Prozesse, einen Server und einen Supervisor.
  • Der Server, mindestens, wird eine Liste aller lebenden "child1" Prozesse mit einigen Eigenschaften (Spieler-ID ...), die auf sie zugreifen können, pflegen. Im Allgemeinen wird es auch den Supervisor-Prozess verwenden, um die "child1" -Prozesse zu starten, zu töten.
  • Der Supervisor ist eine einfache Factory, die "child1" mit einer simple_one_for_one-Strategie erstellt und überwacht.

    parent (Supervisor) ├── child2 (GenServer) └── Client_supervisor(Supervisor) ├── Client_server(registered GenServer) └── Client_factory(registered Supervisor) ├── Child1(GenServer) ├── Child1'(GenServer) └── ...