I have a router, built on Plug.Router that I’m working with that needs interact with a GenServer. My GenServer's API has the method MyRegistry.find/2 which expects the server (pid or name) to query against and the ID of the item to find in the registry.
In my router, I am trying to avoid hard coding the registry name in my calls (MyRegistry.find(:my_registry, params["id"])), but I’m not sure of how best to provide my router with the name of the registry to pull from. I’ve tried to use the init method in the past on the router, but Plug.Router doesn’t accept arbitrary values in the options.
You can decorate the GenServer(Registry) with a Service module:
defmodule GenServerTest do
use GenServer
def start_link do
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
end
def init(:ok) do
{:ok, []}
end
def find(pid, value) do
GenServer.call(pid, {:find, value})
end
def handle_call({:find, value}, _from, state) do
IO.puts "found #{value}"
{:reply, value, state}
end
end
defmodule GenServerService do
def find(value) do
GenServerTest.find(GenServerTest, value)
# this will call GenServerTest.find(Process.whereis(GenServerTest), value)
# Process.whereis(GenServerTest) -> will return pid of GenServerTest
end
end
or inside plug, you can store the GenServer pid/atom inside an attribute:
defmodule MyPlugdo
import Plug.Conn
@genserver_pid Process.whereis(GenServerTest)
...
end
If your GenServer name will change you will modify one attribute or one Service module
But that still doesn’t accomplish what I’m looking for, which is to be able to run my test suite which lights up an instance of MyRegistry for the router to use to run the tests against and inject the name of the registry into the router.
I have similar confusion. Did you every determine an efficient manner to call the GenServer from your router without naming the GenServer specifically?
This still requires a specific name for the GenServer. However, I believe I can use the same logic and store the PID value instead assuming this works in a Module with use Plug.Router.