Skip to content

Commit 0784b02

Browse files
Merge pull request #7282 from rabbitmq/mergify/bp/v3.11.x/pr-7280
rabbit_vhost:set_tags/2 avoids notifying if tags are unchanged (backport #7280)
2 parents 4edae6f + 81fbaba commit 0784b02

File tree

5 files changed

+105
-7
lines changed

5 files changed

+105
-7
lines changed

deps/rabbit/BUILD.bazel

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,6 +1046,9 @@ rabbitmq_integration_suite(
10461046
name = "vhost_SUITE",
10471047
size = "medium",
10481048
flaky = True,
1049+
additional_srcs = [
1050+
"test/test_rabbit_event_handler.erl",
1051+
],
10491052
)
10501053

10511054
rabbitmq_suite(

deps/rabbit/src/rabbit_vhost.erl

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -566,17 +566,38 @@ update_metadata(VHostName, Fun) ->
566566
vhost:set_metadata(Record, Meta)
567567
end).
568568

569-
-spec update_tags(vhost:name(), [vhost_tag()], rabbit_types:username()) -> vhost:vhost() | rabbit_types:ok_or_error(any()).
569+
are_different0([], []) ->
570+
false;
571+
are_different0([], [_ | _]) ->
572+
true;
573+
are_different0([_ | _], []) ->
574+
true;
575+
are_different0([E], [E]) ->
576+
false;
577+
are_different0([E | R1], [E | R2]) ->
578+
are_different0(R1, R2);
579+
are_different0(_, _) ->
580+
true.
581+
582+
are_different(L1, L2) ->
583+
are_different0(lists:usort(L1), lists:usort(L2)).
584+
585+
-spec update_tags(vhost:name(), [vhost_tag()], rabbit_types:username()) -> vhost:vhost().
570586
update_tags(VHostName, Tags, ActingUser) ->
571-
ConvertedTags = [rabbit_data_coercion:to_atom(I) || I <- Tags],
587+
CurrentTags = case mnesia:dirty_read({rabbit_vhost, VHostName}) of
588+
[V] when ?is_vhost(V) -> vhost:get_tags(V);
589+
[] -> []
590+
end,
591+
ConvertedTags = lists:usort([rabbit_data_coercion:to_atom(I) || I <- Tags]),
572592
try
573593
R = rabbit_misc:execute_mnesia_transaction(fun() ->
574594
update_tags(VHostName, ConvertedTags)
575595
end),
576596
rabbit_log:info("Successfully set tags for virtual host '~ts' to ~tp", [VHostName, ConvertedTags]),
577-
rabbit_event:notify(vhost_tags_set, [{name, VHostName},
578-
{tags, ConvertedTags},
579-
{user_who_performed_action, ActingUser}]),
597+
rabbit_event:notify_if(are_different(CurrentTags, ConvertedTags),
598+
vhost_tags_set, [{name, VHostName},
599+
{tags, ConvertedTags},
600+
{user_who_performed_action, ActingUser}]),
580601
R
581602
catch
582603
throw:{error, {no_such_vhost, _}} = Error ->
@@ -592,7 +613,7 @@ update_tags(VHostName, Tags, ActingUser) ->
592613

593614
-spec update_tags(vhost:name(), [vhost_tag()]) -> vhost:vhost() | rabbit_types:ok_or_error(any()).
594615
update_tags(VHostName, Tags) ->
595-
ConvertedTags = [rabbit_data_coercion:to_atom(I) || I <- Tags],
616+
ConvertedTags = lists:usort([rabbit_data_coercion:to_atom(I) || I <- Tags]),
596617
update(VHostName, fun(Record) ->
597618
Meta0 = vhost:get_metadata(Record),
598619
Meta = maps:put(tags, ConvertedTags, Meta0),
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
-module(test_rabbit_event_handler).
2+
3+
-behaviour(gen_event).
4+
5+
-export([okay/0]).
6+
-export([init/1, handle_call/2, handle_event/2, handle_info/2,
7+
terminate/2, code_change/3]).
8+
9+
-include_lib("rabbit_common/include/rabbit.hrl").
10+
11+
% an exported callable func, used to allow rabbit_ct_broker_helpers
12+
% to load this code when rpc'd
13+
okay() -> ok.
14+
15+
init([]) ->
16+
{ok, #{events => []}}.
17+
18+
handle_event(#event{} = Event, #{events := Events} = State) ->
19+
{ok, State#{events => [Event | Events]}};
20+
handle_event(_, State) ->
21+
{ok, State}.
22+
23+
handle_call(events, #{events := Events} = State) ->
24+
{ok, Events, State}.
25+
26+
handle_info(_Info, State) ->
27+
{ok, State}.
28+
29+
terminate(_Arg, _State) ->
30+
ok.
31+
32+
code_change(_OldVsn, State, _Extra) ->
33+
{ok, State}.

deps/rabbit/test/vhost_SUITE.erl

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ groups() ->
2828
single_node_vhost_deletion_forces_connection_closure,
2929
vhost_failure_forces_connection_closure,
3030
vhost_creation_idempotency,
31+
vhost_update_idempotency,
3132
parse_tags
3233
],
3334
ClusterSize2Tests = [
@@ -321,6 +322,46 @@ vhost_creation_idempotency(Config) ->
321322
rabbit_ct_broker_helpers:delete_vhost(Config, VHost)
322323
end.
323324

325+
vhost_update_idempotency(Config) ->
326+
VHost = <<"update-idempotency-test">>,
327+
ActingUser = <<"acting-user">>,
328+
try
329+
% load the dummy event handler on the node
330+
ok = rabbit_ct_broker_helpers:rpc(Config, 0, test_rabbit_event_handler, okay, []),
331+
332+
ok = rabbit_ct_broker_helpers:rpc(Config, 0, gen_event, add_handler,
333+
[rabbit_event, test_rabbit_event_handler, []]),
334+
335+
?assertEqual(ok, rabbit_ct_broker_helpers:add_vhost(Config, VHost)),
336+
337+
?assertMatch({vhost,VHost, _, #{tags := [private,replicate]}},
338+
rabbit_ct_broker_helpers:rpc(Config, 0,
339+
rabbit_vhost, update_tags,
340+
[VHost, [private, replicate], ActingUser])),
341+
?assertMatch({vhost,VHost, _, #{tags := [private,replicate]}},
342+
rabbit_ct_broker_helpers:rpc(Config, 0,
343+
rabbit_vhost, update_tags,
344+
[VHost, [replicate, private], ActingUser])),
345+
346+
Events = rabbit_ct_broker_helpers:rpc(Config, 0,
347+
gen_event, call,
348+
[rabbit_event, test_rabbit_event_handler, events, 100]),
349+
ct:pal(?LOW_IMPORTANCE, "Events: ~p", [lists:reverse(Events)]),
350+
TagsSetEvents = lists:filter(fun
351+
(#event{type = vhost_tags_set}) -> true;
352+
(_) -> false
353+
end, Events),
354+
?assertMatch([#event{type = vhost_tags_set,
355+
props = [{name, VHost},
356+
{tags, [private, replicate]},
357+
{user_who_performed_action, ActingUser}]}],
358+
TagsSetEvents)
359+
after
360+
rabbit_ct_broker_helpers:rpc(Config, 0,
361+
gen_event, delete_handler, [rabbit_event, test_rabbit_event_handler, []]),
362+
rabbit_ct_broker_helpers:delete_vhost(Config, VHost)
363+
end.
364+
324365
vhost_is_created_with_default_limits(Config) ->
325366
VHost = <<"vhost1">>,
326367
Limits = [{<<"max-connections">>, 10}, {<<"max-queues">>, 1}],

deps/rabbitmq_cli/test/ctl/set_vhost_tags_command_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ defmodule SetVhostTagsCommandTest do
7777
fn record -> record[:vhost] == context[:vhost] end
7878
)
7979

80-
assert result[:tags] == context[:tags]
80+
assert Enum.sort(result[:tags]) == Enum.sort(context[:tags])
8181
end
8282

8383
@tag user: @vhost, tags: [:qa]

0 commit comments

Comments
 (0)