|
31 | 31 | update_machine_state/2, |
32 | 32 | pending_size/1, |
33 | 33 | stat/1, |
34 | | - stat/2 |
| 34 | + stat/2, |
| 35 | + query_single_active_consumer/1 |
35 | 36 | ]). |
36 | 37 |
|
37 | 38 | -include_lib("rabbit_common/include/rabbit.hrl"). |
38 | 39 |
|
39 | 40 | -define(SOFT_LIMIT, 32). |
40 | 41 | -define(TIMER_TIME, 10000). |
| 42 | +-define(COMMAND_TIMEOUT, 30000). |
41 | 43 |
|
42 | 44 | -type seq() :: non_neg_integer(). |
43 | 45 | %% last_applied is initialised to -1 |
@@ -142,27 +144,33 @@ init(ClusterName = #resource{}, Servers, SoftLimit, BlockFun, UnblockFun) -> |
142 | 144 | enqueue(Correlation, Msg, |
143 | 145 | #state{queue_status = undefined, |
144 | 146 | next_enqueue_seq = 1, |
145 | | - cfg = #cfg{timeout = Timeout}} = State0) -> |
| 147 | + cfg = #cfg{servers = Servers, |
| 148 | + timeout = Timeout}} = State0) -> |
146 | 149 | %% it is the first enqueue, check the version |
147 | | - {_, Node} = Server = pick_server(State0), |
| 150 | + {_, Node} = pick_server(State0), |
148 | 151 | case rpc:call(Node, ra_machine, version, [{machine, rabbit_fifo, #{}}]) of |
149 | 152 | 0 -> |
150 | 153 | %% the leader is running the old version |
151 | | - %% so we can't initialize the enqueuer session safely |
152 | | - %% fall back on old behavour |
153 | 154 | enqueue(Correlation, Msg, State0#state{queue_status = go}); |
154 | 155 | 1 -> |
155 | 156 | %% were running the new version on the leader do sync initialisation |
156 | 157 | %% of enqueuer session |
157 | 158 | Reg = rabbit_fifo:make_register_enqueuer(self()), |
158 | | - case ra:process_command(Server, Reg, Timeout) of |
159 | | - {ok, reject_publish, _} -> |
160 | | - {reject_publish, State0#state{queue_status = reject_publish}}; |
161 | | - {ok, ok, _} -> |
162 | | - enqueue(Correlation, Msg, State0#state{queue_status = go}); |
| 159 | + case ra:process_command(Servers, Reg, Timeout) of |
| 160 | + {ok, reject_publish, Leader} -> |
| 161 | + {reject_publish, State0#state{leader = Leader, |
| 162 | + queue_status = reject_publish}}; |
| 163 | + {ok, ok, Leader} -> |
| 164 | + enqueue(Correlation, Msg, State0#state{leader = Leader, |
| 165 | + queue_status = go}); |
| 166 | + {error, {no_more_servers_to_try, _Errs}} -> |
| 167 | + %% if we are not able to process the register command |
| 168 | + %% it is safe to reject the message as we never attempted |
| 169 | + %% to send it |
| 170 | + {reject_publish, State0}; |
| 171 | + %% TODO: not convinced this can ever happen when using |
| 172 | + %% a list of servers |
163 | 173 | {timeout, _} -> |
164 | | - %% if we timeout it is probably better to reject |
165 | | - %% the message than being uncertain |
166 | 174 | {reject_publish, State0}; |
167 | 175 | Err -> |
168 | 176 | exit(Err) |
@@ -387,6 +395,20 @@ checkout(ConsumerTag, NumUnsettled, CreditMode, Meta, |
387 | 395 | ack = Ack}, CDels0), |
388 | 396 | try_process_command(Servers, Cmd, State0#state{consumer_deliveries = SDels}). |
389 | 397 |
|
| 398 | + |
| 399 | +-spec query_single_active_consumer(state()) -> |
| 400 | + {ok, term()} | {error, term()} | {timeout, term()}. |
| 401 | +query_single_active_consumer(#state{leader = undefined}) -> |
| 402 | + {error, leader_not_known}; |
| 403 | +query_single_active_consumer(#state{leader = Leader}) -> |
| 404 | + case ra:local_query(Leader, fun rabbit_fifo:query_single_active_consumer/1, |
| 405 | + ?COMMAND_TIMEOUT) of |
| 406 | + {ok, {_, Reply}, _} -> |
| 407 | + {ok, Reply}; |
| 408 | + Err -> |
| 409 | + Err |
| 410 | + end. |
| 411 | + |
390 | 412 | %% @doc Provide credit to the queue |
391 | 413 | %% |
392 | 414 | %% This only has an effect if the consumer uses credit mode: credited |
@@ -436,8 +458,8 @@ cancel_checkout(ConsumerTag, #state{consumer_deliveries = CDels} = State0) -> |
436 | 458 | %% @doc Purges all the messages from a rabbit_fifo queue and returns the number |
437 | 459 | %% of messages purged. |
438 | 460 | -spec purge(ra:server_id()) -> {ok, non_neg_integer()} | {error | timeout, term()}. |
439 | | -purge(Node) -> |
440 | | - case ra:process_command(Node, rabbit_fifo:make_purge()) of |
| 461 | +purge(Server) -> |
| 462 | + case ra:process_command(Server, rabbit_fifo:make_purge(), ?COMMAND_TIMEOUT) of |
441 | 463 | {ok, {purge, Reply}, _} -> |
442 | 464 | {ok, Reply}; |
443 | 465 | Err -> |
@@ -474,7 +496,7 @@ cluster_name(#state{cfg = #cfg{cluster_name = ClusterName}}) -> |
474 | 496 | ClusterName. |
475 | 497 |
|
476 | 498 | update_machine_state(Server, Conf) -> |
477 | | - case ra:process_command(Server, rabbit_fifo:make_update_config(Conf)) of |
| 499 | + case ra:process_command(Server, rabbit_fifo:make_update_config(Conf), ?COMMAND_TIMEOUT) of |
478 | 500 | {ok, ok, _} -> |
479 | 501 | ok; |
480 | 502 | Err -> |
@@ -632,8 +654,9 @@ untracked_enqueue([Node | _], Msg) -> |
632 | 654 |
|
633 | 655 | %% Internal |
634 | 656 |
|
635 | | -try_process_command([Server | Rem], Cmd, State) -> |
636 | | - case ra:process_command(Server, Cmd, 30000) of |
| 657 | +try_process_command([Server | Rem], Cmd, |
| 658 | + #state{cfg = #cfg{timeout = Timeout}} = State) -> |
| 659 | + case ra:process_command(Server, Cmd, Timeout) of |
637 | 660 | {ok, _, Leader} -> |
638 | 661 | {ok, State#state{leader = Leader}}; |
639 | 662 | Err when length(Rem) =:= 0 -> |
@@ -793,7 +816,7 @@ get_missing_deliveries(Leader, From, To, ConsumerTag) -> |
793 | 816 | Query = fun (State) -> |
794 | 817 | rabbit_fifo:get_checked_out(ConsumerId, From, To, State) |
795 | 818 | end, |
796 | | - case ra:local_query(Leader, Query) of |
| 819 | + case ra:local_query(Leader, Query, ?COMMAND_TIMEOUT) of |
797 | 820 | {ok, {_, Missing}, _} -> |
798 | 821 | Missing; |
799 | 822 | {error, Error} -> |
|
0 commit comments