Skip to content

Commit 710e83f

Browse files
Merge pull request #12130 from rabbitmq/mergify/bp/v4.0.x/pr-12082
2 parents 7aef123 + c9ad0cd commit 710e83f

File tree

7 files changed

+94
-30
lines changed

7 files changed

+94
-30
lines changed

deps/rabbit/src/rabbit_amqqueue.erl

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1669,6 +1669,11 @@ delete_with(QueueName, ConnPid, IfUnused, IfEmpty, Username, CheckExclusive) whe
16691669
{error, {exit, _, _}} ->
16701670
%% delete()/delegate:invoke might return {error, {exit, _, _}}
16711671
{ok, 0};
1672+
{error, timeout} ->
1673+
rabbit_misc:protocol_error(
1674+
internal_error,
1675+
"The operation to delete the queue from the metadata store "
1676+
"timed out", []);
16721677
{ok, Count} ->
16731678
{ok, Count};
16741679
{protocol_error, Type, Reason, ReasonArgs} ->
@@ -1777,7 +1782,10 @@ notify_sent_queue_down(QPid) ->
17771782
resume(QPid, ChPid) -> delegate:invoke_no_result(QPid, {gen_server2, cast,
17781783
[{resume, ChPid}]}).
17791784

1780-
-spec internal_delete(amqqueue:amqqueue(), rabbit_types:username()) -> 'ok'.
1785+
-spec internal_delete(Queue, ActingUser) -> Ret when
1786+
Queue :: amqqueue:amqqueue(),
1787+
ActingUser :: rabbit_types:username(),
1788+
Ret :: ok | {error, timeout}.
17811789

17821790
internal_delete(Queue, ActingUser) ->
17831791
internal_delete(Queue, ActingUser, normal).
@@ -1787,6 +1795,8 @@ internal_delete(Queue, ActingUser, Reason) ->
17871795
case rabbit_db_queue:delete(QueueName, Reason) of
17881796
ok ->
17891797
ok;
1798+
{error, timeout} = Err ->
1799+
Err;
17901800
Deletions ->
17911801
_ = rabbit_binding:process_deletions(Deletions),
17921802
rabbit_binding:notify_deletions(Deletions, ?INTERNAL_USER),

deps/rabbit/src/rabbit_amqqueue_process.erl

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ terminate(shutdown = R, State = #q{backing_queue = BQ, q = Q0}) ->
297297
end, State);
298298
terminate({shutdown, missing_owner = Reason}, {{reply_to, From}, #q{q = Q} = State}) ->
299299
%% if the owner was missing then there will be no queue, so don't emit stats
300-
State1 = terminate_shutdown(terminate_delete(false, Reason, State), State),
300+
State1 = terminate_shutdown(terminate_delete(false, Reason, none, State), State),
301301
send_reply(From, {owner_died, Q}),
302302
State1;
303303
terminate({shutdown, _} = R, State = #q{backing_queue = BQ}) ->
@@ -310,18 +310,22 @@ terminate(normal, State = #q{status = {terminated_by, auto_delete}}) ->
310310
%% thousands of queues. A optimisation introduced by server#1513
311311
%% needs to be reverted by this case, avoiding to guard the delete
312312
%% operation on `rabbit_durable_queue`
313-
terminate_shutdown(terminate_delete(true, auto_delete, State), State);
314-
terminate(normal, State) -> %% delete case
315-
terminate_shutdown(terminate_delete(true, normal, State), State);
313+
terminate_shutdown(terminate_delete(true, auto_delete, none, State), State);
314+
terminate(normal, {{reply_to, ReplyTo}, State}) -> %% delete case
315+
terminate_shutdown(terminate_delete(true, normal, ReplyTo, State), State);
316+
terminate(normal, State) ->
317+
terminate_shutdown(terminate_delete(true, normal, none, State), State);
316318
%% If we crashed don't try to clean up the BQS, probably best to leave it.
317319
terminate(_Reason, State = #q{q = Q}) ->
318320
terminate_shutdown(fun (BQS) ->
319321
Q2 = amqqueue:set_state(Q, crashed),
322+
%% When mnesia is removed this update can become
323+
%% an async Khepri command.
320324
_ = rabbit_amqqueue:store_queue(Q2),
321325
BQS
322326
end, State).
323327

324-
terminate_delete(EmitStats, Reason0,
328+
terminate_delete(EmitStats, Reason0, ReplyTo,
325329
State = #q{q = Q,
326330
backing_queue = BQ,
327331
status = Status}) ->
@@ -332,19 +336,24 @@ terminate_delete(EmitStats, Reason0,
332336
missing_owner -> normal;
333337
Any -> Any
334338
end,
339+
Len = BQ:len(BQS),
335340
BQS1 = BQ:delete_and_terminate(Reason, BQS),
336341
if EmitStats -> rabbit_event:if_enabled(State, #q.stats_timer,
337342
fun() -> emit_stats(State) end);
338343
true -> ok
339344
end,
340345
%% This try-catch block transforms throws to errors since throws are not
341-
%% logged.
342-
try
343-
%% don't care if the internal delete doesn't return 'ok'.
344-
rabbit_amqqueue:internal_delete(Q, ActingUser, Reason0)
345-
catch
346-
{error, ReasonE} -> error(ReasonE)
347-
end,
346+
%% logged. When mnesia is removed this `try` can be removed: Khepri
347+
%% returns errors as error tuples instead.
348+
Reply = try rabbit_amqqueue:internal_delete(Q, ActingUser, Reason0) of
349+
ok ->
350+
{ok, Len};
351+
{error, _} = Err ->
352+
Err
353+
catch
354+
{error, ReasonE} -> error(ReasonE)
355+
end,
356+
send_reply(ReplyTo, Reply),
348357
BQS1
349358
end.
350359

@@ -1396,15 +1405,16 @@ handle_call(stat, _From, State) ->
13961405
ensure_expiry_timer(State),
13971406
reply({ok, BQ:len(BQS), rabbit_queue_consumers:count()}, State1);
13981407

1399-
handle_call({delete, IfUnused, IfEmpty, ActingUser}, _From,
1408+
handle_call({delete, IfUnused, IfEmpty, ActingUser}, From,
14001409
State = #q{backing_queue_state = BQS, backing_queue = BQ}) ->
14011410
IsEmpty = BQ:is_empty(BQS),
14021411
IsUnused = is_unused(State),
14031412
if
14041413
IfEmpty and not(IsEmpty) -> reply({error, not_empty}, State);
14051414
IfUnused and not(IsUnused) -> reply({error, in_use}, State);
1406-
true -> stop({ok, BQ:len(BQS)},
1407-
State#q{status = {terminated_by, ActingUser}})
1415+
true ->
1416+
State1 = State#q{status = {terminated_by, ActingUser}},
1417+
stop({{reply_to, From}, State1})
14081418
end;
14091419

14101420
handle_call(purge, _From, State = #q{backing_queue = BQ,

deps/rabbit/src/rabbit_db_queue.erl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,9 @@ list_for_count_in_khepri(VHostName) ->
376376
-spec delete(QName, Reason) -> Ret when
377377
QName :: rabbit_amqqueue:name(),
378378
Reason :: atom(),
379-
Ret :: ok | Deletions :: rabbit_binding:deletions().
379+
Ret :: ok |
380+
Deletions :: rabbit_binding:deletions() |
381+
rabbit_khepri:timeout_error().
380382

381383
delete(QueueName, Reason) ->
382384
rabbit_khepri:handle_fallback(

deps/rabbit/src/rabbit_quorum_queue.erl

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -809,19 +809,24 @@ delete(Q, _IfUnused, _IfEmpty, ActingUser) when ?amqqueue_is_quorum(Q) ->
809809
ok = force_delete_queue(Servers)
810810
end,
811811
notify_decorators(QName, shutdown),
812-
ok = delete_queue_data(Q, ActingUser),
813-
_ = erpc:call(LeaderNode, rabbit_core_metrics, queue_deleted, [QName],
814-
?RPC_TIMEOUT),
815-
{ok, ReadyMsgs};
812+
case delete_queue_data(Q, ActingUser) of
813+
ok ->
814+
_ = erpc:call(LeaderNode, rabbit_core_metrics, queue_deleted, [QName],
815+
?RPC_TIMEOUT),
816+
{ok, ReadyMsgs};
817+
{error, timeout} ->
818+
{protocol_error, internal_error,
819+
"The operation to delete queue ~ts from the metadata "
820+
"store timed out", [rabbit_misc:rs(QName)]}
821+
end;
816822
{error, {no_more_servers_to_try, Errs}} ->
817823
case lists:all(fun({{error, noproc}, _}) -> true;
818824
(_) -> false
819825
end, Errs) of
820826
true ->
821827
%% If all ra nodes were already down, the delete
822828
%% has succeed
823-
delete_queue_data(Q, ActingUser),
824-
{ok, ReadyMsgs};
829+
ok;
825830
false ->
826831
%% attempt forced deletion of all servers
827832
rabbit_log:warning(
@@ -830,9 +835,15 @@ delete(Q, _IfUnused, _IfEmpty, ActingUser) when ?amqqueue_is_quorum(Q) ->
830835
" Attempting force delete.",
831836
[rabbit_misc:rs(QName), Errs]),
832837
ok = force_delete_queue(Servers),
833-
notify_decorators(QName, shutdown),
834-
delete_queue_data(Q, ActingUser),
835-
{ok, ReadyMsgs}
838+
notify_decorators(QName, shutdown)
839+
end,
840+
case delete_queue_data(Q, ActingUser) of
841+
ok ->
842+
{ok, ReadyMsgs};
843+
{error, timeout} ->
844+
{protocol_error, internal_error,
845+
"The operation to delete queue ~ts from the metadata "
846+
"store timed out", [rabbit_misc:rs(QName)]}
836847
end
837848
end.
838849

@@ -850,9 +861,13 @@ force_delete_queue(Servers) ->
850861
end || S <- Servers],
851862
ok.
852863

864+
-spec delete_queue_data(Queue, ActingUser) -> Ret when
865+
Queue :: amqqueue:amqqueue(),
866+
ActingUser :: rabbit_types:username(),
867+
Ret :: ok | {error, timeout}.
868+
853869
delete_queue_data(Queue, ActingUser) ->
854-
_ = rabbit_amqqueue:internal_delete(Queue, ActingUser),
855-
ok.
870+
rabbit_amqqueue:internal_delete(Queue, ActingUser).
856871

857872

858873
delete_immediately(Queue) ->

deps/rabbit/src/rabbit_stream_queue.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ delete(Q, _IfUnused, _IfEmpty, ActingUser) ->
219219
{ok, Reply} ->
220220
Reply;
221221
Error ->
222-
{protocol_error, internal_error, "Cannot delete queue '~ts' on node '~ts': ~255p ",
222+
{protocol_error, internal_error, "Cannot delete ~ts on node '~ts': ~255p ",
223223
[rabbit_misc:rs(amqqueue:get_name(Q)), node(), Error]}
224224
end.
225225

deps/rabbit/src/rabbit_vhost.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ assert_benign({error, not_found}, _) -> ok;
467467
assert_benign({error, {absent, Q, _}}, ActingUser) ->
468468
%% Removing the database entries here is safe. If/when the down node
469469
%% restarts, it will clear out the on-disk storage of the queue.
470-
rabbit_amqqueue:internal_delete(Q, ActingUser).
470+
ok = rabbit_amqqueue:internal_delete(Q, ActingUser).
471471

472472
-spec exists(vhost:name()) -> boolean().
473473

deps/rabbit/test/cluster_minority_SUITE.erl

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ groups() ->
2828
declare_binding,
2929
delete_binding,
3030
declare_queue,
31+
delete_queue,
3132
publish_to_exchange,
3233
publish_and_consume_to_local_classic_queue,
3334
consume_from_queue,
@@ -97,6 +98,16 @@ init_per_group(Group, Config0) when Group == client_operations;
9798
%% To be used in consume_from_queue
9899
#'queue.declare_ok'{} = amqp_channel:call(Ch, #'queue.declare'{queue = <<"test-queue">>,
99100
arguments = [{<<"x-queue-type">>, longstr, <<"classic">>}]}),
101+
%% To be used in consume_from_queue
102+
#'queue.declare_ok'{} = amqp_channel:call(Ch, #'queue.declare'{queue = <<"test-queue-delete-classic">>,
103+
durable = true,
104+
arguments = [{<<"x-queue-type">>, longstr, <<"classic">>}]}),
105+
#'queue.declare_ok'{} = amqp_channel:call(Ch, #'queue.declare'{queue = <<"test-queue-delete-stream">>,
106+
durable = true,
107+
arguments = [{<<"x-queue-type">>, longstr, <<"stream">>}]}),
108+
#'queue.declare_ok'{} = amqp_channel:call(Ch, #'queue.declare'{queue = <<"test-queue-delete-quorum">>,
109+
durable = true,
110+
arguments = [{<<"x-queue-type">>, longstr, <<"quorum">>}]}),
100111
%% To be used in delete_binding
101112
#'exchange.bind_ok'{} = amqp_channel:call(Ch, #'exchange.bind'{destination = <<"amq.fanout">>,
102113
source = <<"amq.direct">>,
@@ -188,6 +199,22 @@ declare_queue(Config) ->
188199
?assertExit({{shutdown, {connection_closing, {server_initiated_close, 541, _}}}, _},
189200
amqp_channel:call(Ch, #'queue.declare'{queue = <<"test-queue-2">>})).
190201

202+
delete_queue(Config) ->
203+
[A | _] = rabbit_ct_broker_helpers:get_node_configs(Config, nodename),
204+
Conn1 = rabbit_ct_client_helpers:open_unmanaged_connection(Config, A),
205+
{ok, Ch1} = amqp_connection:open_channel(Conn1),
206+
?assertExit({{shutdown, {connection_closing, {server_initiated_close, 541, _}}}, _},
207+
amqp_channel:call(Ch1, #'queue.delete'{queue = <<"test-queue-delete-classic">>})),
208+
Conn2 = rabbit_ct_client_helpers:open_unmanaged_connection(Config, A),
209+
{ok, Ch2} = amqp_connection:open_channel(Conn2),
210+
?assertExit({{shutdown, {connection_closing, {server_initiated_close, 541, _}}}, _},
211+
amqp_channel:call(Ch2, #'queue.delete'{queue = <<"test-queue-delete-stream">>})),
212+
Conn3 = rabbit_ct_client_helpers:open_unmanaged_connection(Config, A),
213+
{ok, Ch3} = amqp_connection:open_channel(Conn3),
214+
?assertExit({{shutdown, {connection_closing, {server_initiated_close, 541, _}}}, _},
215+
amqp_channel:call(Ch3, #'queue.delete'{queue = <<"test-queue-delete-quorum">>})),
216+
ok.
217+
191218
publish_to_exchange(Config) ->
192219
[A | _] = rabbit_ct_broker_helpers:get_node_configs(Config, nodename),
193220
{_, Ch} = rabbit_ct_client_helpers:open_connection_and_channel(Config, A),

0 commit comments

Comments
 (0)