Skip to content

Commit 9d39cb0

Browse files
Merge pull request #7683 from rabbitmq/mergify/bp/v3.10.x/pr-7681
Improve rabbit_fifo_dlx_worker resiliency (backport #7677) (backport #7680) (backport #7681)
2 parents 6ffcc4b + a10d2f2 commit 9d39cb0

4 files changed

Lines changed: 31 additions & 17 deletions

File tree

deps/rabbit/src/rabbit_fifo_dlx.erl

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,20 @@ apply(_, {dlx, #checkout{consumer = Pid,
114114
apply(_, {dlx, #checkout{consumer = ConsumerPid,
115115
prefetch = Prefetch}},
116116
at_least_once,
117-
#?MODULE{consumer = #dlx_consumer{checked_out = CheckedOutOldConsumer},
117+
#?MODULE{consumer = #dlx_consumer{pid = OldConsumerPid,
118+
checked_out = CheckedOutOldConsumer},
118119
discards = Discards0,
119120
msg_bytes = Bytes,
120121
msg_bytes_checkout = BytesCheckout} = State0) ->
121122
%% Since we allow only a single consumer, the new consumer replaces the old consumer.
123+
case ConsumerPid of
124+
OldConsumerPid ->
125+
ok;
126+
_ ->
127+
rabbit_log:debug("Terminating ~p since ~p becomes active rabbit_fifo_dlx_worker",
128+
[OldConsumerPid, ConsumerPid]),
129+
ensure_worker_terminated(State0)
130+
end,
122131
%% All checked out messages to the old consumer need to be returned to the discards queue
123132
%% such that these messages will be re-delivered to the new consumer.
124133
%% When inserting back into the discards queue, we respect the original order in which messages

deps/rabbit/src/rabbit_fifo_dlx_client.erl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ settle(MsgIds, #state{leader = Leader} = State)
3232
{ok, State}.
3333

3434
-spec checkout(rabbit_amqqueue:name(), ra:server_id(), non_neg_integer()) ->
35-
{ok, state()} | {error, ra_command_failed}.
35+
{ok, state()} | {error, non_local_leader | ra_command_failed}.
3636
checkout(QResource, Leader, NumUnsettled) ->
3737
Cmd = rabbit_fifo_dlx:make_checkout(self(), NumUnsettled),
3838
State = #state{queue_resource = QResource,
@@ -46,10 +46,10 @@ process_command(Cmd, #state{leader = Leader} = State, Tries) ->
4646
case ra:process_command(Leader, Cmd, 60_000) of
4747
{ok, ok, Leader} ->
4848
{ok, State#state{leader = Leader}};
49-
{ok, ok, L} ->
49+
{ok, ok, NonLocalLeader} ->
5050
rabbit_log:warning("Failed to process command ~p on quorum queue leader ~p because actual leader is ~p.",
51-
[Cmd, Leader, L]),
52-
{error, ra_command_failed};
51+
[Cmd, Leader, NonLocalLeader]),
52+
{error, non_local_leader};
5353
Err ->
5454
rabbit_log:warning("Failed to process command ~p on quorum queue leader ~p: ~p~n"
5555
"Trying ~b more time(s)...",

deps/rabbit/src/rabbit_fifo_dlx_sup.erl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ start_link() ->
2424

2525
init([]) ->
2626
SupFlags = #{strategy => simple_one_for_one,
27-
intensity => 1,
28-
period => 5},
27+
intensity => 100,
28+
period => 1},
2929
Worker = rabbit_fifo_dlx_worker,
3030
ChildSpec = #{id => Worker,
3131
start => {Worker, start_link, []},
3232
type => worker,
33+
restart => transient,
3334
modules => [Worker]},
3435
{ok, {SupFlags, [ChildSpec]}}.

deps/rabbit/src/rabbit_fifo_dlx_worker.erl

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -106,23 +106,27 @@ init(QRef) ->
106106
{ok, undefined, {continue, QRef}}.
107107

108108
-spec handle_continue(rabbit_amqqueue:name(), undefined) ->
109-
{noreply, state()}.
109+
{noreply, state()} | {stop, term(), undefined}.
110110
handle_continue(QRef, undefined) ->
111111
{ok, Prefetch} = application:get_env(rabbit,
112112
dead_letter_worker_consumer_prefetch),
113113
{ok, SettleTimeout} = application:get_env(rabbit,
114114
dead_letter_worker_publisher_confirm_timeout),
115115
{ok, Q} = rabbit_amqqueue:lookup(QRef),
116116
{ClusterName, _MaybeOldLeaderNode} = amqqueue:get_pid(Q),
117-
{ok, ConsumerState} = rabbit_fifo_dlx_client:checkout(QRef,
118-
{ClusterName, node()},
119-
Prefetch),
120-
{noreply, lookup_topology(#state{queue_ref = QRef,
121-
queue_type_state = rabbit_queue_type:init(),
122-
settle_timeout = SettleTimeout,
123-
dlx_client_state = ConsumerState,
124-
monitor_ref = erlang:monitor(process, ClusterName)
125-
})}.
117+
case rabbit_fifo_dlx_client:checkout(QRef, {ClusterName, node()}, Prefetch) of
118+
{ok, ConsumerState} ->
119+
{noreply, lookup_topology(#state{queue_ref = QRef,
120+
queue_type_state = rabbit_queue_type:init(),
121+
settle_timeout = SettleTimeout,
122+
dlx_client_state = ConsumerState,
123+
monitor_ref = erlang:monitor(process, ClusterName)
124+
})};
125+
{error, non_local_leader = Reason} ->
126+
{stop, {shutdown, Reason}, undefined};
127+
Error ->
128+
{stop, Error, undefined}
129+
end.
126130

127131
terminate(_Reason, State) ->
128132
cancel_timer(State).

0 commit comments

Comments
 (0)