In GenServer.start_link/3
I can register a name locally using an atom for a process like this:
defmodule Worker do
use GenServer
def start_link do
GenServer.start_link(__MODULE__, nil, name: :worker)
end
end
Then I can start a supervisor to supervise this process:
defmodule Boss do
use Supervisor
def init(_) do
children = [worker(Worker, [])]
supervise(children, strategy: :one_for_one)
end
end
Now I want to make the supervisor to supervise 3 Worker
processes, so I need to give those 3 processes unique names, so that when supervisor restarts the process it will always use the same symbolic name.
I can simply use string interpolation for the unique Worker
process name like this:
defmodule Worker do
use GenServer
def start_link(id) do
GenServer.start_link(__MODULE__, nil, name: :"worker_#{id}")
end
end
Then supervise 3 processes like this:
defmodule Boss do
use Supervisor
def init(_) do
children = for id <- 1..3 do
worker(Worker, [id], id: id)
end
supervise(children, strategy: :one_for_one)
end
end
It works like expected.
In the doc for GenServer under "Name registration" section, it says you can use {:via, module, term}
to register a name as well.
{:via, module, term}
- the GenServer is registered with the given mechanism and name. The:via
option expects a module that exportsregister_name/2
,unregister_name/1
,whereis_name/1
, andsend/2
. One such example is the:global
module which uses these functions for keeping the list of names of processes and their associated PIDs that are available globally for a network of Elixir nodes. Elixir also ships with a local, decentralized and scalable registry called Registry for locally storing names that are generated dynamically.
However, in order to use :via
option you have to implement a module that exports register_name/2
, unregister_name/1
, whereis_name/1
and send/2
, which seems pretty cumbersome comparing to simply use string interpolation technique as shown above.
So my question is:
:via
option to register name?Settings View Source GenServer behaviour (Elixir v1. 13.4) A behaviour module for implementing the server of a client-server relation. A GenServer is a process like any other Elixir process and it can be used to keep state, execute code asynchronously and so on.
12.3) A local, decentralized and scalable key-value process storage. It allows developers to lookup one or more processes with a given key. If the registry has :unique keys, a key points to 0 or 1 process.
What are Elixir and OTP? Elixir is a functional programming language built on the Erlang VM. OTP is a process oriented programming framework integral to Erlang and Elixir.
Both start_link/3 and start/3 support the GenServer to register a name on start via the :name option. Registered names are also automatically cleaned up on termination. The supported values are: an atom - the GenServer is registered locally with the given name using Process.register/2.
{:via, module, term} - the GenServer is registered with the given mechanism and name. The first option, an atom, is what we have been using so far and we know it’s not enough for our needs now. The second option is used to register a process globally, across multiple nodes, and relies on a local ETS table.
The supported values are: an atom - the GenServer is registered locally with the given name using Process.register/2. {:global, term} - the GenServer is registered globally with the given term using the functions in the :global module. {:via, module, term} - the GenServer is registered with the given mechanism and name.
The advantage of using a generic server process (GenServer) implemented using this module is that it will have a standard set of interface functions and include functionality for tracing and error reporting. It will also fit into a supervision tree. The GenServer behaviour abstracts the common client-server interaction.
tl;dr - :via
is there to allow you to use non-standard process registration libraries. They must conform to an interface (much like implementing an interface in Java), and may provide extra functionality.
The main example is when you want to use a non-standard name registration library. Take for example the gproc library. It follows the interface requirements to use :via
, so minimal intrusion is required into your application code. In addition, it provides several advantages over the standard name registration system:
Elixir's Registry
module is another example of one which requires a via tuple.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With