Browse Source

Allow multi_call to accept a Timeout value.

[ostinelli/syn#12]
Roberto Ostinelli 9 years ago
parent
commit
e589fa92d4
4 changed files with 30 additions and 16 deletions
  1. 7 1
      README.md
  2. 5 1
      src/syn.erl
  3. 17 13
      src/syn_groups.erl
  4. 1 1
      test/syn_groups_SUITE.erl

+ 7 - 1
README.md

@@ -280,17 +280,23 @@ To call all group members and get their replies:
 
 ```erlang
 syn:multi_call(Name, Message) -> {Replies, BadPids}.
+```
+Same as `syn:multi_call(Name, Message, 5000)`.
+
+```erlang
+syn:multi_call(Name, Message, Timeout) -> {Replies, BadPids}.
 
 Types:
 	Name = any()
 	Message = any()
+	Timeout = non_neg_integer()
 	Replies = [{MemberPid, Reply}]
 	BadPids = [MemberPid]
 	  MemberPid = pid()
 	  Reply = any()
 ```
 
-> Syn will wait up to 5 seconds to receive all replies from the members. The members that do not reply in time will be added to the BadPids list.
+> Syn will wait up to the value specified in `Timeout` to receive all replies from the members. The members that do not reply in time will be added to the `BadPids` list.
 
 When this call is issued, all members will receive a tuple in the format:
 

+ 5 - 1
src/syn.erl

@@ -42,7 +42,7 @@
 -export([member/2]).
 -export([get_members/1]).
 -export([publish/2]).
--export([multi_call/2]).
+-export([multi_call/2, multi_call/3]).
 -export([multi_call_reply/2]).
 
 %% ===================================================================
@@ -122,6 +122,10 @@ publish(Name, Message) ->
 multi_call(Name, Message) ->
     syn_groups:multi_call(Name, Message).
 
+-spec multi_call(Name :: any(), Message :: any(), Timeout :: non_neg_integer()) -> [{pid(), Response :: any()}].
+multi_call(Name, Message, Timeout) ->
+    syn_groups:multi_call(Name, Message, Timeout).
+
 -spec multi_call_reply(CallerPid :: pid(), Reply :: any()) -> ok.
 multi_call_reply(CallerPid, Reply) ->
     syn_groups:multi_call_reply(CallerPid, Reply).

+ 17 - 13
src/syn_groups.erl

@@ -33,7 +33,7 @@
 -export([member/2]).
 -export([get_members/1]).
 -export([publish/2]).
--export([multi_call/2]).
+-export([multi_call/2, multi_call/3]).
 -export([multi_call_reply/2]).
 
 %% gen_server callbacks
@@ -43,7 +43,7 @@
 -record(state, {}).
 
 %% macros
--define(MULTI_CALL_TIMEOUT_MS, 5000).
+-define(DEFAULT_MULTI_CALL_TIMEOUT_MS, 5000).
 
 %% include
 -include("syn.hrl").
@@ -84,16 +84,20 @@ publish(Name, Message) ->
     lists:foreach(FSend, MemberPids),
     {ok, length(MemberPids)}.
 
--spec multi_call(Name :: any(), Message :: any()) ->
-    {[{pid(), Reply :: any()}], [BadPid :: pid()]}.
+-spec multi_call(Name :: any(), Message :: any()) -> {[{pid(), Reply :: any()}], [BadPid :: pid()]}.
 multi_call(Name, Message) ->
+    multi_call(Name, Message, ?DEFAULT_MULTI_CALL_TIMEOUT_MS).
+
+-spec multi_call(Name :: any(), Message :: any(), Timeout :: non_neg_integer()) ->
+    {[{pid(), Reply :: any()}], [BadPid :: pid()]}.
+multi_call(Name, Message, Timeout) ->
     Self = self(),
     MemberPids = i_get_members(Name),
     FSend = fun(Pid) ->
         Pid ! {syn_multi_call, Self, Message}
     end,
     lists:foreach(FSend, MemberPids),
-    collect_replies(MemberPids).
+    collect_replies(MemberPids, Timeout).
 
 -spec multi_call_reply(CallerPid :: pid(), Reply :: any()) -> ok.
 multi_call_reply(CallerPid, Reply) ->
@@ -274,19 +278,19 @@ i_find_by_pid(Pid) ->
 remove_process(Process) ->
     mnesia:dirty_delete_object(syn_groups_table, Process).
 
--spec collect_replies(MemberPids :: [pid()]) ->
+-spec collect_replies(MemberPids :: [pid()], Timeout :: non_neg_integer()) ->
     {[{pid(), Reply :: any()}], [BadPid :: pid()]}.
-collect_replies(MemberPids) ->
-    collect_replies(MemberPids, []).
+collect_replies(MemberPids, Timeout) ->
+    collect_replies(MemberPids, Timeout, []).
 
--spec collect_replies(MemberPids :: [pid()], Replies :: [{pid(), Reply :: any()}]) ->
+-spec collect_replies(MemberPids :: [pid()], Timeout :: non_neg_integer(), Replies :: [{pid(), Reply :: any()}]) ->
     {[{pid(), Reply :: any()}], [BadPid :: pid()]}.
-collect_replies([], Replies) -> {Replies, []};
-collect_replies(MemberPids, Replies) ->
+collect_replies([], _Timeout, Replies) -> {Replies, []};
+collect_replies(MemberPids, Timeout, Replies) ->
     receive
         {syn_multi_call_reply, Pid, Reply} ->
             MemberPids1 = lists:delete(Pid, MemberPids),
-            collect_replies(MemberPids1, [{Pid, Reply} | Replies])
-    after ?MULTI_CALL_TIMEOUT_MS ->
+            collect_replies(MemberPids1, Timeout, [{Pid, Reply} | Replies])
+    after Timeout ->
         {Replies, MemberPids}
     end.

+ 1 - 1
test/syn_groups_SUITE.erl

@@ -376,7 +376,7 @@ two_nodes_multi_call(Config) ->
     ok = syn:join(<<"my group">>, PidUnresponsive),
     timer:sleep(100),
     %% call
-    {Replies, BadPids} = syn:multi_call(<<"my group">>, get_pid_name),
+    {Replies, BadPids} = syn:multi_call(<<"my group">>, get_pid_name, 3000),
     %% check responses
     2 = length(Replies),
     pid1 = proplists:get_value(PidLocal, Replies),