Browse Source

Add reason to callbacks for registry.

Roberto Ostinelli 3 years ago
parent
commit
c2b30a4243

+ 1 - 1
docs.config

@@ -1,4 +1,4 @@
 {source_url, <<"https://github.com/ostinelli/syn">>}.
-{extras, [<<"README.md">>, <<"LICENSE.md">>]}.
+{extras, [<<"README.md">>]}.
 {main, <<"readme">>}.
 {proglang, erlang}.

+ 38 - 17
src/syn_event_handler.erl

@@ -37,6 +37,17 @@
 %% All of the callbacks, except for `resolve_registry_conflict/3', are called on all the nodes of the cluster.
 %% This allows you to receive events for the processes running on nodes that get shut down, or in case of net splits.
 %%
+%% The argument `Reason' in the callbacks can be:
+%% <ul>
+%% <li> `normal' for expected operations.</li>
+%% <li> Crash reasons when processes die (for `on_process_unregistered/5' and `on_process_left/5').</li>
+%% <li> `{syn_remote_scope_node_up, Scope, Node}' for `on_process_registered/5' and `on_process_joined/5'
+%%      when the callbacks are called due to nodes syncing.</li>
+%% <li> `{syn_remote_scope_node_down, Scope, Node}' for `on_process_unregistered/5' and `on_process_left/5'
+%%      when the callbacks are called due to nodes disconnecting.</li>
+%% <li> `syn_conflict_resolution' for `on_process_registered/5' and `on_process_unregistered/5'
+%%      during registry conflict resolution.</li>
+%% </ul>
 %% While all callbacks do not have a direct effect on Syn (their return value is ignored), a special case is the callback
 %% `resolve_registry_conflict/3'. If specified, this is the method that will be used to resolve registry conflicts when detected.
 %%
@@ -75,9 +86,10 @@
 %%     scope :: atom(),
 %%     name :: any(),
 %%     pid :: pid(),
-%%     meta :: any()
+%%     meta :: any(),
+%%     reason :: atom()
 %%   ) :: any()
-%%   def on_process_unregistered(scope, name, pid, meta) do
+%%   def on_process_unregistered(scope, name, pid, meta, reason) do
 %%   end
 %%
 %%   ‎@impl true
@@ -85,9 +97,10 @@
 %%     scope :: atom(),
 %%     group_name :: any(),
 %%     pid :: pid(),
-%%     meta :: any()
+%%     meta :: any(),
+%%     reason :: atom()
 %%   ) :: any()
-%%   def on_process_left(scope, group_name, pid, meta) do
+%%   def on_process_left(scope, group_name, pid, meta, reason) do
 %%   end
 %% end
 %% '''
@@ -102,18 +115,20 @@
 %%     Scope :: atom(),
 %%     Name :: any(),
 %%     Pid :: pid(),
-%%     Meta :: any()
+%%     Meta :: any(),
+%%     Reason :: atom()
 %% ) -> any().
-%% on_process_unregistered(Scope, Name, Pid, Meta) ->
+%% on_process_unregistered(Scope, Name, Pid, Meta, Reason) ->
 %%     ok.
 %%
 %% -spec on_process_left(
 %%     Scope :: atom(),
 %%     GroupName :: any(),
 %%     Pid :: pid(),
-%%     Meta :: any()
+%%     Meta :: any(),
+%%     Reason :: atom()
 %% ) -> any().
-%% on_process_left(Scope, GroupName, Pid, Meta) ->
+%% on_process_left(Scope, GroupName, Pid, Meta, Reason) ->
 %%     ok.
 %% '''
 %%
@@ -131,42 +146,48 @@
     Scope :: any(),
     Name :: any(),
     Pid :: pid(),
-    Meta :: any()
+    Meta :: any(),
+    Reason :: atom()
 ) -> any().
 
 -callback on_registry_process_updated(
     Scope :: any(),
     Name :: any(),
     Pid :: pid(),
-    Meta :: any()
+    Meta :: any(),
+    Reason :: atom()
 ) -> any().
 
 -callback on_process_unregistered(
     Scope :: any(),
     Name :: any(),
     Pid :: pid(),
-    Meta :: any()
+    Meta :: any(),
+    Reason :: atom()
 ) -> any().
 
 -callback on_process_joined(
     Scope :: any(),
     GroupName :: any(),
     Pid :: pid(),
-    Meta :: any()
+    Meta :: any(),
+    Reason :: atom()
 ) -> any().
 
 -callback on_group_process_updated(
     Scope :: any(),
     GroupName :: any(),
     Pid :: pid(),
-    Meta :: any()
+    Meta :: any(),
+    Reason :: atom()
 ) -> any().
 
 -callback on_process_left(
     Scope :: any(),
     GroupName :: any(),
     Pid :: pid(),
-    Meta :: any()
+    Meta :: any(),
+    Reason :: atom()
 ) -> any().
 
 -callback resolve_registry_conflict(
@@ -175,8 +196,8 @@
     {Pid2 :: pid(), Meta2 :: any(), Time2 :: non_neg_integer()}
 ) -> PidToKeep :: pid().
 
--optional_callbacks([on_process_registered/4, on_registry_process_updated/4, on_process_unregistered/4]).
--optional_callbacks([on_process_joined/4, on_group_process_updated/4, on_process_left/4]).
+-optional_callbacks([on_process_registered/5, on_registry_process_updated/5, on_process_unregistered/5]).
+-optional_callbacks([on_process_joined/5, on_group_process_updated/5, on_process_left/5]).
 -optional_callbacks([resolve_registry_conflict/3]).
 
 %% ===================================================================
@@ -195,7 +216,7 @@ ensure_event_handler_loaded() ->
 ) -> any().
 call_event_handler(CallbackMethod, Args) ->
     CustomEventHandler = get_custom_event_handler(),
-    case erlang:function_exported(CustomEventHandler, CallbackMethod, 4) of
+    case erlang:function_exported(CustomEventHandler, CallbackMethod, 5) of
         true ->
             try apply(CustomEventHandler, CallbackMethod, Args)
             catch Class:Reason:Stacktrace ->

+ 42 - 30
src/syn_registry.erl

@@ -101,7 +101,7 @@ register(Scope, Name, Pid, Meta) ->
             %% update table on caller node immediately so that subsequent calls have an updated registry
             add_to_local_table(Name, Pid, Meta, Time, undefined, TableByName, TableByPid),
             %% callback
-            syn_event_handler:call_event_handler(CallbackMethod, [Scope, Name, Pid, Meta]),
+            syn_event_handler:call_event_handler(CallbackMethod, [Scope, Name, Pid, Meta, normal]),
             %% return
             ok;
 
@@ -132,7 +132,7 @@ unregister(Scope, Name) ->
                             %% remove table on caller node immediately so that subsequent calls have an updated registry
                             remove_from_local_table(Name, Pid, TableByName, TableByPid),
                             %% callback
-                            syn_event_handler:call_event_handler(on_process_unregistered, [Scope, Name, Pid, Meta]),
+                            syn_event_handler:call_event_handler(on_process_unregistered, [Scope, Name, Pid, Meta, normal]),
                             %% return
                             ok;
 
@@ -214,14 +214,14 @@ handle_call({register_on_node, RequesterNode, Name, Pid, Meta}, _From, #state{
                         undefined -> erlang:monitor(process, Pid);  %% process is not monitored yet, add
                         MRef0 -> MRef0
                     end,
-                    do_register_on_node(Name, Pid, Meta, MRef, RequesterNode, on_process_registered, State);
+                    do_register_on_node(Name, Pid, Meta, normal, MRef, RequesterNode, on_process_registered, State);
 
                 {Name, Pid, Meta, _, _, _} ->
                     %% same pid, same meta
                     {reply, {ok, noop}, State};
 
                 {Name, Pid, _, _, MRef, _} ->
-                    do_register_on_node(Name, Pid, Meta, MRef, RequesterNode, on_registry_process_updated, State);
+                    do_register_on_node(Name, Pid, Meta, normal, MRef, RequesterNode, on_registry_process_updated, State);
 
                 _ ->
                     {reply, {{error, taken}, undefined}, State}
@@ -243,9 +243,9 @@ handle_call({unregister_on_node, RequesterNode, Name, Pid}, _From, #state{
             %% remove from table
             remove_from_local_table(Name, Pid, TableByName, TableByPid),
             %% callback
-            syn_event_handler:call_event_handler(on_process_unregistered, [Scope, Name, Pid, Meta]),
+            syn_event_handler:call_event_handler(on_process_unregistered, [Scope, Name, Pid, Meta, normal]),
             %% broadcast
-            syn_gen_scope:broadcast({'3.0', sync_unregister, Name, Pid, Meta}, [RequesterNode], State),
+            syn_gen_scope:broadcast({'3.0', sync_unregister, Name, Pid, Meta, normal}, [RequesterNode], State),
             %% return
             {reply, {ok, TableByPid}, State};
 
@@ -268,18 +268,25 @@ handle_call(Request, From, #state{scope = Scope} = State) ->
     {noreply, #state{}} |
     {noreply, #state{}, timeout() | hibernate | {continue, term()}} |
     {stop, Reason :: term(), #state{}}.
-handle_info({'3.0', sync_register, Name, Pid, Meta, Time}, State) ->
-    handle_registry_sync(Name, Pid, Meta, Time, State),
+handle_info({'3.0', sync_register, Name, Pid, Meta, Time, Reason}, State) ->
+    handle_registry_sync(Name, Pid, Meta, Time, Reason, State),
     {noreply, State};
 
-handle_info({'3.0', sync_unregister, Name, Pid, Meta}, #state{
+handle_info({'3.0', sync_unregister, Name, Pid, Meta, Reason}, #state{
     scope = Scope,
     table_by_name = TableByName,
     table_by_pid = TableByPid
 } = State) ->
-    remove_from_local_table(Name, Pid, TableByName, TableByPid),
-    %% callback
-    syn_event_handler:call_event_handler(on_process_unregistered, [Scope, Name, Pid, Meta]),
+    case find_registry_entry_by_name(Name, TableByName) of
+        {_, Pid, _, _, _, _} ->
+            remove_from_local_table(Name, Pid, TableByName, TableByPid),
+            %% callback
+            syn_event_handler:call_event_handler(on_process_unregistered, [Scope, Name, Pid, Meta, Reason]);
+
+         _ ->
+             %% not in table, nothing to do
+             ok
+    end,
     %% return
     {noreply, State};
 
@@ -300,9 +307,9 @@ handle_info({'DOWN', _MRef, process, Pid, Reason}, #state{
                 %% remove from table
                 remove_from_local_table(Name, Pid, TableByName, TableByPid),
                 %% callback
-                syn_event_handler:call_event_handler(on_process_unregistered, [Scope, Name, Pid, Meta]),
+                syn_event_handler:call_event_handler(on_process_unregistered, [Scope, Name, Pid, Meta, Reason]),
                 %% broadcast
-                syn_gen_scope:broadcast({'3.0', sync_unregister, Name, Pid, Meta}, State)
+                syn_gen_scope:broadcast({'3.0', sync_unregister, Name, Pid, Meta, Reason}, State)
             end, Entries)
     end,
     %% return
@@ -320,10 +327,10 @@ get_local_data(#state{table_by_name = TableByName}) ->
     {ok, get_registry_tuples_for_node(node(), TableByName)}.
 
 -spec save_remote_data(RemoteData :: term(), #state{}) -> any().
-save_remote_data(RegistryTuplesOfRemoteNode, State) ->
+save_remote_data(RegistryTuplesOfRemoteNode, #state{scope = Scope} = State) ->
     %% insert tuples
     lists:foreach(fun({Name, Pid, Meta, Time}) ->
-        handle_registry_sync(Name, Pid, Meta, Time, State)
+        handle_registry_sync(Name, Pid, Meta, Time, {syn_remote_scope_node_up, Scope, node(Pid)}, State)
     end, RegistryTuplesOfRemoteNode).
 
 -spec purge_local_data_for_node(Node :: node(), #state{}) -> any().
@@ -372,6 +379,7 @@ do_rebuild_monitors([{Name, Pid, Meta, Time} | T], NewMonitorRefs, #state{
     Name :: term(),
     Pid :: pid(),
     Meta :: term(),
+    Reason :: atom(),
     MRef :: reference() | undefined,
     RequesterNode :: node(),
     CallbackMethod :: atom(),
@@ -387,7 +395,7 @@ do_rebuild_monitors([{Name, Pid, Meta, Time} | T], NewMonitorRefs, #state{
         }},
         #state{}
     }.
-do_register_on_node(Name, Pid, Meta, MRef, RequesterNode, CallbackMethod, #state{
+do_register_on_node(Name, Pid, Meta, Reason, MRef, RequesterNode, CallbackMethod, #state{
     scope = Scope,
     table_by_name = TableByName,
     table_by_pid = TableByPid
@@ -396,9 +404,9 @@ do_register_on_node(Name, Pid, Meta, MRef, RequesterNode, CallbackMethod, #state
     Time = erlang:system_time(),
     add_to_local_table(Name, Pid, Meta, Time, MRef, TableByName, TableByPid),
     %% callback
-    syn_event_handler:call_event_handler(CallbackMethod, [Scope, Name, Pid, Meta]),
+    syn_event_handler:call_event_handler(CallbackMethod, [Scope, Name, Pid, Meta, Reason]),
     %% broadcast
-    syn_gen_scope:broadcast({'3.0', sync_register, Name, Pid, Meta, Time}, [RequesterNode], State),
+    syn_gen_scope:broadcast({'3.0', sync_register, Name, Pid, Meta, Time, Reason}, [RequesterNode], State),
     %% return
     {reply, {ok, {CallbackMethod, Time, TableByName, TableByPid}}, State}.
 
@@ -503,7 +511,9 @@ purge_registry_for_remote_node(Scope, Node, TableByName, TableByPid) when Node =
     RegistryTuples = get_registry_tuples_for_node(Node, TableByName),
     spawn(fun() ->
         lists:foreach(fun({Name, Pid, Meta, _Time}) ->
-            syn_event_handler:call_event_handler(on_process_unregistered, [Scope, Name, Pid, Meta])
+            syn_event_handler:call_event_handler(on_process_unregistered,
+                [Scope, Name, Pid, Meta, {syn_remote_scope_node_down, Scope, Node}]
+            )
         end, RegistryTuples)
     end),
     %% remove all from pid table
@@ -514,10 +524,11 @@ purge_registry_for_remote_node(Scope, Node, TableByName, TableByPid) when Node =
     Name :: term(),
     Pid :: pid(),
     Meta :: term(),
+    Reason :: atom(),
     Time :: non_neg_integer(),
     #state{}
 ) -> any().
-handle_registry_sync(Name, Pid, Meta, Time, #state{
+handle_registry_sync(Name, Pid, Meta, Time, Reason, #state{
     scope = Scope,
     table_by_name = TableByName,
     table_by_pid = TableByPid
@@ -527,7 +538,7 @@ handle_registry_sync(Name, Pid, Meta, Time, #state{
             %% no conflict
             add_to_local_table(Name, Pid, Meta, Time, undefined, TableByName, TableByPid),
             %% callback
-            syn_event_handler:call_event_handler(on_process_registered, [Scope, Name, Pid, Meta]);
+            syn_event_handler:call_event_handler(on_process_registered, [Scope, Name, Pid, Meta, Reason]);
 
         {_, Pid, TableMeta, _, MRef, _} ->
             %% same pid, more recent (because it comes from the same node, which means that it's sequential)
@@ -535,7 +546,8 @@ handle_registry_sync(Name, Pid, Meta, Time, #state{
             add_to_local_table(Name, Pid, Meta, Time, MRef, TableByName, TableByPid),
             %% callback (call only if meta update)
             case TableMeta =/= Meta of
-                true -> syn_event_handler:call_event_handler(on_registry_process_updated, [Scope, Name, Pid, Meta]);
+                true ->
+                    syn_event_handler:call_event_handler(on_registry_process_updated, [Scope, Name, Pid, Meta, Reason]);
                 _ -> ok
             end;
 
@@ -551,8 +563,8 @@ handle_registry_sync(Name, Pid, Meta, Time, #state{
             %% current node does not own any of the conflicting processes, update
             update_local_table(Name, TablePid, {Pid, Meta, Time, undefined}, TableByName, TableByPid),
             %% callbacks
-            syn_event_handler:call_event_handler(on_process_unregistered, [Scope, Name, TablePid, TableMeta]),
-            syn_event_handler:call_event_handler(on_process_registered, [Scope, Name, Pid, Meta]);
+            syn_event_handler:call_event_handler(on_process_unregistered, [Scope, Name, TablePid, TableMeta, Reason]),
+            syn_event_handler:call_event_handler(on_process_registered, [Scope, Name, Pid, Meta, Reason]);
 
         {_, _, _, _, _, _} ->
             %% race condition: incoming data is older, ignore
@@ -592,8 +604,8 @@ resolve_conflict(Scope, Name, {Pid, Meta, Time}, {TablePid, TableMeta, TableTime
                 false -> ok
             end,
             %% callbacks
-            syn_event_handler:call_event_handler(on_process_unregistered, [Scope, Name, TablePid, TableMeta]),
-            syn_event_handler:call_event_handler(on_process_registered, [Scope, Name, Pid, Meta]);
+            syn_event_handler:call_event_handler(on_process_unregistered, [Scope, Name, TablePid, TableMeta, syn_conflict_resolution]),
+            syn_event_handler:call_event_handler(on_process_registered, [Scope, Name, Pid, Meta, syn_conflict_resolution]);
 
         TablePid ->
             %% -> we keep the local pid, remote pid will be killed by the other node in the conflict
@@ -604,7 +616,7 @@ resolve_conflict(Scope, Name, {Pid, Meta, Time}, {TablePid, TableMeta, TableTime
             ResolveTime = erlang:system_time(),
             add_to_local_table(Name, TablePid, TableMeta, ResolveTime, TableMRef, TableByName, TableByPid),
             %% broadcast to all (including remote node to update the time)
-            syn_gen_scope:broadcast({'3.0', sync_register, Name, TablePid, TableMeta, ResolveTime}, State);
+            syn_gen_scope:broadcast({'3.0', sync_register, Name, TablePid, TableMeta, ResolveTime, syn_conflict_resolution}, State);
 
         Invalid ->
             error_logger:info_msg("SYN[~s<~s>] Registry CONFLICT for name ~p: ~p vs ~p -> none chosen (got: ~p)",
@@ -619,7 +631,7 @@ resolve_conflict(Scope, Name, {Pid, Meta, Time}, {TablePid, TableMeta, TableTime
                 false -> ok
             end,
             %% callback
-            syn_event_handler:call_event_handler(on_process_unregistered, [Scope, Name, TablePid, TableMeta]),
+            syn_event_handler:call_event_handler(on_process_unregistered, [Scope, Name, TablePid, TableMeta, syn_conflict_resolution]),
             %% broadcast to all but remote node, which will remove it during conflict resolution
-            syn_gen_scope:broadcast({'3.0', sync_unregister, Name, TablePid, TableMeta}, [node(Pid)], State)
+            syn_gen_scope:broadcast({'3.0', sync_unregister, Name, TablePid, TableMeta, syn_conflict_resolution}, [node(Pid)], State)
     end.

+ 139 - 52
test/syn_registry_SUITE.erl

@@ -1237,9 +1237,9 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_registered, CurrentNode, default, "proc-handler", Pid, <<"meta">>},
-        {on_process_registered, SlaveNode1, default, "proc-handler", Pid, <<"meta">>},
-        {on_process_registered, SlaveNode2, default, "proc-handler", Pid, <<"meta">>}
+        {on_process_registered, CurrentNode, default, "proc-handler", Pid, <<"meta">>, normal},
+        {on_process_registered, SlaveNode1, default, "proc-handler", Pid, <<"meta">>, normal},
+        {on_process_registered, SlaveNode2, default, "proc-handler", Pid, <<"meta">>, normal}
     ]),
     syn_test_suite_helper:assert_empty_queue(self()),
 
@@ -1248,9 +1248,9 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_registered, CurrentNode, default, "proc-handler-2", Pid2, <<"meta-for-2">>},
-        {on_process_registered, SlaveNode1, default, "proc-handler-2", Pid2, <<"meta-for-2">>},
-        {on_process_registered, SlaveNode2, default, "proc-handler-2", Pid2, <<"meta-for-2">>}
+        {on_process_registered, CurrentNode, default, "proc-handler-2", Pid2, <<"meta-for-2">>, normal},
+        {on_process_registered, SlaveNode1, default, "proc-handler-2", Pid2, <<"meta-for-2">>, normal},
+        {on_process_registered, SlaveNode2, default, "proc-handler-2", Pid2, <<"meta-for-2">>, normal}
     ]),
     syn_test_suite_helper:assert_empty_queue(self()),
 
@@ -1259,9 +1259,9 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_registry_process_updated, CurrentNode, default, "proc-handler", Pid, <<"new-meta">>},
-        {on_registry_process_updated, SlaveNode1, default, "proc-handler", Pid, <<"new-meta">>},
-        {on_registry_process_updated, SlaveNode2, default, "proc-handler", Pid, <<"new-meta">>}
+        {on_registry_process_updated, CurrentNode, default, "proc-handler", Pid, <<"new-meta">>, normal},
+        {on_registry_process_updated, SlaveNode1, default, "proc-handler", Pid, <<"new-meta">>, normal},
+        {on_registry_process_updated, SlaveNode2, default, "proc-handler", Pid, <<"new-meta">>, normal}
     ]),
     syn_test_suite_helper:assert_empty_queue(self()),
 
@@ -1270,9 +1270,9 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_registry_process_updated, CurrentNode, default, "proc-handler-2", Pid2, <<"meta-for-2-update">>},
-        {on_registry_process_updated, SlaveNode1, default, "proc-handler-2", Pid2, <<"meta-for-2-update">>},
-        {on_registry_process_updated, SlaveNode2, default, "proc-handler-2", Pid2, <<"meta-for-2-update">>}
+        {on_registry_process_updated, CurrentNode, default, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal},
+        {on_registry_process_updated, SlaveNode1, default, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal},
+        {on_registry_process_updated, SlaveNode2, default, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal}
     ]),
     syn_test_suite_helper:assert_empty_queue(self()),
 
@@ -1281,9 +1281,9 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_unregistered, CurrentNode, default, "proc-handler", Pid, <<"new-meta">>},
-        {on_process_unregistered, SlaveNode1, default, "proc-handler", Pid, <<"new-meta">>},
-        {on_process_unregistered, SlaveNode2, default, "proc-handler", Pid, <<"new-meta">>}
+        {on_process_unregistered, CurrentNode, default, "proc-handler", Pid, <<"new-meta">>, normal},
+        {on_process_unregistered, SlaveNode1, default, "proc-handler", Pid, <<"new-meta">>, normal},
+        {on_process_unregistered, SlaveNode2, default, "proc-handler", Pid, <<"new-meta">>, normal}
     ]),
     syn_test_suite_helper:assert_empty_queue(self()),
 
@@ -1292,9 +1292,9 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_unregistered, CurrentNode, default, "proc-handler-2", Pid2, <<"meta-for-2-update">>},
-        {on_process_unregistered, SlaveNode1, default, "proc-handler-2", Pid2, <<"meta-for-2-update">>},
-        {on_process_unregistered, SlaveNode2, default, "proc-handler-2", Pid2, <<"meta-for-2-update">>}
+        {on_process_unregistered, CurrentNode, default, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal},
+        {on_process_unregistered, SlaveNode1, default, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal},
+        {on_process_unregistered, SlaveNode2, default, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal}
     ]),
     syn_test_suite_helper:assert_empty_queue(self()),
 
@@ -1308,9 +1308,9 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_registered, CurrentNode, default, remote_on_1, PidRemoteOn1, <<"netsplit">>},
-        {on_process_registered, SlaveNode1, default, remote_on_1, PidRemoteOn1, <<"netsplit">>},
-        {on_process_registered, SlaveNode2, default, remote_on_1, PidRemoteOn1, <<"netsplit">>}
+        {on_process_registered, CurrentNode, default, remote_on_1, PidRemoteOn1, <<"netsplit">>, normal},
+        {on_process_registered, SlaveNode1, default, remote_on_1, PidRemoteOn1, <<"netsplit">>, normal},
+        {on_process_registered, SlaveNode2, default, remote_on_1, PidRemoteOn1, <<"netsplit">>, normal}
     ]),
     syn_test_suite_helper:assert_empty_queue(self()),
 
@@ -1322,7 +1322,7 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_unregistered, SlaveNode2, default, remote_on_1, PidRemoteOn1, <<"netsplit">>}
+        {on_process_unregistered, SlaveNode2, default, remote_on_1, PidRemoteOn1, <<"netsplit">>, {syn_remote_scope_node_down, default, SlaveNode1}}
     ]),
     syn_test_suite_helper:assert_empty_queue(self()),
 
@@ -1335,7 +1335,7 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_registered, SlaveNode2, default, remote_on_1, PidRemoteOn1, <<"netsplit">>}
+        {on_process_registered, SlaveNode2, default, remote_on_1, PidRemoteOn1, <<"netsplit">>, {syn_remote_scope_node_up, default, SlaveNode1}}
     ]),
     syn_test_suite_helper:assert_empty_queue(self()),
 
@@ -1344,9 +1344,9 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_unregistered, CurrentNode, default, remote_on_1, PidRemoteOn1, <<"netsplit">>},
-        {on_process_unregistered, SlaveNode1, default, remote_on_1, PidRemoteOn1, <<"netsplit">>},
-        {on_process_unregistered, SlaveNode2, default, remote_on_1, PidRemoteOn1, <<"netsplit">>}
+        {on_process_unregistered, CurrentNode, default, remote_on_1, PidRemoteOn1, <<"netsplit">>, killed},
+        {on_process_unregistered, SlaveNode1, default, remote_on_1, PidRemoteOn1, <<"netsplit">>, killed},
+        {on_process_unregistered, SlaveNode2, default, remote_on_1, PidRemoteOn1, <<"netsplit">>, killed}
     ]),
     syn_test_suite_helper:assert_empty_queue(self()),
 
@@ -1366,11 +1366,11 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_registered, CurrentNode, default, "proc-confict", Pid2RemoteOn1, <<"meta-1">>},
-        {on_process_unregistered, CurrentNode, default, "proc-confict", Pid2RemoteOn1, <<"meta-1">>},
-        {on_process_registered, CurrentNode, default, "proc-confict", Pid2RemoteOn2, <<"meta-2">>},
-        {on_process_registered, SlaveNode1, default, "proc-confict", Pid2RemoteOn1, <<"meta-1">>},
-        {on_process_registered, SlaveNode2, default, "proc-confict", Pid2RemoteOn2, <<"meta-2">>}
+        {on_process_registered, CurrentNode, default, "proc-confict", Pid2RemoteOn1, <<"meta-1">>, normal},
+        {on_process_unregistered, CurrentNode, default, "proc-confict", Pid2RemoteOn1, <<"meta-1">>, normal},
+        {on_process_registered, CurrentNode, default, "proc-confict", Pid2RemoteOn2, <<"meta-2">>, normal},
+        {on_process_registered, SlaveNode1, default, "proc-confict", Pid2RemoteOn1, <<"meta-1">>, normal},
+        {on_process_registered, SlaveNode2, default, "proc-confict", Pid2RemoteOn2, <<"meta-2">>, normal}
     ]),
     syn_test_suite_helper:assert_empty_queue(self()),
 
@@ -1382,20 +1382,20 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_unregistered, SlaveNode1, default, "proc-confict", Pid2RemoteOn1, <<"meta-1">>},
-        {on_process_registered, SlaveNode1, default, "proc-confict", Pid2RemoteOn2, <<"meta-2">>}
+        {on_process_unregistered, SlaveNode1, default, "proc-confict", Pid2RemoteOn1, <<"meta-1">>, syn_conflict_resolution},
+        {on_process_registered, SlaveNode1, default, "proc-confict", Pid2RemoteOn2, <<"meta-2">>, syn_conflict_resolution}
     ]),
     syn_test_suite_helper:assert_empty_queue(self()),
 
-    %% clean
+    %% kill
     syn_test_suite_helper:kill_process(Pid2RemoteOn1),
     syn_test_suite_helper:kill_process(Pid2RemoteOn2),
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_unregistered, CurrentNode, default, "proc-confict", Pid2RemoteOn2, <<"meta-2">>},
-        {on_process_unregistered, SlaveNode1, default, "proc-confict", Pid2RemoteOn2, <<"meta-2">>},
-        {on_process_unregistered, SlaveNode2, default, "proc-confict", Pid2RemoteOn2, <<"meta-2">>}
+        {on_process_unregistered, CurrentNode, default, "proc-confict", Pid2RemoteOn2, <<"meta-2">>, killed},
+        {on_process_unregistered, SlaveNode1, default, "proc-confict", Pid2RemoteOn2, <<"meta-2">>, killed},
+        {on_process_unregistered, SlaveNode2, default, "proc-confict", Pid2RemoteOn2, <<"meta-2">>, killed}
     ]),
     syn_test_suite_helper:assert_empty_queue(self()),
 
@@ -1428,6 +1428,10 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
     ok = rpc:call(SlaveNode1, syn, add_node_to_scopes, [[custom_scope_bc]]),
     ok = rpc:call(SlaveNode2, syn, add_node_to_scopes, [[custom_scope_bc]]),
 
+    %% current node
+    TestPid = self(),
+    CurrentNode = node(),
+
     %% partial netsplit (1 cannot see 2)
     rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
     syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
@@ -1439,10 +1443,23 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
     PidOn2 = syn_test_suite_helper:start_process(SlaveNode2),
 
     %% --> conflict by netsplit
-    ok = rpc:call(SlaveNode1, syn, register, ["proc-confict-by-netsplit-custom", PidOn1, keepthis]),
-    ok = rpc:call(SlaveNode2, syn, register, ["proc-confict-by-netsplit-custom", PidOn2, "meta-2"]),
-    ok = rpc:call(SlaveNode1, syn, register, [custom_scope_bc, "proc-confict-by-netsplit-scoped-custom", PidOn1, keepthis]),
-    ok = rpc:call(SlaveNode2, syn, register, [custom_scope_bc, "proc-confict-by-netsplit-scoped-custom", PidOn2, "meta-2"]),
+    ok = rpc:call(SlaveNode1, syn, register, ["proc-confict-by-netsplit-custom", PidOn1, {recipient, TestPid, keepthis}]),
+    ok = rpc:call(SlaveNode2, syn, register, ["proc-confict-by-netsplit-custom", PidOn2, {recipient, TestPid, "meta-2"}]),
+    ok = rpc:call(SlaveNode1, syn, register, [custom_scope_bc, "proc-confict-by-netsplit-scoped-custom", PidOn1, {recipient, TestPid, keepthis}]),
+    ok = rpc:call(SlaveNode2, syn, register, [custom_scope_bc, "proc-confict-by-netsplit-scoped-custom", PidOn2, {recipient, TestPid, "meta-2"}]),
+
+    %% check callbacks
+    syn_test_suite_helper:assert_received_messages([
+        {on_process_registered, CurrentNode, default, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
+        {on_process_unregistered, CurrentNode, default, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
+        {on_process_registered, CurrentNode, default, "proc-confict-by-netsplit-custom", PidOn2, "meta-2", normal},
+
+        {on_process_registered, SlaveNode1, default, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
+        {on_process_registered, SlaveNode2, default, "proc-confict-by-netsplit-custom", PidOn2, "meta-2", normal},
+        {on_process_registered, SlaveNode1, custom_scope_bc, "proc-confict-by-netsplit-scoped-custom", PidOn1, keepthis, normal},
+        {on_process_registered, SlaveNode2, custom_scope_bc, "proc-confict-by-netsplit-scoped-custom", PidOn2, "meta-2", normal}
+    ]),
+    syn_test_suite_helper:assert_empty_queue(self()),
 
     %% re-join
     rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
@@ -1452,15 +1469,15 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
 
     %% retrieve
     syn_test_suite_helper:assert_wait(
-        {PidOn1, keepthis},
+        {PidOn1, {recipient, TestPid, keepthis}},
         fun() -> syn:lookup("proc-confict-by-netsplit-custom") end
     ),
     syn_test_suite_helper:assert_wait(
-        {PidOn1, keepthis},
+        {PidOn1, {recipient, TestPid, keepthis}},
         fun() -> rpc:call(SlaveNode1, syn, lookup, ["proc-confict-by-netsplit-custom"]) end
     ),
     syn_test_suite_helper:assert_wait(
-        {PidOn1, keepthis},
+        {PidOn1, {recipient, TestPid, keepthis}},
         fun() -> rpc:call(SlaveNode2, syn, lookup, ["proc-confict-by-netsplit-custom"]) end
     ),
     1 = syn:registry_count(),
@@ -1476,11 +1493,11 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
     1 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode1]),
     0 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode2]),
     syn_test_suite_helper:assert_wait(
-        {PidOn1, keepthis},
+        {PidOn1, {recipient, TestPid, keepthis}},
         fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_bc, "proc-confict-by-netsplit-scoped-custom"]) end
     ),
     syn_test_suite_helper:assert_wait(
-        {PidOn1, keepthis},
+        {PidOn1, {recipient, TestPid, keepthis}},
         fun() -> rpc:call(SlaveNode2, syn, lookup, [custom_scope_bc, "proc-confict-by-netsplit-scoped-custom"]) end
     ),
     1 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc]),
@@ -1492,6 +1509,17 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
     1 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, SlaveNode1]),
     0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, SlaveNode2]),
 
+    syn_test_suite_helper:assert_received_messages([
+        {on_process_unregistered, CurrentNode, default, "proc-confict-by-netsplit-custom", PidOn2, "meta-2", syn_conflict_resolution},
+        {on_process_registered, CurrentNode, default, "proc-confict-by-netsplit-custom", PidOn1, keepthis, syn_conflict_resolution},
+
+        {on_process_unregistered, SlaveNode2, default, "proc-confict-by-netsplit-custom", PidOn2, "meta-2", syn_conflict_resolution},
+        {on_process_registered, SlaveNode2, default, "proc-confict-by-netsplit-custom", PidOn1, keepthis, syn_conflict_resolution},
+        {on_process_unregistered, SlaveNode2, custom_scope_bc, "proc-confict-by-netsplit-scoped-custom", PidOn2, "meta-2", syn_conflict_resolution},
+        {on_process_registered, SlaveNode2, custom_scope_bc, "proc-confict-by-netsplit-scoped-custom", PidOn1, keepthis, syn_conflict_resolution}
+    ]),
+    syn_test_suite_helper:assert_empty_queue(self()),
+
     %% process alive (discarded process does not get killed with a custom handler)
     syn_test_suite_helper:assert_wait(
         true,
@@ -1504,6 +1532,9 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
 
     %% clean up default scope
     syn:unregister("proc-confict-by-netsplit-custom"),
+    ok = rpc:call(SlaveNode1, syn, unregister, [custom_scope_bc, "proc-confict-by-netsplit-scoped-custom"]),
+
+    %% retrieve
     syn_test_suite_helper:assert_wait(
         undefined,
         fun() -> syn:lookup("proc-confict-by-netsplit-custom") end
@@ -1516,6 +1547,24 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
         undefined,
         fun() -> rpc:call(SlaveNode2, syn, lookup, ["proc-confict-by-netsplit-custom"]) end
     ),
+    syn_test_suite_helper:assert_wait(
+        undefined,
+        fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_bc, "proc-confict-by-netsplit-scoped-custom"]) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        undefined,
+        fun() -> rpc:call(SlaveNode2, syn, lookup, [custom_scope_bc, "proc-confict-by-netsplit-scoped-custom"]) end
+    ),
+
+    %% check callbacks
+    syn_test_suite_helper:assert_received_messages([
+        {on_process_unregistered, CurrentNode, default, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
+        {on_process_unregistered, SlaveNode1, default, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
+        {on_process_unregistered, SlaveNode2, default, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
+        {on_process_unregistered, SlaveNode1, custom_scope_bc, "proc-confict-by-netsplit-scoped-custom", PidOn1, keepthis, normal},
+        {on_process_unregistered, SlaveNode2, custom_scope_bc, "proc-confict-by-netsplit-scoped-custom", PidOn1, keepthis, normal}
+    ]),
+    syn_test_suite_helper:assert_empty_queue(self()),
 
     %% --> conflict by netsplit, which returns invalid pid
     %% partial netsplit (1 cannot see 2)
@@ -1524,9 +1573,20 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
     syn_test_suite_helper:assert_cluster(SlaveNode1, [node()]),
     syn_test_suite_helper:assert_cluster(SlaveNode2, [node()]),
 
-    %% update meta to not select any process
-    ok = rpc:call(SlaveNode1, syn, register, ["proc-confict-by-netsplit-custom-other-pid", PidOn1, "meta-1"]),
-    ok = rpc:call(SlaveNode2, syn, register, ["proc-confict-by-netsplit-custom-other-pid", PidOn2, "meta-2"]),
+    %% register with meta with no 'keepthis' element
+    ok = rpc:call(SlaveNode1, syn, register, ["proc-confict-by-netsplit-custom-other-pid", PidOn1, {recipient, TestPid, "meta-1"}]),
+    ok = rpc:call(SlaveNode2, syn, register, ["proc-confict-by-netsplit-custom-other-pid", PidOn2, {recipient, TestPid, "meta-2"}]),
+
+    %% check callbacks
+    syn_test_suite_helper:assert_received_messages([
+        {on_process_registered, CurrentNode, default, "proc-confict-by-netsplit-custom-other-pid", PidOn1, "meta-1", normal},
+        {on_process_unregistered, CurrentNode, default, "proc-confict-by-netsplit-custom-other-pid", PidOn1, "meta-1", normal},
+        {on_process_registered, CurrentNode, default, "proc-confict-by-netsplit-custom-other-pid", PidOn2, "meta-2", normal},
+
+        {on_process_registered, SlaveNode1, default, "proc-confict-by-netsplit-custom-other-pid", PidOn1, "meta-1", normal},
+        {on_process_registered, SlaveNode2, default, "proc-confict-by-netsplit-custom-other-pid", PidOn2, "meta-2", normal}
+    ]),
+    syn_test_suite_helper:assert_empty_queue(self()),
 
     %% re-join
     rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
@@ -1560,6 +1620,14 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
     0 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode1]),
     0 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode2]),
 
+    %% check callbacks
+    syn_test_suite_helper:assert_received_messages([
+        {on_process_unregistered, CurrentNode, default, "proc-confict-by-netsplit-custom-other-pid", PidOn2, "meta-2", syn_conflict_resolution},
+        {on_process_unregistered, SlaveNode1, default, "proc-confict-by-netsplit-custom-other-pid", PidOn1, "meta-1", syn_conflict_resolution},
+        {on_process_unregistered, SlaveNode2, default, "proc-confict-by-netsplit-custom-other-pid", PidOn2, "meta-2", syn_conflict_resolution}
+    ]),
+    syn_test_suite_helper:assert_empty_queue(self()),
+
     %% process alive (discarded process does not get killed with a custom handler)
     syn_test_suite_helper:assert_wait(
         true,
@@ -1578,9 +1646,20 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
     syn_test_suite_helper:assert_cluster(SlaveNode1, [node()]),
     syn_test_suite_helper:assert_cluster(SlaveNode2, [node()]),
 
-    %% update meta to not select any process
-    ok = rpc:call(SlaveNode1, syn, register, ["proc-confict-by-netsplit-custom-crash", PidOn1, crash]),
-    ok = rpc:call(SlaveNode2, syn, register, ["proc-confict-by-netsplit-custom-crash", PidOn2, crash]),
+    %% register with meta with no 'crash' element
+    ok = rpc:call(SlaveNode1, syn, register, ["proc-confict-by-netsplit-custom-crash", PidOn1, {recipient, TestPid, crash}]),
+    ok = rpc:call(SlaveNode2, syn, register, ["proc-confict-by-netsplit-custom-crash", PidOn2, {recipient, TestPid, crash}]),
+
+    %% check callbacks
+    syn_test_suite_helper:assert_received_messages([
+        {on_process_registered, CurrentNode, default, "proc-confict-by-netsplit-custom-crash", PidOn1, crash, normal},
+        {on_process_unregistered, CurrentNode, default, "proc-confict-by-netsplit-custom-crash", PidOn1, crash, normal},
+        {on_process_registered, CurrentNode, default, "proc-confict-by-netsplit-custom-crash", PidOn2, crash, normal},
+
+        {on_process_registered, SlaveNode1, default, "proc-confict-by-netsplit-custom-crash", PidOn1, crash, normal},
+        {on_process_registered, SlaveNode2, default, "proc-confict-by-netsplit-custom-crash", PidOn2, crash, normal}
+    ]),
+    syn_test_suite_helper:assert_empty_queue(self()),
 
     %% re-join
     rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
@@ -1614,6 +1693,14 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
     0 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode1]),
     0 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode2]),
 
+    %% check callbacks
+    syn_test_suite_helper:assert_received_messages([
+        {on_process_unregistered, CurrentNode, default, "proc-confict-by-netsplit-custom-crash", PidOn2, crash, syn_conflict_resolution},
+        {on_process_unregistered, SlaveNode1, default, "proc-confict-by-netsplit-custom-crash", PidOn1, crash, syn_conflict_resolution},
+        {on_process_unregistered, SlaveNode2, default, "proc-confict-by-netsplit-custom-crash", PidOn2, crash, syn_conflict_resolution}
+    ]),
+    syn_test_suite_helper:assert_empty_queue(self()),
+
     %% process alive (discarded process does not get killed with a custom handler)
     syn_test_suite_helper:assert_wait(
         true,

+ 18 - 18
test/syn_test_event_handler_callbacks.erl

@@ -26,27 +26,27 @@
 -module(syn_test_event_handler_callbacks).
 -behaviour(syn_event_handler).
 
--export([on_process_registered/4]).
--export([on_process_unregistered/4]).
--export([on_registry_process_updated/4]).
--export([on_process_joined/4]).
--export([on_process_left/4]).
--export([on_group_process_updated/4]).
+-export([on_process_registered/5]).
+-export([on_process_unregistered/5]).
+-export([on_registry_process_updated/5]).
+-export([on_process_joined/5]).
+-export([on_process_left/5]).
+-export([on_group_process_updated/5]).
 
-on_process_registered(Scope, Name, Pid, {recipient, RecipientPid, AdditionalMeta}) ->
-    RecipientPid ! {on_process_registered, node(), Scope, Name, Pid, AdditionalMeta}.
+on_process_registered(Scope, Name, Pid, {recipient, RecipientPid, AdditionalMeta}, Reason) ->
+    RecipientPid ! {on_process_registered, node(), Scope, Name, Pid, AdditionalMeta, Reason}.
 
-on_process_unregistered(Scope, Name, Pid, {recipient, RecipientPid, AdditionalMeta}) ->
-    RecipientPid ! {on_process_unregistered, node(), Scope, Name, Pid, AdditionalMeta}.
+on_process_unregistered(Scope, Name, Pid, {recipient, RecipientPid, AdditionalMeta}, Reason) ->
+    RecipientPid ! {on_process_unregistered, node(), Scope, Name, Pid, AdditionalMeta, Reason}.
 
-on_registry_process_updated(Scope, Name, Pid, {recipient, RecipientPid, AdditionalMeta}) ->
-    RecipientPid ! {on_registry_process_updated, node(), Scope, Name, Pid, AdditionalMeta}.
+on_registry_process_updated(Scope, Name, Pid, {recipient, RecipientPid, AdditionalMeta}, Reason) ->
+    RecipientPid ! {on_registry_process_updated, node(), Scope, Name, Pid, AdditionalMeta, Reason}.
 
-on_process_joined(Scope, GroupName, Pid, {recipient, RecipientPid, AdditionalMeta}) ->
-    RecipientPid ! {on_process_joined, node(), Scope, GroupName, Pid, AdditionalMeta}.
+on_process_joined(Scope, GroupName, Pid, {recipient, RecipientPid, AdditionalMeta}, Reason) ->
+    RecipientPid ! {on_process_joined, node(), Scope, GroupName, Pid, AdditionalMeta, Reason}.
 
-on_process_left(Scope, GroupName, Pid, {recipient, RecipientPid, AdditionalMeta}) ->
-    RecipientPid ! {on_process_left, node(), Scope, GroupName, Pid, AdditionalMeta}.
+on_process_left(Scope, GroupName, Pid, {recipient, RecipientPid, AdditionalMeta}, Reason) ->
+    RecipientPid ! {on_process_left, node(), Scope, GroupName, Pid, AdditionalMeta, Reason}.
 
-on_group_process_updated(Scope, GroupName, Pid, {recipient, RecipientPid, AdditionalMeta}) ->
-    RecipientPid ! {on_group_process_updated, node(), Scope, GroupName, Pid, AdditionalMeta}.
+on_group_process_updated(Scope, GroupName, Pid, {recipient, RecipientPid, AdditionalMeta}, Reason) ->
+    RecipientPid ! {on_group_process_updated, node(), Scope, GroupName, Pid, AdditionalMeta, Reason}.

+ 11 - 13
test/syn_test_event_handler_resolution.erl

@@ -26,23 +26,21 @@
 -module(syn_test_event_handler_resolution).
 -behaviour(syn_event_handler).
 
+-export([on_process_registered/5]).
+-export([on_process_unregistered/5]).
 -export([resolve_registry_conflict/4]).
 
--spec resolve_registry_conflict(
-    Scope :: atom(),
-    Name :: any(),
-    {LocalPid :: pid(), LocalMeta :: any()},
-    {RemotePid :: pid(), RemoteMeta :: any()}
-) -> PidToKeep :: pid().
-resolve_registry_conflict(default, _Name, {Pid1, keepthis, _Time1}, {_Pid2, _Meta2, _Time2}) ->
-    Pid1;
-resolve_registry_conflict(custom_scope_bc, _Name, {Pid1, keepthis, _Time1}, {_Pid2, _Meta2, _Time2}) ->
+on_process_registered(Scope, Name, Pid, {recipient, RecipientPid, AdditionalMeta}, Reason) ->
+    RecipientPid ! {on_process_registered, node(), Scope, Name, Pid, AdditionalMeta, Reason}.
+
+on_process_unregistered(Scope, Name, Pid, {recipient, RecipientPid, AdditionalMeta}, Reason) ->
+    RecipientPid ! {on_process_unregistered, node(), Scope, Name, Pid, AdditionalMeta, Reason}.
+
+resolve_registry_conflict(_Scope, _Name, {Pid1, {recipient, _, keepthis}, _Time1}, {_Pid2, _Meta2, _Time2}) ->
     Pid1;
-resolve_registry_conflict(default, _Name, {_Pid1, _Meta1, _Time1}, {Pid2, keepthis, _Time2}) ->
-    Pid2;
-resolve_registry_conflict(custom_scope_bc, _Name, {_Pid1, _Meta1, _Time1}, {Pid2, keepthis, _Time2}) ->
+resolve_registry_conflict(_Scope, _Name, {_Pid1, _Meta1, _Time1}, {Pid2, {recipient, _, keepthis}, _Time2}) ->
     Pid2;
 resolve_registry_conflict(default, _Name, {Pid1, _Meta1, _Time1}, {_Pid2, _Meta2, _Time2}) ->
     syn_test_suite_helper:start_process(node(Pid1));
-resolve_registry_conflict(default, _Name, {_Pid1, crash, _Time1}, {_Pid2, crash, _Time2}) ->
+resolve_registry_conflict(default, _Name, {_Pid1, {recipient, _, crash}, _Time1}, {_Pid2, {recipient, _, crash}, _Time2}) ->
     exit(self(), syn_test_crash).

+ 18 - 8
test/syn_test_suite_helper.erl

@@ -31,9 +31,9 @@
 -export([clean_after_test/0]).
 -export([start_process/0, start_process/1, start_process/2]).
 -export([kill_process/1]).
--export([flush_inbox/0]).
 -export([wait_cluster_mesh_connected/1]).
 -export([wait_process_name_ready/1, wait_process_name_ready/2]).
+-export([wait_message_queue_empty/0]).
 -export([assert_cluster/2]).
 -export([assert_registry_scope_subcluster/3, assert_groups_scope_subcluster/3]).
 -export([assert_received_messages/1]).
@@ -112,13 +112,6 @@ kill_process(Pid) when is_pid(Pid) ->
             ok
     end.
 
-flush_inbox() ->
-    receive
-        _ -> flush_inbox()
-    after 0 ->
-        ok
-    end.
-
 wait_cluster_mesh_connected(Nodes) ->
     wait_cluster_mesh_connected(Nodes, os:system_time(millisecond)).
 wait_cluster_mesh_connected(Nodes, StartAt) ->
@@ -174,6 +167,16 @@ wait_process_name_ready(Name, StartAt) ->
             end
     end.
 
+wait_message_queue_empty() ->
+    timer:sleep(500),
+    syn_test_suite_helper:assert_wait(
+        ok,
+        fun() ->
+            flush_inbox(),
+            syn_test_suite_helper:assert_empty_queue(self())
+        end
+    ).
+
 assert_cluster(Node, ExpectedNodes) ->
     assert_cluster(Node, ExpectedNodes, os:system_time(millisecond)).
 assert_cluster(Node, ExpectedNodes, StartAt) ->
@@ -316,6 +319,13 @@ do_assert_received_messages(MissingMessages, UnexpectedMessages) ->
         [lists:reverse(MissingMessages), lists:reverse(UnexpectedMessages)]
     ).
 
+flush_inbox() ->
+    receive
+        _ -> flush_inbox()
+    after 0 ->
+        ok
+    end.
+
 get_line_from_stacktrace() ->
     {current_stacktrace, Stacktrace} = process_info(self(), current_stacktrace),
     [{_, _, _, FileInfo} | _] = lists:dropwhile(fun({Module, _Method, _Arity, _FileInfo}) ->