Search code examples
elixirerlang-otpgen-server

Trouble registering a GenServer with a via tuple. ** (UndefinedFunctionError) function PokerServer.whereis_name/1 is undefined or private)


Here's a very simple GenServer. I am trying to register it on initialization using a via tuple.

defmodule PokerServer do
  use GenServer

  def start(id) do
    GenServer.start(__MODULE__, id, name: {:via, __MODULE__, id})
  end

  @impl GenServer
  def init(id) do
    {:ok, id}
  end
end

Unless I missunderstood something in the documentation, I should be able to pass the via tuple as a name in the third argument of GenServer.start/3

Except that when I try to start the process in the iex shell, I trigger an error

iex(1)> PokerServer.start(123)
** (UndefinedFunctionError) function PokerServer.whereis_name/1 is undefined or private
(live_draft 0.1.0) PokerServer.whereis_name(123)
(stdlib 3.14.2.2) gen.erl:83: :gen.start/6

EDIT: I use elixir 1.12.3 and erlang/OTP 23


Solution

  • The module you pass in {:via, __MODULE__, id} should export register_name/2, unregister_name/1, whereis_name/1 and send/2. For example:

    def start(id) do
      GenServer.start(__MODULE__, id, name: {:via, :global, id})
    end
    

    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. Documentation