View Source TPK.Common.OTP.RegisteredServer (tpk_common v0.0.1)

Defines a GenServer which can be addressed by a name instead a pid. By using the module we will inject you a start_link/1 function and another function reg_name/1.

First make sure you have a Registry up and running. Usually, in a Phoenix or Elixir application you will do that in Application and start the Registry as a supervised child, like so

application.ex

...
def start(_type, _args) do
  children =
    [
      ...,
      {Registry,keys: :unique, name: MyRegistry}
    ] 
...

Then define your own GenServer but use use RegisteredServer instead of use GenServer directely. When using RegisteredServer, provide two arguments. The module you're about to define and the registry to use.

When calling start_link/1 you have to provide reg_name as an argument for the unique process name to be registered, followed by whatever keys your server needs.

{:ok, _unused_pid} = ServerTest.start_link(reg_name: "Server-1", my_key: :something)

example

Example

For your server you have to implement the init/1 function but not start_link/1. start_link/1 will be defined by use RegisteredServer implicitly.

defmodule ServerTest do
  use RegisteredServer, module: __MODULE__, registry: MyRegistry

  @impl true
  def init(args) do
    {:ok, args}
  end

  def myfunc(server) do
    GenServer.call(process_name(server), :mystate)
  end

  @impl true
  def handle_call(:mystate, _, state), do: {:reply, state[:mystate], state}
end

usage

Usage

{:ok, _s1} = ServerTest.start_link(reg_name: "Server-1", mystate: :foo)
{:ok, _s2} = ServerTest.start_link(reg_name: "Server-2", mystate: :bar)
{:error, {:already_started, _pid}} = ServerTest.start_link(reg_name: "Server-2")

assert ServerTest.reg_name("Server-1") == "Server-1"
assert ServerTest.mystate("Server-1") == :foo

assert ServerTest.reg_name("Server-2") == "Server-2"
assert ServerTest.mystate("Server-2") == :bar