Browse Source

Added a function to get all registered group names

This is helpful when using the process groups for a pubsub.
For example, if a processes wants to unsubscribe to all topics.
zander 5 years ago
parent
commit
f155c905f5
4 changed files with 85 additions and 0 deletions
  1. 9 0
      README.md
  2. 5 0
      src/syn.erl
  3. 11 0
      src/syn_groups.erl
  4. 60 0
      test/syn_groups_SUITE.erl

+ 9 - 0
README.md

@@ -254,6 +254,15 @@ Types:
     GroupName = any()
 ```
 
+To get a list of the existing groups:
+
+```erlang
+syn:get_group_names() -> [GroupName].
+
+Types:
+    GroupName = any()
+```
+
 To publish a message to all group members:
 
 ```erlang

+ 5 - 0
src/syn.erl

@@ -35,6 +35,7 @@
 -export([join/2, join/3]).
 -export([leave/2]).
 -export([get_members/1, get_members/2]).
+-export([get_group_names/0]).
 -export([member/2]).
 -export([get_local_members/1, get_local_members/2]).
 -export([local_member/2]).
@@ -146,6 +147,10 @@ get_members(GroupName) ->
 get_members(GroupName, with_meta) ->
     syn_groups:get_members(GroupName, with_meta).
 
+-spec get_group_names() -> [GroupName :: any()].
+get_group_names() ->
+    syn_groups:get_group_names().
+
 -spec member(GroupName :: any(), Pid :: pid()) -> boolean().
 member(GroupName, Pid) ->
     syn_groups:member(GroupName, Pid).

+ 11 - 0
src/syn_groups.erl

@@ -31,6 +31,7 @@
 -export([join/2, join/3]).
 -export([leave/2]).
 -export([get_members/1, get_members/2]).
+-export([get_group_names/0]).
 -export([member/2]).
 -export([get_local_members/1, get_local_members/2]).
 -export([local_member/2]).
@@ -116,6 +117,16 @@ get_members(GroupName, with_meta) ->
         [{{'$2', '$3'}}]
     }]).
 
+-spec get_group_names() -> [GroupName :: any()].
+get_group_names() ->
+    Groups = ets:select(syn_groups_by_name, [{
+      {{'$1', '_'}, '_', '_', '_'},
+      [],
+      ['$1']
+    }]),
+    Set = sets:from_list(Groups),
+    sets:to_list(Set).
+
 -spec member(Pid :: pid(), GroupName :: any()) -> boolean().
 member(Pid, GroupName) ->
     case find_groups_entry_by_name_and_pid(GroupName, Pid) of

+ 60 - 0
test/syn_groups_SUITE.erl

@@ -37,6 +37,7 @@
     single_node_join_and_leave/1,
     single_node_join_errors/1,
     single_node_groups_count/1,
+    single_node_group_names/1,
     single_node_publish/1,
     single_node_multicall/1,
     single_node_multicall_with_custom_timeout/1,
@@ -47,6 +48,7 @@
     two_nodes_join_monitor_and_unregister/1,
     two_nodes_local_members/1,
     two_nodes_groups_count/1,
+    two_nodes_group_names/1,
     two_nodes_publish/1,
     two_nodes_local_publish/1,
     two_nodes_multicall/1,
@@ -100,6 +102,7 @@ groups() ->
             single_node_join_and_leave,
             single_node_join_errors,
             single_node_groups_count,
+            single_node_group_names,
             single_node_publish,
             single_node_multicall,
             single_node_multicall_with_custom_timeout,
@@ -110,6 +113,7 @@ groups() ->
             two_nodes_join_monitor_and_unregister,
             two_nodes_local_members,
             two_nodes_groups_count,
+            two_nodes_group_names,
             two_nodes_publish,
             two_nodes_local_publish,
             two_nodes_multicall,
@@ -326,6 +330,31 @@ single_node_groups_count(_Config) ->
     0 = syn:groups_count(),
     0 = syn:groups_count(node()).
 
+single_node_group_names(_Config) ->
+    %% start
+    ok = syn:start(),
+    %% start processes
+    Pid = syn_test_suite_helper:start_process(),
+    Pid2 = syn_test_suite_helper:start_process(),
+    Pid3 = syn_test_suite_helper:start_process(),
+    %% join
+    ok = syn:join({"group-1"}, Pid),
+    ok = syn:join({"group-1"}, Pid2),
+    ok = syn:join({"group-1"}, Pid3),
+    ok = syn:join({"group-2"}, Pid2),
+    %% names
+    GroupNames = syn:get_group_names(),
+    2 = length(GroupNames),
+    true = lists:member({"group-1"}, GroupNames),
+    true = lists:member({"group-2"}, GroupNames),
+    %% kill & unregister
+    ok = syn:leave({"group-1"}, Pid),
+    syn_test_suite_helper:kill_process(Pid2),
+    syn_test_suite_helper:kill_process(Pid3),
+    timer:sleep(100),
+    %% count
+    [] = syn:get_group_names().
+
 single_node_publish(_Config) ->
     GroupName = "my group",
     Message = {test, message},
@@ -646,6 +675,37 @@ two_nodes_groups_count(Config) ->
     0 = syn:groups_count(node()),
     0 = syn:groups_count(SlaveNode).
 
+two_nodes_group_names(Config) ->
+    %% get slave
+    SlaveNode = proplists:get_value(slave_node, Config),
+    %% start
+    ok = syn:start(),
+    ok = rpc:call(SlaveNode, syn, start, []),
+    timer:sleep(100),
+    %% start processes
+    LocalPid = syn_test_suite_helper:start_process(),
+    RemotePid = syn_test_suite_helper:start_process(SlaveNode),
+    RemotePidRegRemote = syn_test_suite_helper:start_process(SlaveNode),
+    _PidUnjoined = syn_test_suite_helper:start_process(),
+    %% join
+    ok = syn:join(<<"local group">>, LocalPid),
+    ok = syn:join(<<"remote group">>, RemotePid),
+    ok = rpc:call(SlaveNode, syn, join, [<<"remote group join_remote">>, RemotePidRegRemote]),
+    timer:sleep(500),
+    %% names
+    GroupNames = syn:get_group_names(),
+    3 = length(GroupNames),
+    true = lists:member(<<"local group">>, GroupNames),
+    true = lists:member(<<"remote group">>, GroupNames),
+    true = lists:member(<<"remote group join_remote">>, GroupNames),
+    %% kill & unregister processes
+    syn_test_suite_helper:kill_process(LocalPid),
+    ok = syn:leave(<<"remote group">>, RemotePid),
+    syn_test_suite_helper:kill_process(RemotePidRegRemote),
+    timer:sleep(100),
+    %% names
+    [] = syn:get_group_names().
+
 two_nodes_publish(Config) ->
     GroupName = "my group",
     Message = {test, message},