Browse Source

Trigger callbacks for processes died during a scope process crash.

Roberto Ostinelli 3 years ago
parent
commit
5136b7b4ac
6 changed files with 127 additions and 64 deletions
  1. 8 7
      INTERNALS.md
  2. 2 0
      src/syn_event_handler.erl
  3. 14 9
      src/syn_pg.erl
  4. 14 9
      src/syn_registry.erl
  5. 35 10
      test/syn_pg_SUITE.erl
  6. 54 29
      test/syn_registry_SUITE.erl

+ 8 - 7
INTERNALS.md

@@ -24,14 +24,15 @@ the following happens:
 
   * 2 new `gen_server` processes get created (aka "scope processes"), in the given example named `syn_registry_users` (for registry)
   and `syn_pg_users` (for process groups).
-  * 4 new ETS tables get created:
-    * `syn_registry_by_name_users` (of type `set`).
-    * `syn_registry_by_pid_users` (of type `bag`).
-    * `syn_pg_by_name_users` (of type `ordered_set`).
-    * `syn_pg_by_pid_users` (of type `ordered_set`).
+    * 4 new ETS tables get created:
+      * `syn_registry_by_name_users` (of type `set`).
+      * `syn_registry_by_pid_users` (of type `bag`).
+      * `syn_pg_by_name_users` (of type `ordered_set`).
+      * `syn_pg_by_pid_users` (of type `ordered_set`).
     
-    These tables are owned by the `syn_backbone` process, so that if the related scope processes were to crash, the data
-    is not lost and the scope processes can easily recover.
+      These tables are owned by the `syn_backbone` process, so that if the related scope processes were to crash the data is not lost.
+      In such case, upon respawn the scope process purges the data of all remote nodes, then rebuilds the monitors
+      for the local processes that are still alive and removes from the tables the ones that meanwhile died.
   * The 2 newly created scope processes each join a subcluster (one for registry, one for process groups)
   with the other processes in the Erlang distributed cluster that handle the same Scope (which have the same name).
 

+ 2 - 0
src/syn_event_handler.erl

@@ -47,6 +47,8 @@
 %%      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>
+%% <li> `undefined' for `on_process_unregistered/5' and `on_process_left/5' when the processes died while the
+%%      scope process had crashed.</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.

+ 14 - 9
src/syn_pg.erl

@@ -241,7 +241,7 @@ init(#state{
 }) ->
     %% purge remote & rebuild
     purge_groups_for_remote_nodes(Scope, TableByName, TableByPid),
-    rebuild_monitors(TableByName, TableByPid),
+    rebuild_monitors(Scope, TableByName, TableByPid),
     %% init
     HandlerState = #{},
     {ok, HandlerState}.
@@ -400,19 +400,20 @@ purge_local_data_for_node(Node, #state{
 %% ===================================================================
 %% Internal
 %% ===================================================================
--spec rebuild_monitors(TableByName :: atom(), TableByPid :: atom()) -> ok.
-rebuild_monitors(TableByName, TableByPid) ->
+-spec rebuild_monitors(Scope :: atom(), TableByName :: atom(), TableByPid :: atom()) -> ok.
+rebuild_monitors(Scope, TableByName, TableByPid) ->
     GroupsTuples = get_groups_tuples_for_node(node(), TableByName),
-    do_rebuild_monitors(GroupsTuples, #{}, TableByName, TableByPid).
+    do_rebuild_monitors(GroupsTuples, #{}, Scope, TableByName, TableByPid).
 
 -spec do_rebuild_monitors(
     [syn_pg_tuple()],
     #{pid() => reference()},
+    Scope :: atom(),
     TableByName :: atom(),
     TableByPid :: atom()
 ) -> ok.
-do_rebuild_monitors([], _, _, _) -> ok;
-do_rebuild_monitors([{GroupName, Pid, Meta, Time} | T], NewMRefs, TableByName, TableByPid) ->
+do_rebuild_monitors([], _, _, _, _) -> ok;
+do_rebuild_monitors([{GroupName, Pid, Meta, Time} | T], NewMRefs, Scope, TableByName, TableByPid) ->
     remove_from_local_table(GroupName, Pid, TableByName, TableByPid),
     case is_process_alive(Pid) of
         true ->
@@ -420,15 +421,19 @@ do_rebuild_monitors([{GroupName, Pid, Meta, Time} | T], NewMRefs, TableByName, T
                 error ->
                     MRef = erlang:monitor(process, Pid),
                     add_to_local_table(GroupName, Pid, Meta, Time, MRef, TableByName, TableByPid),
-                    do_rebuild_monitors(T, maps:put(Pid, MRef, NewMRefs), TableByName, TableByPid);
+                    do_rebuild_monitors(T, maps:put(Pid, MRef, NewMRefs), Scope, TableByName, TableByPid);
 
                 {ok, MRef} ->
                     add_to_local_table(GroupName, Pid, Meta, Time, MRef, TableByName, TableByPid),
-                    do_rebuild_monitors(T, NewMRefs, TableByName, TableByPid)
+                    do_rebuild_monitors(T, NewMRefs, Scope, TableByName, TableByPid)
             end;
 
         _ ->
-            do_rebuild_monitors(T, NewMRefs, TableByName, TableByPid)
+            %% process died meanwhile, callback
+            %% the remote callbacks will have been called when the scope process crash triggered them
+            syn_event_handler:call_event_handler(on_process_left, [Scope, GroupName, Pid, Meta, undefined]),
+            %% loop
+            do_rebuild_monitors(T, NewMRefs, Scope, TableByName, TableByPid)
     end.
 
 -spec do_join_on_node(

+ 14 - 9
src/syn_registry.erl

@@ -159,7 +159,7 @@ init(#state{
 }) ->
     %% purge remote & rebuild
     purge_registry_for_remote_nodes(Scope, TableByName, TableByPid),
-    rebuild_monitors(TableByName, TableByPid),
+    rebuild_monitors(Scope, TableByName, TableByPid),
     %% init
     HandlerState = #{},
     {ok, HandlerState}.
@@ -324,19 +324,20 @@ purge_local_data_for_node(Node, #state{
 %% ===================================================================
 %% Internal
 %% ===================================================================
--spec rebuild_monitors(TableByName :: atom(), TableByPid :: atom()) -> ok.
-rebuild_monitors(TableByName, TableByPid) ->
+-spec rebuild_monitors(Scope :: atom(), TableByName :: atom(), TableByPid :: atom()) -> ok.
+rebuild_monitors(Scope, TableByName, TableByPid) ->
     RegistryTuples = get_registry_tuples_for_node(node(), TableByName),
-    do_rebuild_monitors(RegistryTuples, #{}, TableByName, TableByPid).
+    do_rebuild_monitors(RegistryTuples, #{}, Scope, TableByName, TableByPid).
 
 -spec do_rebuild_monitors(
     [syn_registry_tuple()],
     #{pid() => reference()},
+    Scope :: atom(),
     TableByName :: atom(),
     TableByPid :: atom()
 ) -> ok.
-do_rebuild_monitors([], _, _, _) -> ok;
-do_rebuild_monitors([{Name, Pid, Meta, Time} | T], NewMRefs, TableByName, TableByPid) ->
+do_rebuild_monitors([], _, _, _, _) -> ok;
+do_rebuild_monitors([{Name, Pid, Meta, Time} | T], NewMRefs, Scope, TableByName, TableByPid) ->
     remove_from_local_table(Name, Pid, TableByName, TableByPid),
     case is_process_alive(Pid) of
         true ->
@@ -344,15 +345,19 @@ do_rebuild_monitors([{Name, Pid, Meta, Time} | T], NewMRefs, TableByName, TableB
                 error ->
                     MRef = erlang:monitor(process, Pid),
                     add_to_local_table(Name, Pid, Meta, Time, MRef, TableByName, TableByPid),
-                    do_rebuild_monitors(T, maps:put(Pid, MRef, NewMRefs), TableByName, TableByPid);
+                    do_rebuild_monitors(T, maps:put(Pid, MRef, NewMRefs), Scope, TableByName, TableByPid);
 
                 {ok, MRef} ->
                     add_to_local_table(Name, Pid, Meta, Time, MRef, TableByName, TableByPid),
-                    do_rebuild_monitors(T, NewMRefs, TableByName, TableByPid)
+                    do_rebuild_monitors(T, NewMRefs, Scope, TableByName, TableByPid)
             end;
 
         _ ->
-            do_rebuild_monitors(T, NewMRefs, TableByName, TableByPid)
+            %% process died meanwhile, callback locally
+            %% the remote callbacks will have been called when the scope process crash triggered them
+            syn_event_handler:call_event_handler(on_process_unregistered, [Scope, Name, Pid, Meta, undefined]),
+            %% loop
+            do_rebuild_monitors(T, NewMRefs, Scope, TableByName, TableByPid)
     end.
 
 -spec do_register_on_node(

+ 35 - 10
test/syn_pg_SUITE.erl

@@ -1093,7 +1093,7 @@ three_nodes_custom_event_handler_joined_left(Config) ->
 
     %% init
     TestPid = self(),
-    CurrentNode = node(),
+    LocalNode = node(),
 
     %% start process
     Pid = syn_test_suite_helper:start_process(),
@@ -1104,7 +1104,7 @@ three_nodes_custom_event_handler_joined_left(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_joined, CurrentNode, scope_all, "my-group", Pid, <<"meta">>, normal},
+        {on_process_joined, LocalNode, scope_all, "my-group", Pid, <<"meta">>, normal},
         {on_process_joined, SlaveNode1, scope_all, "my-group", Pid, <<"meta">>, normal},
         {on_process_joined, SlaveNode2, scope_all, "my-group", Pid, <<"meta">>, normal}
     ]),
@@ -1115,7 +1115,7 @@ three_nodes_custom_event_handler_joined_left(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_joined, CurrentNode, scope_all, "my-group", Pid2, <<"meta-for-2">>, normal},
+        {on_process_joined, LocalNode, scope_all, "my-group", Pid2, <<"meta-for-2">>, normal},
         {on_process_joined, SlaveNode1, scope_all, "my-group", Pid2, <<"meta-for-2">>, normal},
         {on_process_joined, SlaveNode2, scope_all, "my-group", Pid2, <<"meta-for-2">>, normal}
     ]),
@@ -1126,7 +1126,7 @@ three_nodes_custom_event_handler_joined_left(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_group_process_updated, CurrentNode, scope_all, "my-group", Pid, <<"new-meta-0">>, normal},
+        {on_group_process_updated, LocalNode, scope_all, "my-group", Pid, <<"new-meta-0">>, normal},
         {on_group_process_updated, SlaveNode1, scope_all, "my-group", Pid, <<"new-meta-0">>, normal},
         {on_group_process_updated, SlaveNode2, scope_all, "my-group", Pid, <<"new-meta-0">>, normal}
     ]),
@@ -1137,7 +1137,7 @@ three_nodes_custom_event_handler_joined_left(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_group_process_updated, CurrentNode, scope_all, "my-group", Pid, <<"new-meta">>, normal},
+        {on_group_process_updated, LocalNode, scope_all, "my-group", Pid, <<"new-meta">>, normal},
         {on_group_process_updated, SlaveNode1, scope_all, "my-group", Pid, <<"new-meta">>, normal},
         {on_group_process_updated, SlaveNode2, scope_all, "my-group", Pid, <<"new-meta">>, normal}
     ]),
@@ -1148,7 +1148,7 @@ three_nodes_custom_event_handler_joined_left(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_left, CurrentNode, scope_all, "my-group", Pid, <<"new-meta">>, normal},
+        {on_process_left, LocalNode, scope_all, "my-group", Pid, <<"new-meta">>, normal},
         {on_process_left, SlaveNode1, scope_all, "my-group", Pid, <<"new-meta">>, normal},
         {on_process_left, SlaveNode2, scope_all, "my-group", Pid, <<"new-meta">>, normal}
     ]),
@@ -1159,7 +1159,7 @@ three_nodes_custom_event_handler_joined_left(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_left, CurrentNode, scope_all, "my-group", Pid2, <<"meta-for-2">>, normal},
+        {on_process_left, LocalNode, scope_all, "my-group", Pid2, <<"meta-for-2">>, normal},
         {on_process_left, SlaveNode1, scope_all, "my-group", Pid2, <<"meta-for-2">>, normal},
         {on_process_left, SlaveNode2, scope_all, "my-group", Pid2, <<"meta-for-2">>, normal}
     ]),
@@ -1175,7 +1175,7 @@ three_nodes_custom_event_handler_joined_left(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_joined, CurrentNode, scope_all, remote_on_1, PidRemoteOn1, <<"netsplit">>, normal},
+        {on_process_joined, LocalNode, scope_all, remote_on_1, PidRemoteOn1, <<"netsplit">>, normal},
         {on_process_joined, SlaveNode1, scope_all, remote_on_1, PidRemoteOn1, <<"netsplit">>, normal},
         {on_process_joined, SlaveNode2, scope_all, remote_on_1, PidRemoteOn1, <<"netsplit">>, normal}
     ]),
@@ -1211,7 +1211,7 @@ three_nodes_custom_event_handler_joined_left(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_left, CurrentNode, scope_all, remote_on_1, PidRemoteOn1, <<"netsplit">>, killed},
+        {on_process_left, LocalNode, scope_all, remote_on_1, PidRemoteOn1, <<"netsplit">>, killed},
         {on_process_left, SlaveNode1, scope_all, remote_on_1, PidRemoteOn1, <<"netsplit">>, killed},
         {on_process_left, SlaveNode2, scope_all, remote_on_1, PidRemoteOn1, <<"netsplit">>, killed}
     ]),
@@ -1220,12 +1220,37 @@ three_nodes_custom_event_handler_joined_left(Config) ->
     %% ---> don't call on monitor rebuild
     %% crash the scope process on local
     syn_test_suite_helper:kill_process(syn_pg_scope_all),
+    syn_test_suite_helper:wait_process_name_ready(syn_pg_scope_all),
 
     %% no messages
     syn_test_suite_helper:assert_wait(
         ok,
         fun() -> syn_test_suite_helper:assert_empty_queue(self()) end
-    ).
+    ),
+
+    %% ---> call if process died during the scope process crash
+    TransientPid = syn_test_suite_helper:start_process(),
+    syn:join(scope_all, "transient-group", TransientPid, {recipient, self(), "transient-meta"}),
+
+    %% check callbacks called
+    syn_test_suite_helper:assert_received_messages([
+        {on_process_joined, LocalNode, scope_all, "transient-group", TransientPid, "transient-meta", normal},
+        {on_process_joined, SlaveNode1, scope_all, "transient-group", TransientPid, "transient-meta", normal},
+        {on_process_joined, SlaveNode2, scope_all, "transient-group", TransientPid, "transient-meta", normal}
+    ]),
+    syn_test_suite_helper:assert_empty_queue(self()),
+
+    %% crash the scope process & transient process on local
+    syn_test_suite_helper:kill_process(syn_pg_scope_all),
+    syn_test_suite_helper:kill_process(TransientPid),
+
+    %% check callbacks called
+    syn_test_suite_helper:assert_received_messages([
+        {on_process_left, LocalNode, scope_all, "transient-group", TransientPid, "transient-meta", undefined},
+        {on_process_left, SlaveNode1, scope_all, "transient-group", TransientPid, "transient-meta", {syn_remote_scope_node_down, scope_all, LocalNode}},
+        {on_process_left, SlaveNode2, scope_all, "transient-group", TransientPid, "transient-meta", {syn_remote_scope_node_down, scope_all, LocalNode}}
+    ]),
+    syn_test_suite_helper:assert_empty_queue(self()).
 
 three_nodes_publish(Config) ->
     %% get slaves

+ 54 - 29
test/syn_registry_SUITE.erl

@@ -930,7 +930,7 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
     ok = rpc:call(SlaveNode2, syn, add_node_to_scopes, [[scope_all]]),
 
     %% init
-    CurrentNode = node(),
+    LocalNode = node(),
 
     %% start process
     Pid = syn_test_suite_helper:start_process(),
@@ -941,7 +941,7 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_registered, CurrentNode, scope_all, "proc-handler", Pid, <<"meta">>, normal},
+        {on_process_registered, LocalNode, scope_all, "proc-handler", Pid, <<"meta">>, normal},
         {on_process_registered, SlaveNode1, scope_all, "proc-handler", Pid, <<"meta">>, normal},
         {on_process_registered, SlaveNode2, scope_all, "proc-handler", Pid, <<"meta">>, normal}
     ]),
@@ -952,7 +952,7 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_registered, CurrentNode, scope_all, "proc-handler-2", Pid2, <<"meta-for-2">>, normal},
+        {on_process_registered, LocalNode, scope_all, "proc-handler-2", Pid2, <<"meta-for-2">>, normal},
         {on_process_registered, SlaveNode1, scope_all, "proc-handler-2", Pid2, <<"meta-for-2">>, normal},
         {on_process_registered, SlaveNode2, scope_all, "proc-handler-2", Pid2, <<"meta-for-2">>, normal}
     ]),
@@ -963,7 +963,7 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_registry_process_updated, CurrentNode, scope_all, "proc-handler", Pid, <<"new-meta">>, normal},
+        {on_registry_process_updated, LocalNode, scope_all, "proc-handler", Pid, <<"new-meta">>, normal},
         {on_registry_process_updated, SlaveNode1, scope_all, "proc-handler", Pid, <<"new-meta">>, normal},
         {on_registry_process_updated, SlaveNode2, scope_all, "proc-handler", Pid, <<"new-meta">>, normal}
     ]),
@@ -974,7 +974,7 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_registry_process_updated, CurrentNode, scope_all, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal},
+        {on_registry_process_updated, LocalNode, scope_all, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal},
         {on_registry_process_updated, SlaveNode1, scope_all, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal},
         {on_registry_process_updated, SlaveNode2, scope_all, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal}
     ]),
@@ -985,7 +985,7 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_unregistered, CurrentNode, scope_all, "proc-handler", Pid, <<"new-meta">>, normal},
+        {on_process_unregistered, LocalNode, scope_all, "proc-handler", Pid, <<"new-meta">>, normal},
         {on_process_unregistered, SlaveNode1, scope_all, "proc-handler", Pid, <<"new-meta">>, normal},
         {on_process_unregistered, SlaveNode2, scope_all, "proc-handler", Pid, <<"new-meta">>, normal}
     ]),
@@ -996,7 +996,7 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_unregistered, CurrentNode, scope_all, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal},
+        {on_process_unregistered, LocalNode, scope_all, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal},
         {on_process_unregistered, SlaveNode1, scope_all, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal},
         {on_process_unregistered, SlaveNode2, scope_all, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal}
     ]),
@@ -1012,7 +1012,7 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_registered, CurrentNode, scope_all, remote_on_1, PidRemoteOn1, <<"netsplit">>, normal},
+        {on_process_registered, LocalNode, scope_all, remote_on_1, PidRemoteOn1, <<"netsplit">>, normal},
         {on_process_registered, SlaveNode1, scope_all, remote_on_1, PidRemoteOn1, <<"netsplit">>, normal},
         {on_process_registered, SlaveNode2, scope_all, remote_on_1, PidRemoteOn1, <<"netsplit">>, normal}
     ]),
@@ -1048,7 +1048,7 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_unregistered, CurrentNode, scope_all, remote_on_1, PidRemoteOn1, <<"netsplit">>, killed},
+        {on_process_unregistered, LocalNode, scope_all, remote_on_1, PidRemoteOn1, <<"netsplit">>, killed},
         {on_process_unregistered, SlaveNode1, scope_all, remote_on_1, PidRemoteOn1, <<"netsplit">>, killed},
         {on_process_unregistered, SlaveNode2, scope_all, remote_on_1, PidRemoteOn1, <<"netsplit">>, killed}
     ]),
@@ -1070,9 +1070,9 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_registered, CurrentNode, scope_all, "proc-confict", Pid2RemoteOn1, <<"meta-1">>, normal},
-        {on_process_unregistered, CurrentNode, scope_all, "proc-confict", Pid2RemoteOn1, <<"meta-1">>, normal},
-        {on_process_registered, CurrentNode, scope_all, "proc-confict", Pid2RemoteOn2, <<"meta-2">>, normal},
+        {on_process_registered, LocalNode, scope_all, "proc-confict", Pid2RemoteOn1, <<"meta-1">>, normal},
+        {on_process_unregistered, LocalNode, scope_all, "proc-confict", Pid2RemoteOn1, <<"meta-1">>, normal},
+        {on_process_registered, LocalNode, scope_all, "proc-confict", Pid2RemoteOn2, <<"meta-2">>, normal},
         {on_process_registered, SlaveNode1, scope_all, "proc-confict", Pid2RemoteOn1, <<"meta-1">>, normal},
         {on_process_registered, SlaveNode2, scope_all, "proc-confict", Pid2RemoteOn2, <<"meta-2">>, normal}
     ]),
@@ -1097,7 +1097,7 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
 
     %% check callbacks called
     syn_test_suite_helper:assert_received_messages([
-        {on_process_unregistered, CurrentNode, scope_all, "proc-confict", Pid2RemoteOn2, <<"meta-2">>, killed},
+        {on_process_unregistered, LocalNode, scope_all, "proc-confict", Pid2RemoteOn2, <<"meta-2">>, killed},
         {on_process_unregistered, SlaveNode1, scope_all, "proc-confict", Pid2RemoteOn2, <<"meta-2">>, killed},
         {on_process_unregistered, SlaveNode2, scope_all, "proc-confict", Pid2RemoteOn2, <<"meta-2">>, killed}
     ]),
@@ -1106,12 +1106,37 @@ three_nodes_custom_event_handler_reg_unreg(Config) ->
     %% ---> don't call on monitor rebuild
     %% crash the scope process on local
     syn_test_suite_helper:kill_process(syn_registry_scope_all),
+    syn_test_suite_helper:wait_process_name_ready(syn_registry_scope_all),
 
     %% no messages
     syn_test_suite_helper:assert_wait(
         ok,
         fun() -> syn_test_suite_helper:assert_empty_queue(self()) end
-    ).
+    ),
+
+    %% ---> call if process died during the scope process crash
+    TransientPid = syn_test_suite_helper:start_process(),
+    syn:register(scope_all, "transient-pid", TransientPid, {recipient, self(), "transient-meta"}),
+
+    %% check callbacks called
+    syn_test_suite_helper:assert_received_messages([
+        {on_process_registered, LocalNode, scope_all, "transient-pid", TransientPid, "transient-meta", normal},
+        {on_process_registered, SlaveNode1, scope_all, "transient-pid", TransientPid, "transient-meta", normal},
+        {on_process_registered, SlaveNode2, scope_all, "transient-pid", TransientPid, "transient-meta", normal}
+    ]),
+    syn_test_suite_helper:assert_empty_queue(self()),
+
+    %% crash the scope process & transient process on local
+    syn_test_suite_helper:kill_process(syn_registry_scope_all),
+    syn_test_suite_helper:kill_process(TransientPid),
+
+    %% check callbacks called
+    syn_test_suite_helper:assert_received_messages([
+        {on_process_unregistered, LocalNode, scope_all, "transient-pid", TransientPid, "transient-meta", undefined},
+        {on_process_unregistered, SlaveNode1, scope_all, "transient-pid", TransientPid, "transient-meta", {syn_remote_scope_node_down, scope_all, LocalNode}},
+        {on_process_unregistered, SlaveNode2, scope_all, "transient-pid", TransientPid, "transient-meta", {syn_remote_scope_node_down, scope_all, LocalNode}}
+    ]),
+    syn_test_suite_helper:assert_empty_queue(self()).
 
 three_nodes_custom_event_handler_conflict_resolution(Config) ->
     %% get slaves
@@ -1135,7 +1160,7 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
 
     %% current node
     TestPid = self(),
-    CurrentNode = node(),
+    LocalNode = node(),
 
     %% partial netsplit (1 cannot see 2)
     rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
@@ -1155,9 +1180,9 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
 
     %% check callbacks
     syn_test_suite_helper:assert_received_messages([
-        {on_process_registered, CurrentNode, scope_all, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
-        {on_process_unregistered, CurrentNode, scope_all, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
-        {on_process_registered, CurrentNode, scope_all, "proc-confict-by-netsplit-custom", PidOn2, "meta-2", normal},
+        {on_process_registered, LocalNode, scope_all, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
+        {on_process_unregistered, LocalNode, scope_all, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
+        {on_process_registered, LocalNode, scope_all, "proc-confict-by-netsplit-custom", PidOn2, "meta-2", normal},
 
         {on_process_registered, SlaveNode1, scope_all, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
         {on_process_registered, SlaveNode2, scope_all, "proc-confict-by-netsplit-custom", PidOn2, "meta-2", normal},
@@ -1215,8 +1240,8 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
     0 = rpc:call(SlaveNode2, syn, registry_count, [scope_bc, SlaveNode2]),
 
     syn_test_suite_helper:assert_received_messages([
-        {on_process_unregistered, CurrentNode, scope_all, "proc-confict-by-netsplit-custom", PidOn2, "meta-2", syn_conflict_resolution},
-        {on_process_registered, CurrentNode, scope_all, "proc-confict-by-netsplit-custom", PidOn1, keepthis, syn_conflict_resolution},
+        {on_process_unregistered, LocalNode, scope_all, "proc-confict-by-netsplit-custom", PidOn2, "meta-2", syn_conflict_resolution},
+        {on_process_registered, LocalNode, scope_all, "proc-confict-by-netsplit-custom", PidOn1, keepthis, syn_conflict_resolution},
 
         {on_process_unregistered, SlaveNode2, scope_all, "proc-confict-by-netsplit-custom", PidOn2, "meta-2", syn_conflict_resolution},
         {on_process_registered, SlaveNode2, scope_all, "proc-confict-by-netsplit-custom", PidOn1, keepthis, syn_conflict_resolution},
@@ -1263,7 +1288,7 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
 
     %% check callbacks
     syn_test_suite_helper:assert_received_messages([
-        {on_process_unregistered, CurrentNode, scope_all, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
+        {on_process_unregistered, LocalNode, scope_all, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
         {on_process_unregistered, SlaveNode1, scope_all, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
         {on_process_unregistered, SlaveNode2, scope_all, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
         {on_process_unregistered, SlaveNode1, scope_bc, "proc-confict-by-netsplit-scoped-custom", PidOn1, keepthis, normal},
@@ -1284,9 +1309,9 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
 
     %% check callbacks
     syn_test_suite_helper:assert_received_messages([
-        {on_process_registered, CurrentNode, scope_all, "proc-confict-by-netsplit-custom-other-pid", PidOn1, "meta-1", normal},
-        {on_process_unregistered, CurrentNode, scope_all, "proc-confict-by-netsplit-custom-other-pid", PidOn1, "meta-1", normal},
-        {on_process_registered, CurrentNode, scope_all, "proc-confict-by-netsplit-custom-other-pid", PidOn2, "meta-2", normal},
+        {on_process_registered, LocalNode, scope_all, "proc-confict-by-netsplit-custom-other-pid", PidOn1, "meta-1", normal},
+        {on_process_unregistered, LocalNode, scope_all, "proc-confict-by-netsplit-custom-other-pid", PidOn1, "meta-1", normal},
+        {on_process_registered, LocalNode, scope_all, "proc-confict-by-netsplit-custom-other-pid", PidOn2, "meta-2", normal},
 
         {on_process_registered, SlaveNode1, scope_all, "proc-confict-by-netsplit-custom-other-pid", PidOn1, "meta-1", normal},
         {on_process_registered, SlaveNode2, scope_all, "proc-confict-by-netsplit-custom-other-pid", PidOn2, "meta-2", normal}
@@ -1327,7 +1352,7 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
 
     %% check callbacks
     syn_test_suite_helper:assert_received_messages([
-        {on_process_unregistered, CurrentNode, scope_all, "proc-confict-by-netsplit-custom-other-pid", PidOn2, "meta-2", syn_conflict_resolution},
+        {on_process_unregistered, LocalNode, scope_all, "proc-confict-by-netsplit-custom-other-pid", PidOn2, "meta-2", syn_conflict_resolution},
         {on_process_unregistered, SlaveNode1, scope_all, "proc-confict-by-netsplit-custom-other-pid", PidOn1, "meta-1", syn_conflict_resolution},
         {on_process_unregistered, SlaveNode2, scope_all, "proc-confict-by-netsplit-custom-other-pid", PidOn2, "meta-2", syn_conflict_resolution}
     ]),
@@ -1357,9 +1382,9 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
 
     %% check callbacks
     syn_test_suite_helper:assert_received_messages([
-        {on_process_registered, CurrentNode, scope_all, "proc-confict-by-netsplit-custom-crash", PidOn1, crash, normal},
-        {on_process_unregistered, CurrentNode, scope_all, "proc-confict-by-netsplit-custom-crash", PidOn1, crash, normal},
-        {on_process_registered, CurrentNode, scope_all, "proc-confict-by-netsplit-custom-crash", PidOn2, crash, normal},
+        {on_process_registered, LocalNode, scope_all, "proc-confict-by-netsplit-custom-crash", PidOn1, crash, normal},
+        {on_process_unregistered, LocalNode, scope_all, "proc-confict-by-netsplit-custom-crash", PidOn1, crash, normal},
+        {on_process_registered, LocalNode, scope_all, "proc-confict-by-netsplit-custom-crash", PidOn2, crash, normal},
 
         {on_process_registered, SlaveNode1, scope_all, "proc-confict-by-netsplit-custom-crash", PidOn1, crash, normal},
         {on_process_registered, SlaveNode2, scope_all, "proc-confict-by-netsplit-custom-crash", PidOn2, crash, normal}
@@ -1400,7 +1425,7 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
 
     %% check callbacks
     syn_test_suite_helper:assert_received_messages([
-        {on_process_unregistered, CurrentNode, scope_all, "proc-confict-by-netsplit-custom-crash", PidOn2, crash, syn_conflict_resolution},
+        {on_process_unregistered, LocalNode, scope_all, "proc-confict-by-netsplit-custom-crash", PidOn2, crash, syn_conflict_resolution},
         {on_process_unregistered, SlaveNode1, scope_all, "proc-confict-by-netsplit-custom-crash", PidOn1, crash, syn_conflict_resolution},
         {on_process_unregistered, SlaveNode2, scope_all, "proc-confict-by-netsplit-custom-crash", PidOn2, crash, syn_conflict_resolution}
     ]),