Background
I am running a distributed Elixir (Phoenix) application.
I want to run one instance of a globally registered GenServer for all my n
nodes. (thinking singleton coming from OO). This process is under a supervision tree in my app.
The start_link
function in my GenServer looks like:
def start_link(_opts \\ []) do
GenServer.start_link(__MODULE__, [], name: {:global, __MODULE__})
end
When I start my GenServer, I’m successfully seeing it registered globally and running.
If I try to run my GenServer on a connected node, I get an error as expected.
Problem
(assuming I’m running 2 nodes)
When the app is started, it looks like the GenServer process is being started on Node A and B. One of those nodes joins the cluster. Then when the other node joins the cluster, I am getting an error as expected based on the erlang :global
docs
from Erlang -- global -
When new nodes are added to the network, they are informed of the globally registered names that already exist. The network is also informed of any global names in newly connected nodes. If any name clashes are discovered, function Resolve is called. Its purpose is to decide which pid is correct. If the function crashes, or returns anything other than one of the pids, the name is unregistered. This function is called once for each name clash.
What I Want To Do
I would like to handle this error.
I have tried trapping exits in my GenServer’s init
function by adding Process.flag(:trap_exit, true)
But realized that the default Resolve
function to handle these name clashes sends a kill
message to a process (which I don’t think I can trap)
I noticed that one of the other Resolve
functions would allow me to handle this error
When registering the GenServer globally in start_link
, is there any way to specify the Resolve
callback used in case of a name clash?