I've pushed an experimental branch for resolving netsplits in gproc.
I'd like to go over the code a bit more and do more testing, but since
it's time for the annual Swedish heathen rituals (Midsummer), I
expect it won't happen today. :P
https://github.com/uwiger/gproc/tree/split-brain
If anyone feels adventurous, I'd certainly appreciate some feedback.
In particular, I'd like to know if anyone really needs the protocol
between gproc_dist instances to be backward compatible for upgrade
purposes. I could fix that, but it would certainly be nicer to skip it. :)
BR,
Ulf W
The idea is that you add a deconflict method for each global
registration (default method is 'exit_all'). This can be done using
either gproc:reg(Key, Value, [Deconflict | OtherAttrs]),
or gproc:set_attributes(Key, [Deconflict | OtherAttrs]),
where Deconflict = gproc:deconflict(Method)
Method :: exit_all | smallest_pid | largest_pid
(More methods could be envisioned, esp. {Module, Function}).
From the edoc source:
%% @spec deconflict(Type) -> {gproc_deconflict, Type}.
%% @doc Attribute controlling reconciliation after split-brain.
%%
%% Certain network failures can result in gproc nodes becoming separated from
%% each other - a so-called 'split-brain' scenario. When the nodes reconnect,
%% there may be conflicting registrations in the gproc database. This function
%% instructs gproc on how to resolve such conflicts.
%%
%% The following deconflict methods are supported
%%
%% * `exit_all' - send an `exit(Pid, {gproc_conflict, Key})' signal to all
%% involved pids, and remove the registrations
%% * `smallest_pid' - send an `exit(Pid, {gproc_conflict, Key})' signal to the
%% smallest pid, and remove the corresponding registration.
%% * `largest_pid' - send an `exit(Pid, {gproc_conflict, Key})' signal to the
%% largest pid, and remove the corresponding registration.
Ulf Wiger, Co-founder & Developer Advocate, Feuerlabs Inc.
http://feuerlabs.com