Browse Source

Add get_local_members.

Roberto Ostinelli 3 years ago
parent
commit
9e01f98a0c
3 changed files with 352 additions and 4 deletions
  1. 9 0
      src/syn.erl
  2. 14 1
      src/syn_groups.erl
  3. 329 3
      test/syn_groups_SUITE.erl

+ 9 - 0
src/syn.erl

@@ -39,6 +39,7 @@
 -export([register_name/2, unregister_name/1, whereis_name/1, send/2]).
 %% groups
 -export([get_members/1, get_members/2]).
+-export([get_local_members/1, get_local_members/2]).
 -export([join/2, join/3, join/4]).
 -export([leave/2, leave/3]).
 -export([groups_count/1, groups_count/2]).
@@ -152,6 +153,14 @@ get_members(GroupName) ->
 get_members(Scope, GroupName) ->
     syn_groups:get_members(Scope, GroupName).
 
+-spec get_local_members(GroupName :: term()) -> [{Pid :: pid(), Meta :: term()}].
+get_local_members(GroupName) ->
+    syn_groups:get_local_members(GroupName).
+
+-spec get_local_members(Scope :: atom(), GroupName :: term()) -> [{Pid :: pid(), Meta :: term()}].
+get_local_members(Scope, GroupName) ->
+    syn_groups:get_local_members(Scope, GroupName).
+
 -spec join(GroupName :: any(), Pid :: pid()) -> ok | {error, Reason :: any()}.
 join(GroupName, Pid) ->
     syn_groups:join(GroupName, Pid).

+ 14 - 1
src/syn_groups.erl

@@ -32,6 +32,7 @@
 -export([join/2, join/3, join/4]).
 -export([leave/2, leave/3]).
 -export([get_members/1, get_members/2]).
+-export([get_local_members/1, get_local_members/2]).
 -export([count/1, count/2]).
 
 %% syn_gen_scope callbacks
@@ -65,13 +66,25 @@ get_members(GroupName) ->
 
 -spec get_members(Scope :: atom(), GroupName :: term()) -> [{Pid :: pid(), Meta :: term()}].
 get_members(Scope, GroupName) ->
+    do_get_members(Scope, GroupName, '_').
+
+-spec get_local_members(GroupName :: term()) -> [{Pid :: pid(), Meta :: term()}].
+get_local_members(GroupName) ->
+    get_local_members(default, GroupName).
+
+-spec get_local_members(Scope :: atom(), GroupName :: term()) -> [{Pid :: pid(), Meta :: term()}].
+get_local_members(Scope, GroupName) ->
+    do_get_members(Scope, GroupName, node()).
+
+-spec do_get_members(Scope :: atom(), GroupName :: term(), NodeParam :: atom()) -> [{Pid :: pid(), Meta :: term()}].
+do_get_members(Scope, GroupName, NodeParam) ->
     case syn_backbone:get_table_name(syn_groups_by_name, Scope) of
         undefined ->
             error({invalid_scope, Scope});
 
         TableByName ->
             ets:select(TableByName, [{
-                {{GroupName, '$2'}, '$3', '_', '_', '_'},
+                {{GroupName, '$2'}, '$3', '_', '_', NodeParam},
                 [],
                 [{{'$2', '$3'}}]
             }])

+ 329 - 3
test/syn_groups_SUITE.erl

@@ -368,6 +368,14 @@ three_nodes_join_leave_and_monitor_default_scope(Config) ->
     [] = syn:get_members({group, "two"}),
     [] = rpc:call(SlaveNode1, syn, get_members, [{group, "two"}]),
     [] = rpc:call(SlaveNode2, syn, get_members, [{group, "two"}]),
+
+    [] = syn:get_local_members({group, "one"}),
+    [] = rpc:call(SlaveNode1, syn, get_local_members, [{group, "one"}]),
+    [] = rpc:call(SlaveNode2, syn, get_local_members, [{group, "one"}]),
+    [] = syn:get_local_members({group, "two"}),
+    [] = rpc:call(SlaveNode1, syn, get_local_members, [{group, "two"}]),
+    [] = rpc:call(SlaveNode2, syn, get_local_members, [{group, "two"}]),
+
     0 = syn:groups_count(default),
     0 = syn:groups_count(default, node()),
     0 = syn:groups_count(default, SlaveNode1),
@@ -397,6 +405,20 @@ three_nodes_join_leave_and_monitor_default_scope(Config) ->
         lists:sort([{Pid, undefined}, {PidWithMeta, <<"with meta">>}, {PidRemoteOn1, undefined}]),
         fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [{group, "one"}])) end
     ),
+
+    syn_test_suite_helper:assert_wait(
+        lists:sort([{Pid, undefined}, {PidWithMeta, <<"with meta">>}]),
+        fun() -> lists:sort(syn:get_local_members({group, "one"})) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [{PidRemoteOn1, undefined}],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [{group, "one"}])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [{group, "one"}])) end
+    ),
+
     syn_test_suite_helper:assert_wait(
         lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
         fun() -> lists:sort(syn:get_members({group, "two"})) end
@@ -409,6 +431,20 @@ three_nodes_join_leave_and_monitor_default_scope(Config) ->
         lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
         fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [{group, "two"}])) end
     ),
+
+    syn_test_suite_helper:assert_wait(
+        lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
+        fun() -> lists:sort(syn:get_local_members({group, "two"})) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [{group, "two"}])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [{group, "two"}])) end
+    ),
+
     2 = syn:groups_count(default),
     2 = syn:groups_count(default, node()),
     1 = syn:groups_count(default, SlaveNode1),
@@ -431,6 +467,20 @@ three_nodes_join_leave_and_monitor_default_scope(Config) ->
         lists:sort([{Pid, undefined}, {PidWithMeta, <<"with updated meta">>}, {PidRemoteOn1, added_meta}]),
         fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [{group, "one"}])) end
     ),
+
+    syn_test_suite_helper:assert_wait(
+        lists:sort([{Pid, undefined}, {PidWithMeta, <<"with updated meta">>}]),
+        fun() -> lists:sort(syn:get_local_members({group, "one"})) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [{PidRemoteOn1, added_meta}],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [{group, "one"}])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [{group, "one"}])) end
+    ),
+
     syn_test_suite_helper:assert_wait(
         lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
         fun() -> lists:sort(syn:get_members({group, "two"})) end
@@ -443,6 +493,20 @@ three_nodes_join_leave_and_monitor_default_scope(Config) ->
         lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
         fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [{group, "two"}])) end
     ),
+
+    syn_test_suite_helper:assert_wait(
+        lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
+        fun() -> lists:sort(syn:get_local_members({group, "two"})) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [{group, "two"}])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [{group, "two"}])) end
+    ),
+
     2 = syn:groups_count(default),
     2 = syn:groups_count(default, node()),
     1 = syn:groups_count(default, SlaveNode1),
@@ -471,6 +535,20 @@ three_nodes_join_leave_and_monitor_default_scope(Config) ->
         [],
         fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [{group, "one"}])) end
     ),
+
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(syn:get_local_members({group, "one"})) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [{group, "one"}])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [{group, "one"}])) end
+    ),
+
     syn_test_suite_helper:assert_wait(
         [{PidWithMeta, "with-meta-2"}],
         fun() -> lists:sort(syn:get_members({group, "two"})) end
@@ -483,6 +561,20 @@ three_nodes_join_leave_and_monitor_default_scope(Config) ->
         [{PidWithMeta, "with-meta-2"}],
         fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [{group, "two"}])) end
     ),
+
+    syn_test_suite_helper:assert_wait(
+        [{PidWithMeta, "with-meta-2"}],
+        fun() -> lists:sort(syn:get_local_members({group, "two"})) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [{group, "two"}])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [{group, "two"}])) end
+    ),
+
     1 = syn:groups_count(default),
     1 = syn:groups_count(default, node()),
     0 = syn:groups_count(default, SlaveNode1),
@@ -516,16 +608,35 @@ three_nodes_join_leave_and_monitor_custom_scope(Config) ->
     [] = syn:get_members(custom_scope_ab, {group, "one"}),
     [] = rpc:call(SlaveNode1, syn, get_members, [custom_scope_ab, {group, "one"}]),
     {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_members, [custom_scope_ab, {group, "one"}]),
+
+    [] = syn:get_local_members(custom_scope_ab, {group, "one"}),
+    [] = rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_ab, {group, "one"}]),
+    {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_ab, {group, "one"}]),
+
     {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_members(custom_scope_bc, {group, "one"}),
     [] = rpc:call(SlaveNode1, syn, get_members, [custom_scope_bc, {group, "one"}]),
     [] = rpc:call(SlaveNode2, syn, get_members, [custom_scope_bc, {group, "one"}]),
+
+    {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_local_members(custom_scope_bc, {group, "one"}),
+    [] = rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_bc, {group, "one"}]),
+    [] = rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_bc, {group, "one"}]),
+
     [] = syn:get_members(custom_scope_ab, {group, "two"}),
     [] = rpc:call(SlaveNode1, syn, get_members, [custom_scope_ab, {group, "two"}]),
     {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_members, [custom_scope_ab, {group, "two"}]),
+
+    [] = syn:get_local_members(custom_scope_ab, {group, "two"}),
+    [] = rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_ab, {group, "two"}]),
+    {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_ab, {group, "two"}]),
+
     {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_members(custom_scope_bc, {group, "two"}),
     [] = rpc:call(SlaveNode1, syn, get_members, [custom_scope_bc, {group, "two"}]),
     [] = rpc:call(SlaveNode2, syn, get_members, [custom_scope_bc, {group, "two"}]),
 
+    {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_local_members(custom_scope_bc, {group, "two"}),
+    [] = rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_bc, {group, "two"}]),
+    [] = rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_bc, {group, "two"}]),
+
     %% join
     ok = syn:join(custom_scope_ab, {group, "one"}, Pid),
     ok = syn:join(custom_scope_ab, {group, "one"}, PidWithMeta, <<"with meta">>),
@@ -548,6 +659,17 @@ three_nodes_join_leave_and_monitor_custom_scope(Config) ->
         fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_ab, {group, "one"}])) end
     ),
     {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_members, [custom_scope_ab, {group, "one"}]),
+
+    syn_test_suite_helper:assert_wait(
+        lists:sort([{Pid, undefined}, {PidWithMeta, <<"with meta">>}]),
+        fun() -> lists:sort(syn:get_local_members(custom_scope_ab, {group, "one"})) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_ab, {group, "one"}])) end
+    ),
+    {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_ab, {group, "one"}]),
+
     syn_test_suite_helper:assert_wait(
         lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
         fun() -> lists:sort(syn:get_members(custom_scope_ab, {group, "two"})) end
@@ -557,6 +679,17 @@ three_nodes_join_leave_and_monitor_custom_scope(Config) ->
         fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_ab, {group, "two"}])) end
     ),
     {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_members, [custom_scope_ab, {group, "two"}]),
+
+    syn_test_suite_helper:assert_wait(
+        lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
+        fun() -> lists:sort(syn:get_local_members(custom_scope_ab, {group, "two"})) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_ab, {group, "two"}])) end
+    ),
+    {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_ab, {group, "two"}]),
+
     {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_members(custom_scope_bc, {group, "two"}),
     syn_test_suite_helper:assert_wait(
         [{PidRemoteOn1, undefined}],
@@ -566,6 +699,17 @@ three_nodes_join_leave_and_monitor_custom_scope(Config) ->
         [{PidRemoteOn1, undefined}],
         fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [custom_scope_bc, {group, "two"}])) end
     ),
+
+    {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_local_members(custom_scope_bc, {group, "two"}),
+    syn_test_suite_helper:assert_wait(
+        [{PidRemoteOn1, undefined}],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_bc, {group, "two"}])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_bc, {group, "two"}])) end
+    ),
+
     2 = syn:groups_count(custom_scope_ab),
     2 = syn:groups_count(custom_scope_ab, node()),
     0 = syn:groups_count(custom_scope_ab, SlaveNode1),
@@ -605,6 +749,17 @@ three_nodes_join_leave_and_monitor_custom_scope(Config) ->
         fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_ab, {group, "one"}])) end
     ),
     {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_members, [custom_scope_ab, {group, "one"}]),
+
+    syn_test_suite_helper:assert_wait(
+        lists:sort([{Pid, undefined}, {PidWithMeta, <<"with updated meta">>}]),
+        fun() -> lists:sort(syn:get_local_members(custom_scope_ab, {group, "one"})) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_ab, {group, "one"}])) end
+    ),
+    {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_ab, {group, "one"}]),
+
     syn_test_suite_helper:assert_wait(
         lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
         fun() -> lists:sort(syn:get_members(custom_scope_ab, {group, "two"})) end
@@ -614,6 +769,17 @@ three_nodes_join_leave_and_monitor_custom_scope(Config) ->
         fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_ab, {group, "two"}])) end
     ),
     {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_members, [custom_scope_ab, {group, "two"}]),
+
+    syn_test_suite_helper:assert_wait(
+        lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
+        fun() -> lists:sort(syn:get_local_members(custom_scope_ab, {group, "two"})) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_ab, {group, "two"}])) end
+    ),
+    {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_ab, {group, "two"}]),
+
     {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_members(custom_scope_bc, {group, "two"}),
     syn_test_suite_helper:assert_wait(
         [{PidRemoteOn1, added_meta}],
@@ -623,6 +789,17 @@ three_nodes_join_leave_and_monitor_custom_scope(Config) ->
         [{PidRemoteOn1, added_meta}],
         fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [custom_scope_bc, {group, "two"}])) end
     ),
+
+    {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_local_members(custom_scope_bc, {group, "two"}),
+    syn_test_suite_helper:assert_wait(
+        [{PidRemoteOn1, added_meta}],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_bc, {group, "two"}])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_bc, {group, "two"}])) end
+    ),
+
     2 = syn:groups_count(custom_scope_ab),
     2 = syn:groups_count(custom_scope_ab, node()),
     0 = syn:groups_count(custom_scope_ab, SlaveNode1),
@@ -668,6 +845,17 @@ three_nodes_join_leave_and_monitor_custom_scope(Config) ->
         fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_ab, {group, "one"}])) end
     ),
     {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_members, [custom_scope_ab, {group, "one"}]),
+
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(syn:get_local_members(custom_scope_ab, {group, "one"})) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_ab, {group, "one"}])) end
+    ),
+    {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_ab, {group, "one"}]),
+
     syn_test_suite_helper:assert_wait(
         [{PidWithMeta, "with-meta-2"}],
         fun() -> lists:sort(syn:get_members(custom_scope_ab, {group, "two"})) end
@@ -677,6 +865,17 @@ three_nodes_join_leave_and_monitor_custom_scope(Config) ->
         fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_ab, {group, "two"}])) end
     ),
     {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_members, [custom_scope_ab, {group, "two"}]),
+
+    syn_test_suite_helper:assert_wait(
+        [{PidWithMeta, "with-meta-2"}],
+        fun() -> lists:sort(syn:get_local_members(custom_scope_ab, {group, "two"})) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_ab, {group, "two"}])) end
+    ),
+    {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_ab, {group, "two"}]),
+
     {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_members(custom_scope_bc, {group, "two"}),
     syn_test_suite_helper:assert_wait(
         [],
@@ -685,6 +884,16 @@ three_nodes_join_leave_and_monitor_custom_scope(Config) ->
     syn_test_suite_helper:assert_wait(
         [], fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [custom_scope_bc, {group, "two"}])) end
     ),
+
+    {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_local_members(custom_scope_bc, {group, "two"}),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_bc, {group, "two"}])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [], fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_bc, {group, "two"}])) end
+    ),
+
     1 = syn:groups_count(custom_scope_ab),
     1 = syn:groups_count(custom_scope_ab, node()),
     0 = syn:groups_count(custom_scope_ab, SlaveNode1),
@@ -764,6 +973,20 @@ three_nodes_cluster_changes(Config) ->
         lists:sort([{PidRemoteOn1, "meta-1"}, {PidRemoteOn2, "meta-2"}]),
         fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [<<"common-group">>])) end
     ),
+
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(syn:get_local_members(<<"common-group">>)) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [{PidRemoteOn1, "meta-1"}],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [<<"common-group">>])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [{PidRemoteOn2, "meta-2"}],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [<<"common-group">>])) end
+    ),
+
     syn_test_suite_helper:assert_wait(
         [{PidRemoteOn2, "other-meta"}],
         fun() -> lists:sort(syn:get_members(<<"group-2">>)) end
@@ -776,6 +999,20 @@ three_nodes_cluster_changes(Config) ->
         [{PidRemoteOn2, "other-meta"}],
         fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [<<"group-2">>])) end
     ),
+
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(syn:get_local_members(<<"group-2">>)) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [<<"group-2">>])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [{PidRemoteOn2, "other-meta"}],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [<<"group-2">>])) end
+    ),
+
     2 = syn:groups_count(default),
     0 = syn:groups_count(default, node()),
     1 = syn:groups_count(default, SlaveNode1),
@@ -789,7 +1026,7 @@ three_nodes_cluster_changes(Config) ->
     1 = rpc:call(SlaveNode2, syn, groups_count, [default, SlaveNode1]),
     2 = rpc:call(SlaveNode2, syn, groups_count, [default, SlaveNode2]),
 
-    {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc),
+    {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_members(custom_scope_bc, <<"scoped-on-bc">>),
     syn_test_suite_helper:assert_wait(
         lists:sort([{PidRemoteOn1, "scoped-meta-1"}, {PidRemoteOn2, "scoped-meta-2"}]),
         fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
@@ -798,6 +1035,17 @@ three_nodes_cluster_changes(Config) ->
         lists:sort([{PidRemoteOn1, "scoped-meta-1"}, {PidRemoteOn2, "scoped-meta-2"}]),
         fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
     ),
+
+    {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_local_members(custom_scope_bc, <<"scoped-on-bc">>),
+    syn_test_suite_helper:assert_wait(
+        [{PidRemoteOn1, "scoped-meta-1"}],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [{PidRemoteOn2, "scoped-meta-2"}],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
+    ),
+
     {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc),
     {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, node()),
     {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, SlaveNode1),
@@ -830,6 +1078,20 @@ three_nodes_cluster_changes(Config) ->
         [{PidRemoteOn2, "meta-2"}],
         fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [<<"common-group">>])) end
     ),
+
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(syn:get_local_members(<<"common-group">>)) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [{PidRemoteOn1, "meta-1"}],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [<<"common-group">>])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [{PidRemoteOn2, "meta-2"}],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [<<"common-group">>])) end
+    ),
+
     syn_test_suite_helper:assert_wait(
         [{PidRemoteOn2, "other-meta"}],
         fun() -> lists:sort(syn:get_members(<<"group-2">>)) end
@@ -842,6 +1104,20 @@ three_nodes_cluster_changes(Config) ->
         [{PidRemoteOn2, "other-meta"}],
         fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [<<"group-2">>])) end
     ),
+
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(syn:get_local_members(<<"group-2">>)) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [<<"group-2">>])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [{PidRemoteOn2, "other-meta"}],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [<<"group-2">>])) end
+    ),
+
     2 = syn:groups_count(default),
     0 = syn:groups_count(default, node()),
     1 = syn:groups_count(default, SlaveNode1),
@@ -855,7 +1131,7 @@ three_nodes_cluster_changes(Config) ->
     0 = rpc:call(SlaveNode2, syn, groups_count, [default, SlaveNode1]),
     2 = rpc:call(SlaveNode2, syn, groups_count, [default, SlaveNode2]),
 
-    {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc),
+    {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_members(custom_scope_bc, <<"scoped-on-bc">>),
     syn_test_suite_helper:assert_wait(
         [{PidRemoteOn1, "scoped-meta-1"}],
         fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
@@ -864,6 +1140,17 @@ three_nodes_cluster_changes(Config) ->
         [{PidRemoteOn2, "scoped-meta-2"}],
         fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
     ),
+
+    {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_local_members(custom_scope_bc, <<"scoped-on-bc">>),
+    syn_test_suite_helper:assert_wait(
+        [{PidRemoteOn1, "scoped-meta-1"}],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [{PidRemoteOn2, "scoped-meta-2"}],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
+    ),
+
     {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc),
     {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, node()),
     {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, SlaveNode1),
@@ -896,6 +1183,20 @@ three_nodes_cluster_changes(Config) ->
         lists:sort([{PidRemoteOn1, "meta-1"}, {PidRemoteOn2, "meta-2"}]),
         fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [<<"common-group">>])) end
     ),
+
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(syn:get_local_members(<<"common-group">>)) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [{PidRemoteOn1, "meta-1"}],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [<<"common-group">>])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [{PidRemoteOn2, "meta-2"}],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [<<"common-group">>])) end
+    ),
+
     syn_test_suite_helper:assert_wait(
         [{PidRemoteOn2, "other-meta"}],
         fun() -> lists:sort(syn:get_members(<<"group-2">>)) end
@@ -908,6 +1209,20 @@ three_nodes_cluster_changes(Config) ->
         [{PidRemoteOn2, "other-meta"}],
         fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [<<"group-2">>])) end
     ),
+
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(syn:get_local_members(<<"group-2">>)) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [<<"group-2">>])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [{PidRemoteOn2, "other-meta"}],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [<<"group-2">>])) end
+    ),
+
     2 = syn:groups_count(default),
     0 = syn:groups_count(default, node()),
     1 = syn:groups_count(default, SlaveNode1),
@@ -921,7 +1236,7 @@ three_nodes_cluster_changes(Config) ->
     1 = rpc:call(SlaveNode2, syn, groups_count, [default, SlaveNode1]),
     2 = rpc:call(SlaveNode2, syn, groups_count, [default, SlaveNode2]),
 
-    {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc),
+    {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_members(custom_scope_bc, <<"scoped-on-bc">>),
     syn_test_suite_helper:assert_wait(
         lists:sort([{PidRemoteOn1, "scoped-meta-1"}, {PidRemoteOn2, "scoped-meta-2"}]),
         fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
@@ -930,6 +1245,17 @@ three_nodes_cluster_changes(Config) ->
         lists:sort([{PidRemoteOn1, "scoped-meta-1"}, {PidRemoteOn2, "scoped-meta-2"}]),
         fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
     ),
+
+    {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_local_members(custom_scope_bc, <<"scoped-on-bc">>),
+    syn_test_suite_helper:assert_wait(
+        [{PidRemoteOn1, "scoped-meta-1"}],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [{PidRemoteOn2, "scoped-meta-2"}],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
+    ),
+
     {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc),
     {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, node()),
     {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, SlaveNode1),