It depends. If you run only one GenServer process per node, you can call it like this:
@doc """ If you want to call the server only from the current module. """ def local_call(message) do GenServer.call(__MODULE__, message) end
or
@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
If you have several processes from the same module, you need an additional identifier (for example, if you have a supervisor strategy :simple_one_for_one to generate a GenServer on demand).
For something like this, I would recommend using:
:gproc to name the processes.:ets if you need more information to identify your processes.
:gproc is awesome and works with GenServer . You usually name your processes using an atom as a registered name. :gproc allows you to call your processes an arbitrary member, i.e. tuple.
Say, in my function call, I have a complex identifier for my server, for example {:id, id :: term} , where id can be a string, for example. I could start my GenServer as:
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
And look at my process for something other than an atom, as I said, for example, on a string. Therefore, if I start my server, for example:
MyServer.start_link("My Random Hash")
And I have a function like:
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
You can use it to call processes, such as:
MyServer.f("My Random Hash", {:message, "Hello"})
If the naming process is more complex, you can use :ets to store a more complex state.
If you want to use :gproc , you can add it to your mix.exs file, for example:
(...) defp deps do [{:gproc, github: "uwiger/gproc"}] end (...)
On a side note, never call GenServer.call/3 from handle_call/3 . It will time out and do DOS on other GenServer.call . handle_call/3 processes one message at a time.