diff --git a/src/pooler.erl b/src/pooler.erl index a8516da..c6cbec7 100644 --- a/src/pooler.erl +++ b/src/pooler.erl @@ -33,6 +33,7 @@ take_member/1, take_member/2, take_group_member/1, + take_group_member/2, return_group_member/2, return_group_member/3, return_member/2, @@ -202,13 +203,21 @@ take_member(PoolName) when is_atom(PoolName) orelse is_pid(PoolName) -> take_member(PoolName, Timeout) when is_atom(PoolName) orelse is_pid(PoolName) -> gen_server:call(PoolName, {take_member, time_as_millis(Timeout)}, infinity). - %% @doc Take a member from a randomly selected member of the group %% `GroupName'. Returns `MemberPid' or `error_no_members'. If no %% members are available in the randomly chosen pool, all other pools %% in the group are tried in order. -spec take_group_member(atom()) -> pid() | error_no_members | {error_no_group, atom()}. -take_group_member(GroupName) -> +take_group_member(GroupName) -> take_group_member(GroupName, 0). + +%% @doc Take a member from a randomly selected member of the group +%% `GroupName'. Returns `MemberPid' or `error_no_members'. If no +%% members are available in the randomly chosen pool, all other pools +%% in the group are tried in order. If no member +%% is available within the specified timeout, error_no_members is returned. +%% `Timeout' can be either milliseconds as integer or `{duration, time_unit}' +-spec take_group_member(atom(), non_neg_integer()) -> pid() | error_no_members | {error_no_group, atom()}. +take_group_member(GroupName, Timeout) -> case pg2:get_local_members(GroupName) of {error, {no_such_group, GroupName}} -> {error_no_group, GroupName}; @@ -220,18 +229,25 @@ take_group_member(GroupName) -> {_, _, X} = os:timestamp(), Idx = (X rem length(Pools)) + 1, {PoolPid, Rest} = extract_nth(Idx, Pools), - take_first_pool([PoolPid | Rest]) + case {take_first_pool([PoolPid | Rest], 0), Timeout} of + {error_no_members, 0} -> + error_no_members; + {error_no_members, _} -> + take_first_pool([PoolPid | Rest], Timeout); + {Member, _} -> + Member + end end. -take_first_pool([PoolPid | Rest]) -> - case take_member(PoolPid) of +take_first_pool([PoolPid | Rest], Timeout) -> + case take_member(PoolPid, Timeout) of error_no_members -> - take_first_pool(Rest); + take_first_pool(Rest, Timeout); Member -> ets:insert(?POOLER_GROUP_TABLE, {Member, PoolPid}), Member end; -take_first_pool([]) -> +take_first_pool([], _) -> error_no_members. %% this helper function returns `{Nth_Elt, Rest}' where `Nth_Elt' is