Browse Source

Add group names.

Roberto Ostinelli 3 years ago
parent
commit
b94060955e
3 changed files with 416 additions and 2 deletions
  1. 22 0
      src/syn.erl
  2. 38 0
      src/syn_groups.erl
  3. 356 2
      test/syn_groups_SUITE.erl

+ 22 - 0
src/syn.erl

@@ -45,6 +45,8 @@
 -export([join/2, join/3, join/4]).
 -export([leave/2, leave/3]).
 -export([groups_count/1, groups_count/2]).
+-export([group_names/0, group_names/1, group_names/2]).
+-export([local_group_names/0, local_group_names/1]).
 -export([publish/2, publish/3]).
 -export([local_publish/2, local_publish/3]).
 -export([multi_call/2, multi_call/3, multi_call/4, multi_call_reply/2]).
@@ -210,6 +212,26 @@ groups_count(Scope) ->
 groups_count(Scope, Node) ->
     syn_groups:count(Scope, Node).
 
+-spec group_names() -> [GroupName :: term()].
+group_names() ->
+    syn_groups:group_names().
+
+-spec group_names(Scope :: atom()) -> [GroupName :: term()].
+group_names(Scope) ->
+    syn_groups:group_names(Scope).
+
+-spec group_names(Scope :: atom(), Node :: node()) -> [GroupName :: term()].
+group_names(Scope, Node) ->
+    syn_groups:group_names(Scope, Node).
+
+-spec local_group_names() -> [GroupName :: term()].
+local_group_names() ->
+    syn_groups:local_group_names().
+
+-spec local_group_names(Scope :: atom()) -> [GroupName :: term()].
+local_group_names(Scope) ->
+    syn_groups:local_group_names(Scope).
+
 -spec publish(GroupName :: any(), Message :: any()) -> {ok, RecipientCount :: non_neg_integer()}.
 publish(GroupName, Message) ->
     syn_groups:publish(GroupName, Message).

+ 38 - 0
src/syn_groups.erl

@@ -36,6 +36,8 @@
 -export([local_members/1, local_members/2]).
 -export([is_local_member/2, is_local_member/3]).
 -export([count/1, count/2]).
+-export([group_names/0, group_names/1, group_names/2]).
+-export([local_group_names/0, local_group_names/1]).
 -export([publish/2, publish/3]).
 -export([local_publish/2, local_publish/3]).
 -export([multi_call/2, multi_call/3, multi_call/4, multi_call_reply/2]).
@@ -212,6 +214,42 @@ do_count(Scope, NodeParam) ->
             ordsets:size(Set)
     end.
 
+-spec group_names() -> [GroupName :: term()].
+group_names() ->
+    group_names(?DEFAULT_SCOPE).
+
+-spec group_names(Scope :: atom()) -> [GroupName :: term()].
+group_names(Scope) ->
+    do_group_names(Scope, '_').
+
+-spec group_names(Scope :: atom(), Node :: node()) -> [GroupName :: term()].
+group_names(Scope, Node) ->
+    do_group_names(Scope, Node).
+
+-spec do_group_names(Scope :: atom(), Node :: node()) -> [GroupName :: term()].
+do_group_names(Scope, NodeParam) ->
+    case syn_backbone:get_table_name(syn_groups_by_name, Scope) of
+        undefined ->
+            error({invalid_scope, Scope});
+
+        TableByName ->
+            Groups = ets:select(TableByName, [{
+                {{'$1', '_'}, '_', '_', '_', NodeParam},
+                [],
+                ['$1']
+            }]),
+            Set = ordsets:from_list(Groups),
+            ordsets:to_list(Set)
+    end.
+
+-spec local_group_names() -> [GroupName :: term()].
+local_group_names() ->
+    group_names(?DEFAULT_SCOPE, node()).
+
+-spec local_group_names(Scope :: atom()) -> [GroupName :: term()].
+local_group_names(Scope) ->
+    group_names(Scope, node()).
+
 -spec publish(GroupName :: any(), Message :: any()) -> {ok, RecipientCount :: non_neg_integer()}.
 publish(GroupName, Message) ->
     publish(?DEFAULT_SCOPE, GroupName, Message).

+ 356 - 2
test/syn_groups_SUITE.erl

@@ -42,7 +42,9 @@
     three_nodes_publish_default_scope/1,
     three_nodes_publish_custom_scope/1,
     three_nodes_multi_call_default_scope/1,
-    three_nodes_multi_call_custom_scope/1
+    three_nodes_multi_call_custom_scope/1,
+    three_nodes_group_names_default_scope/1,
+    three_nodes_group_names_custom_scope/1
 ]).
 
 %% internals
@@ -95,7 +97,9 @@ groups() ->
             three_nodes_publish_default_scope,
             three_nodes_publish_custom_scope,
             three_nodes_multi_call_default_scope,
-            three_nodes_multi_call_custom_scope
+            three_nodes_multi_call_custom_scope,
+            three_nodes_group_names_default_scope,
+            three_nodes_group_names_custom_scope
         ]}
     ].
 %% -------------------------------------------------------------------
@@ -1839,6 +1843,356 @@ three_nodes_multi_call_custom_scope(Config) ->
     ]),
     BadRepliesBC = [].
 
+three_nodes_group_names_default_scope(Config) ->
+    %% get slaves
+    SlaveNode1 = proplists:get_value(slave_node_1, Config),
+    SlaveNode2 = proplists:get_value(slave_node_2, Config),
+
+    %% start syn on nodes
+    ok = syn:start(),
+    ok = rpc:call(SlaveNode1, syn, start, []),
+    ok = rpc:call(SlaveNode2, syn, start, []),
+
+    %% start processes
+    Pid = syn_test_suite_helper:start_process(),
+    Pid2 = syn_test_suite_helper:start_process(),
+    PidRemoteOn1 = syn_test_suite_helper:start_process(SlaveNode1),
+    PidRemoteOn2 = syn_test_suite_helper:start_process(SlaveNode2),
+
+    %% join
+    ok = syn:join(<<"subscribers">>, Pid),
+    ok = syn:join(<<"subscribers">>, Pid2),
+    ok = syn:join(<<"subscribers-2">>, Pid),
+    ok = syn:join(<<"subscribers-2">>, PidRemoteOn1),
+    ok = syn:join(<<"subscribers-2">>, PidRemoteOn2),
+    ok = syn:join(<<"subscribers-3">>, PidRemoteOn1),
+
+    %% retrieve
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-2">>, <<"subscribers-3">>]),
+        fun() -> lists:sort(syn:group_names()) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-2">>]),
+        fun() -> lists:sort(syn:group_names(default, node())) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers-2">>, <<"subscribers-3">>]),
+        fun() -> lists:sort(syn:group_names(default, SlaveNode1)) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers-2">>],
+        fun() -> lists:sort(syn:group_names(default, SlaveNode2)) end
+    ),
+
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-2">>, <<"subscribers-3">>]),
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-2">>]),
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [default, node()])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers-2">>, <<"subscribers-3">>]),
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [default, SlaveNode1])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers-2">>],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [default, SlaveNode2])) end
+    ),
+
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-2">>, <<"subscribers-3">>]),
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-2">>]),
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [default, node()])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers-2">>, <<"subscribers-3">>]),
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [default, SlaveNode1])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers-2">>],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [default, SlaveNode2])) end
+    ),
+
+    %% leave
+    ok = syn:leave(<<"subscribers-2">>, Pid),
+    ok = syn:leave(<<"subscribers-2">>, PidRemoteOn1),
+    ok = syn:leave(<<"subscribers-2">>, PidRemoteOn2),
+
+    %% retrieve
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-3">>]),
+        fun() -> lists:sort(syn:group_names()) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers">>],
+        fun() -> lists:sort(syn:group_names(default, node())) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers-3">>],
+        fun() -> lists:sort(syn:group_names(default, SlaveNode1)) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(syn:group_names(default, SlaveNode2)) end
+    ),
+
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-3">>]),
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers">>],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [default, node()])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers-3">>],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [default, SlaveNode1])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [default, SlaveNode2])) end
+    ),
+
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-3">>]),
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers">>],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [default, node()])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers-3">>],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [default, SlaveNode1])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [default, SlaveNode2])) end
+    ),
+
+    %% 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]),
+    syn_test_suite_helper:assert_cluster(SlaveNode1, [node()]),
+    syn_test_suite_helper:assert_cluster(SlaveNode2, [node()]),
+
+    %% retrieve
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-3">>]),
+        fun() -> lists:sort(syn:group_names()) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers">>],
+        fun() -> lists:sort(syn:group_names(default, node())) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers-3">>],
+        fun() -> lists:sort(syn:group_names(default, SlaveNode1)) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(syn:group_names(default, SlaveNode2)) end
+    ),
+
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-3">>]),
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers">>],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [default, node()])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers-3">>],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [default, SlaveNode1])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [default, SlaveNode2])) end
+    ),
+
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers">>],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers">>],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [default, node()])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [default, SlaveNode1])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [default, SlaveNode2])) end
+    ),
+
+    %% re-join
+    rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
+    syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
+    syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
+    syn_test_suite_helper:assert_cluster(SlaveNode2, [node(), SlaveNode1]),
+
+    %% retrieve
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-3">>]),
+        fun() -> lists:sort(syn:group_names()) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers">>],
+        fun() -> lists:sort(syn:group_names(default, node())) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers-3">>],
+        fun() -> lists:sort(syn:group_names(default, SlaveNode1)) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(syn:group_names(default, SlaveNode2)) end
+    ),
+
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-3">>]),
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers">>],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [default, node()])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers-3">>],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [default, SlaveNode1])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [default, SlaveNode2])) end
+    ),
+
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-3">>]),
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers">>],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [default, node()])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers-3">>],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [default, SlaveNode1])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [default, SlaveNode2])) end
+    ).
+
+three_nodes_group_names_custom_scope(Config) ->
+    %% get slaves
+    SlaveNode1 = proplists:get_value(slave_node_1, Config),
+    SlaveNode2 = proplists:get_value(slave_node_2, Config),
+
+    %% start syn on nodes
+    ok = syn:start(),
+    ok = rpc:call(SlaveNode1, syn, start, []),
+    ok = rpc:call(SlaveNode2, syn, start, []),
+
+    %% add custom scopes
+    ok = syn:add_node_to_scope(custom_scope_ab),
+    ok = rpc:call(SlaveNode1, syn, add_node_to_scopes, [[custom_scope_ab, custom_scope_bc]]),
+    ok = rpc:call(SlaveNode2, syn, add_node_to_scopes, [[custom_scope_bc]]),
+
+    %% start processes
+    Pid = syn_test_suite_helper:start_process(),
+    Pid2 = syn_test_suite_helper:start_process(),
+    PidRemoteOn1 = syn_test_suite_helper:start_process(SlaveNode1),
+    PidRemoteOn2 = syn_test_suite_helper:start_process(SlaveNode2),
+
+    %% join
+    ok = syn:join(custom_scope_ab, <<"subscribers">>, Pid),
+    ok = syn:join(custom_scope_ab, <<"subscribers">>, Pid2),
+    ok = syn:join(custom_scope_ab, <<"subscribers">>, PidRemoteOn1),
+    ok = syn:join(custom_scope_ab, <<"subscribers-2">>, Pid),
+    ok = rpc:call(SlaveNode1, syn, join, [custom_scope_bc, <<"subscribers">>, PidRemoteOn1]),
+    ok = rpc:call(SlaveNode2, syn, join, [custom_scope_bc, <<"subscribers-2">>, PidRemoteOn2]),
+
+    %% errors
+    {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:group_names(custom_scope_bc),
+
+    %% retrieve
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-2">>]),
+        fun() -> lists:sort(syn:group_names(custom_scope_ab)) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-2">>]),
+        fun() -> lists:sort(syn:group_names(custom_scope_ab, node())) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers">>],
+        fun() -> lists:sort(syn:group_names(custom_scope_ab, SlaveNode1)) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(syn:group_names(custom_scope_ab, SlaveNode2)) end
+    ),
+
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-2">>]),
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [custom_scope_ab])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-2">>]),
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [custom_scope_ab, node()])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers">>],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [custom_scope_ab, SlaveNode1])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [custom_scope_ab, SlaveNode2])) end
+    ),
+
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-2">>]),
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [custom_scope_bc])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [custom_scope_bc, node()])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers">>],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [custom_scope_bc, SlaveNode1])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers-2">>],
+        fun() -> lists:sort(rpc:call(SlaveNode1, syn, group_names, [custom_scope_bc, SlaveNode2])) end
+    ),
+
+    syn_test_suite_helper:assert_wait(
+        lists:sort([<<"subscribers">>, <<"subscribers-2">>]),
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [custom_scope_bc])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [custom_scope_bc, node()])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers">>],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [custom_scope_bc, SlaveNode1])) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        [<<"subscribers-2">>],
+        fun() -> lists:sort(rpc:call(SlaveNode2, syn, group_names, [custom_scope_bc, SlaveNode2])) end
+    ).
+
 %% ===================================================================
 %% Internal
 %% ===================================================================