Skip to content

Commit 1e95870

Browse files
author
Alex Valiushko
committed
add API to list voters
1 parent 90078d4 commit 1e95870

File tree

3 files changed

+69
-4
lines changed

3 files changed

+69
-4
lines changed

src/ra.erl

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
%% queries
2424
members/1,
2525
members/2,
26+
voters/1,
27+
voters/2,
2628
initial_members/1,
2729
initial_members/2,
2830
local_query/2,
@@ -1037,6 +1039,44 @@ members({local, ServerId}, Timeout) ->
10371039
members(ServerId, Timeout) ->
10381040
ra_server_proc:state_query(ServerId, members, Timeout).
10391041

1042+
%% @doc Returns a list of cluster voters
1043+
%%
1044+
%% Except if `{local, ServerId}' is passed, the query is sent to the specified
1045+
%% server which may redirect it to the leader if it is a follower. It may
1046+
%% timeout if there is currently no leader (i.e. an election is in progress).
1047+
%%
1048+
%% With `{local, ServerId}', the query is always handled by the specified
1049+
%% server. It means the returned list might be out-of-date compared to what the
1050+
%% leader would have returned.
1051+
%%
1052+
%% @param ServerId the Ra server(s) to send the query to
1053+
%% @end
1054+
-spec voters(ra_server_id() | [ra_server_id()] | {local, ra_server_id()}) ->
1055+
ra_server_proc:ra_leader_call_ret([ra_server_id()]).
1056+
voters(ServerId) ->
1057+
voters(ServerId, ?DEFAULT_TIMEOUT).
1058+
1059+
%% @doc Returns a list of cluster voters
1060+
%%
1061+
%% Except if `{local, ServerId}' is passed, the query is sent to the specified
1062+
%% server which may redirect it to the leader if it is a follower. It may
1063+
%% timeout if there is currently no leader (i.e. an election is in progress).
1064+
%%
1065+
%% With `{local, ServerId}', the query is always handled by the specified
1066+
%% server. It means the returned list might be out-of-date compared to what the
1067+
%% leader would have returned.
1068+
%%
1069+
%% @param ServerId the Ra server(s) to send the query to
1070+
%% @param Timeout the timeout to use
1071+
%% @end
1072+
-spec voters(ra_server_id() | [ra_server_id()] | {local, ra_server_id()},
1073+
timeout()) ->
1074+
ra_server_proc:ra_leader_call_ret([ra_server_id()]).
1075+
voters({local, ServerId}, Timeout) ->
1076+
ra_server_proc:local_state_query(ServerId, voters, Timeout);
1077+
voters(ServerId, Timeout) ->
1078+
ra_server_proc:state_query(ServerId, voters, Timeout).
1079+
10401080
%% @doc Returns a list of initial (seed) cluster members.
10411081
%%
10421082
%% This allows Ra-based systems with dynamic cluster membership

src/ra_server_proc.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1552,7 +1552,7 @@ do_state_query(voters, #{cluster := Cluster}) ->
15521552
end
15531553
end
15541554
end, [], Cluster),
1555-
Vs;
1555+
lists:sort(Vs);
15561556
do_state_query(members, #{cluster := Cluster}) ->
15571557
maps:keys(Cluster);
15581558
do_state_query(initial_members, #{log := Log}) ->

test/ra_SUITE.erl

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ all_tests() ->
4444
local_query_boom,
4545
local_query_stale,
4646
members,
47+
voters_promotable,
48+
voters_non_voter,
4749
consistent_query,
4850
consistent_query_after_restart,
4951
consistent_query_minority,
@@ -537,6 +539,29 @@ members(Config) ->
537539
{ok, Cluster, Leader} = ra:members(Leader),
538540
terminate_cluster(Cluster).
539541

542+
voters_promotable(Config) ->
543+
Name = ?config(test_name, Config),
544+
[A, B] = Cluster = start_local_cluster(2, Name, add_machine()),
545+
{ok, _, Leader} = ra:process_command(A, 9),
546+
C = {ra_server:name(Name, "3"), node()},
547+
ok = ra:start_server(default, Name, C, add_machine(), Cluster),
548+
{ok, _, _} = ra:add_member(Leader, #{id => C, uid => <<"4">>, membership => promotable}),
549+
{ok, [A, B, C], Leader} = ra:members(Leader),
550+
{ok, [A, B], Leader} = ra:voters(Leader),
551+
terminate_cluster([C | Cluster]).
552+
553+
voters_non_voter(Config) ->
554+
Name = ?config(test_name, Config),
555+
[A, B] = Cluster = start_local_cluster(2, Name, add_machine()),
556+
{ok, _, Leader} = ra:process_command(A, 9),
557+
C = {ra_server:name(Name, "3"), node()},
558+
ok = ra:start_server(default, Name, C, add_machine(), Cluster),
559+
{ok, _, _} = ra:add_member(Leader, #{id => C, uid => <<"4">>, membership => non_voter}),
560+
{ok, [A, B, C], Leader} = ra:members(Leader),
561+
{ok, [A, B], Leader} = ra:voters(Leader),
562+
terminate_cluster([C | Cluster]).
563+
564+
540565
consistent_query(Config) ->
541566
[A, _, _] = Cluster = start_local_cluster(3, ?config(test_name, Config),
542567
add_machine()),
@@ -1073,7 +1098,7 @@ voter_gets_promoted_consistent_leader(Config) ->
10731098
timer:sleep(100),
10741099
All = [N1, N2, N3],
10751100
% in server state
1076-
lists:map(fun(O) -> ?assertEqual(All, voters(O)) end, overviews(N1)),
1101+
lists:map(fun(O) -> ?assertEqual(All, filter_voters(O)) end, overviews(N1)),
10771102
% in ets
10781103
#{servers := Servers} = ra:overview(?SYS),
10791104
lists:map(fun({Name, _}) -> #{Name := #{membership := voter}} = Servers end, All),
@@ -1098,7 +1123,7 @@ voter_gets_promoted_new_leader(Config) ->
10981123
timer:sleep(100),
10991124
All = [N1, N2, N3],
11001125
% in server state
1101-
lists:map(fun(O) -> ?assertEqual(All, voters(O)) end, overviews(N1)),
1126+
lists:map(fun(O) -> ?assertEqual(All, filter_voters(O)) end, overviews(N1)),
11021127
% in ets
11031128
#{servers := Servers} = ra:overview(?SYS),
11041129
lists:map(fun({Name, _}) -> #{Name := #{membership := voter}} = Servers end, All),
@@ -1217,7 +1242,7 @@ overviews(Node) ->
12171242
{ok, Members, _From} = ra:members(Node),
12181243
[ra:member_overview(P) || {_, _} = P <- Members].
12191244

1220-
voters({ok, #{cluster := Peers}, _} = _Overview) ->
1245+
filter_voters({ok, #{cluster := Peers}, _} = _Overview) ->
12211246
[Id || {Id, Status} <- maps:to_list(Peers), maps:get(membership, Status, voter) == voter].
12221247

12231248
%% machine impl

0 commit comments

Comments
 (0)