raymondboswel
Creating a supervised global singleton genserver
We have a process that is registered using:
def start_link do
case GenServer.start_link(__MODULE__, :ok, name: {:global, __MODULE__}) do
{:ok, pid} ->
Logger.info "---- #{__MODULE__} worker started"
{:ok, pid}
{:error, {:already_started, pid}} ->
Logger.info "---- #{__MODULE__} worker already running"
{:ok, pid}
end
end
Currently, if we kill the node running the singleton, the other node doesn’t seem to notice that the node is down, and the killed processes aren’t restarted.
E.g Supervisor.which_children on the remaining node returns the remote pid pid<4554, 234, 0>, and :global.whereis_name returns :undefined
What we would like to see is that the supervisor restarts the process on the remaining node, but so far our attempts have been fruitless.
Marked As Solved
dom
This is a good example: GitHub - arjan/singleton: Global, supervised singleton processes for Elixir · GitHub
Also Liked
dideler
Another option, which I’ve seen in a codebase, is to lazily restart the GenServer when a client call notices that it’s down. This is instead of monitoring the process on every node and handling the :DOWN message as Singleton does.
e.g.
## Client API
def foo(name \\ __MODULE__) do
case GenServer.whereis({:global, name}) do
nil ->
# restart on an available node, e.g. via Supervisor.restart_child
GenServer.call({:global, name}, :foo)
pid ->
GenServer.call(pid, :foo)
end
end
## Server callbacks
def handle_call(:foo, _from, state) do
# update state and reply
end









