Dipende.Se si avvia un solo GenServer
processo per nodo si può chiamare come:
@doc """
If you want to call the server only from the current module.
"""
def local_call(message) do
GenServer.call(__MODULE__, message)
end
o
@doc """
If you want to call the server from another node on the network.
"""
def remote_call(message, server \\ nil) do
server = if server == nil, do: node(), else: server
GenServer.call({__MODULE__, server}, message)
end
Se si dispone di numerosi processi dello stesso modulo, è necessario un identificatore supplementare (Per esempio, se si dispone di una strategia di supervisore :simple_one_for_one
per generare GenServer
s su richiesta).
Per una cosa del genere mi consiglia di utilizzare:
:gproc
ai processi di nome.
:ets
se sono necessarie ulteriori informazioni per identificare i processi.
:gproc
è fantastico e funziona con GenServer
. Di solito nominali i tuoi processi usando un atomo come nome registrato. :gproc
consente di denominare i processi con un termine arbitrario, ad esempio una tupla.
Diciamo che nella mia chiamata di funzione ho un identificatore complesso del mio server come {:id, id :: term}
dove id
può essere una stringa, ad esempio. Potrei iniziare la mia GenServer
come:
defmodule MyServer do
use GenServer
def start_link(id) do
name = {:n, :l, {:id, id}}
GenServer.start_link(__MODULE__, %{}, name: {:via, :gproc, name})
end
(...)
end
E guarda il mio processo con qualcosa di diverso da un atomo, come ho detto prima, una stringa per esempio. Quindi, se ho iniziare il mio server come:
MyServer.start_link("My Random Hash")
E ho una funzione come:
def f(id, message) do
improved_call(id, message)
end
defp improved_call(id, message, timeout \\ 5000) do
name = {:n, :l, {:id, id}}
case :gproc.where(name) do
undefined -> :error
pid -> GenServer.call(pid, message, timeout)
end
È possibile utilizzarlo per chiamare processi come:
MyServer.f("My Random Hash", {:message, "Hello"})
Se il processo di denominazione è più complesso, è possibile utilizzare :ets
per memorizzare uno stato più complesso.
Se si desidera utilizzare :gproc
è possibile aggiungere al file mix.exs
come:
(...)
defp deps do
[{:gproc, github: "uwiger/gproc"}]
end
(...)
Una nota a parte, mai, mai chiamare GenServer.call/3
dall'interno handle_call/3
. Timeout e eseguirà un DOS sull'altro GenServer.call
s. handle_call/3
gestisce un messaggio alla volta.
Come ha detto Onorio, è possibile utilizzare GenServer.call (self, request). Dai uno sguardo a: http://elixir-lang.org/getting-started/processes.html o la guida Little Elixir e OTP se vuoi dare un'occhiata più approfondita ai processi e alla piattaforma OTP. –
@Onorio Perché non è una buona idea? – user3790827
@ user3790827 Non ho detto che non è una buona idea. Ho detto che non sono sicuro che sia il modo migliore per andare. È davvero difficile da dire dato che non ho praticamente alcun contesto alla tua domanda. –