NamedSupervisedServer behaviour (named_supervised_server v0.1.5)
A behaviour module for starting supervised GenServer that is named as __MODULE__
by default or you can supply different name.
With the use of NamedSupervisedServer
, you can avoid the need to add start_link/1
function with name: __MODULE__
to your module every time you write a new one. And if you need your own start_link/1
function, you can override it.
Compatible with PartitionSupervisor. Partition number added at the end of process name, :partition
argument passed down to process init
.
Installation
If available in Hex, the package can be installed
by adding named_supervised_server
to your list of dependencies in mix.exs
:
def deps do
[
{:named_supervised_server, "~> 0.1"}
]
end
Usage
- Add
use NamedSupervisedServer
to your module. - See
Examples
.
use NamedSupervisedServer
When you use NamedSupervisedServer
, the NamedSupervisedServer module will:
- set
@behaviour NamedSupervisedServer
, - add
use GenServer
, - pass options passed to
use NamedSupervisedServer
touse GenServer
, - define a
start_link/1
function withname: __MODULE__
, so your module does not need to define it if you don't want a custom one.
Usage with PartitionSupervisor
You must use with_arguments
with :partition
key:
with_arguments: fn [opts], partition ->
[Keyword.put(opts, :partition, partition)]
end}
Like this:
children = [
{PartitionSupervisor,
child_spec: {MyNamedServer, my_arg: "Hello named server!"},
name: MyNamedServerPartitionSupervisor,
with_arguments: fn [opts], partition ->
[Keyword.put(opts, :partition, partition)]
end},
]
{:ok, pid} = Supervisor.start_link(children, strategy: :one_for_one)
See Examples
.
Callbacks
The following callbacks may be implemented by modules that use the NamedSupervisedServer
behavior:
start_link/1
: Starts a GenServer process linked to the current process. This function is often used to start the server as part of a supervision tree.
start_link/1
callback should return one of the following values:
{:ok, pid}
: The server was successfully created and initialized.:ignore
: The server should be ignored, and no further action is taken.{:error, {:already_started, pid}}
: A process with the specified name already exists.{:error, reason}
: The initialization of the server failed for the given reason.{:stop, reason}
: The process is terminated due to the provided reason.
Options
start_link/1
callback accept the following option:
:name
(optional): Used for name registration as described in the "Name Registration" section in the documentation forGenServer
.
Examples
Basic usage
iex> defmodule MyServer do
...> use NamedSupervisedServer
...>
...> @impl GenServer
...> def init(arg) do
...> {:ok, arg}
...> end
...>end
...># Starting a supervised process
...>{:ok, sup} = Supervisor.start_link([MyServer], strategy: :one_for_one)
...>{_id, child, _type, _modules} = hd(Supervisor.which_children(sup))
...>assert Process.whereis(MyServer) == child
With GenServer options
iex> defmodule TransientServer do
...> use NamedSupervisedServer, restart: :transient, shutdown: 10_000
...>
...> @impl GenServer
...> def init(arg) do
...> {:ok, arg}
...> end
...>end
...># Starting a supervised process
...>{:ok, sup} = Supervisor.start_link([TransientServer], strategy: :one_for_one)
...>{:ok, chldspec} = :supervisor.get_childspec(sup, TransientServer)
...>assert chldspec.restart == :transient
...>assert chldspec.shutdown == 10_000
...>{_id, child, _type, _modules} = hd(Supervisor.which_children(sup))
...>assert Process.whereis(TransientServer) == child
Using a different name for the process
iex>defmodule NamedServer do
...> use NamedSupervisedServer
...>
...> @impl GenServer
...> def init(arg) do
...> {:ok, arg}
...> end
...>
...> @impl GenServer
...> def handle_call(:get_my_arg, _from, state) do
...> {:reply, {:ok, state[:my_arg]}, state}
...> end
...>
...> def get_my_arg(pid) do
...> GenServer.call(pid, :get_my_arg)
...> end
...>end
...>
...>children = [
...> {NamedServer, my_arg: "Hello named server!", name: :my_named_server}
...>]
...># Starting a named supervised process
...>{:ok, _} = Supervisor.start_link(children, strategy: :one_for_one)
...>
...># Access the named process using its registered name
...>{:ok, "Hello named server!"} = NamedServer.get_my_arg(:my_named_server)
With PartitionSupervisor
iex>defmodule MyNamedServer do
...> use NamedSupervisedServer
...>
...> @impl GenServer
...> def init(arg) do
...> {:ok, arg}
...> end
...>
...> @impl GenServer
...> def handle_call(:get_my_arg, _from, state) do
...> {:reply, {:ok, state[:my_arg]}, state}
...> end
...>
...> @impl GenServer
...> def handle_call(:get_partition, _from, state) do
...> {:reply, {:ok, state[:partition]}, state}
...> end
...>
...> def get_my_arg(pid) do
...> GenServer.call(pid, :get_my_arg)
...> end
...>
...> def get_partition(pid) do
...> GenServer.call(pid, :get_partition)
...> end
...>end
...>
...>children = [
...> {PartitionSupervisor,
...> child_spec: {MyNamedServer, my_arg: "Hello named server!", name: :my_named_server},
...> name: MyNamedServerPartitionSupervisor,
...> with_arguments: fn [opts], partition ->
...> [Keyword.put(opts, :partition, partition)]
...> end},
...>]
...># Starting a named supervised process
...>{:ok, _} = Supervisor.start_link(children, strategy: :one_for_one)
...>
...># Access the named process using its registered name
...>{:ok, "Hello named server!"} = MyNamedServer.get_my_arg(:my_named_server0)
...># Partition number of process
...>{:ok, 0} = MyNamedServer.get_partition(:my_named_server0)
Custom start_link/1
iex>defmodule CustomServer do
...> use NamedSupervisedServer
...>
...> # Override start_link/1 to provide additional options
...> @impl NamedSupervisedServer
...> def start_link(args) when is_list(args) do
...> GenServer.start_link(__MODULE__, args, name: :custom_server)
...> end
...>
...> @impl GenServer
...> def init(arg) do
...> {:ok, arg}
...> end
...>end
...>
...># Starting a custom supervised GenServer process
...>{:ok, sup} = Supervisor.start_link([CustomServer], strategy: :one_for_one)
...>{_id, child, _type, _modules} = hd(Supervisor.which_children(sup))
...>assert Process.whereis(:custom_server) == child
References
Summary
Callbacks
Starts a NamedSupervisedServer
process linked to the current process that is named as __MODULE__
by default or you can supply different name.
Callbacks
@callback start_link(args) :: GenServer.on_start() when args: list()
Starts a NamedSupervisedServer
process linked to the current process that is named as __MODULE__
by default or you can supply different name.
This is often used to start the NamedSupervisedServer
as part of a supervision tree.
Once the server is started, the init/1
function of the given is called
with init_arg
as its argument to initialize the server. To ensure a
synchronized start-up procedure, this function does not return until init/1
has returned.
Note that a NamedSupervisedServer
started with start_link/1
is linked to the
parent process and will exit in case of crashes from the parent. The NamedSupervisedServer
will also exit due to the :normal
reasons in case it is configured to trap
exits in the init/1
callback.
Options
:name
(optional): Used for name registration as described in the "Name Registration" section in the documentation forGenServer
.
Return values
If the server is successfully created and initialized, this function returns
{:ok, pid}
, where pid
is the PID of the server. If a process with the
specified server name already exists, this function returns
{:error, {:already_started, pid}}
with the PID of that process.
If the init/1
callback fails with reason
, this function returns
{:error, reason}
. Otherwise, if it returns {:stop, reason}
or :ignore
, the process is terminated and this function returns
{:error, reason}
or :ignore
, respectively.