defmodule MyApp.Worker do use GenServer # api @spec start_link(worker_id :: String.t()) :: GenServer.on_start() def start_link(worker_id) do GenServer.start_link(__MODULE__, [worker_id], name: via_tuple(worker_id)) end @spec child_spec([term()]) :: Supervisor.child_spec() def child_spec([worker_id]) do %{ id: __MODULE__, start: {__MODULE__, :start_link, [worker_id]}, restart: :transient } end @spec stop(worker_id :: String.t()) :: :ok def stop(worker_id) do # Given the :transient option in the child spec, the GenServer will restart # if any reason other than `:normal` is given. GenServer.stop(via_tuple(worker_id)) end @spec ping(worker_id :: String.t()) :: :pong def ping(worker_id) do GenServer.call(via_tuple(worker_id), :ping) end # callbacks @impl true def init([worker_id]) do {:ok, %{id: worker_id}} end @impl true def handle_call(:ping, _from, state) do {:reply, :pong, state} end # internal @spec via_tuple(worker_id :: String.t()) :: {:via, Registry, {:worker_registry, worker_id :: String.t()}} defp via_tuple(worker_id), do: {:via, Registry, {:worker_registry, worker_id}} end