Skip to content

Commit 5f79dec

Browse files
authored
Merge pull request #10091 from rabbitmq/rabbit-local-random-exchange
Add a new local random exchange type.
2 parents 3d10f25 + cca64e8 commit 5f79dec

File tree

6 files changed

+345
-3
lines changed

6 files changed

+345
-3
lines changed

deps/rabbit/BUILD.bazel

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,14 @@ rabbitmq_integration_suite(
10621062
],
10631063
)
10641064

1065+
rabbitmq_integration_suite(
1066+
name = "rabbit_local_random_exchange_SUITE",
1067+
size = "small",
1068+
additional_beam = [
1069+
":test_queue_utils_beam",
1070+
],
1071+
)
1072+
10651073
rabbitmq_integration_suite(
10661074
name = "rabbit_direct_reply_to_prop_SUITE",
10671075
size = "medium",

deps/rabbit/app.bzl

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ def all_beam_files(name = "all_beam_files"):
131131
"src/rabbit_exchange_type_fanout.erl",
132132
"src/rabbit_exchange_type_headers.erl",
133133
"src/rabbit_exchange_type_invalid.erl",
134+
"src/rabbit_exchange_type_local_random.erl",
134135
"src/rabbit_exchange_type_topic.erl",
135136
"src/rabbit_feature_flags.erl",
136137
"src/rabbit_ff_controller.erl",
@@ -391,6 +392,7 @@ def all_test_beam_files(name = "all_test_beam_files"):
391392
"src/rabbit_exchange_type_fanout.erl",
392393
"src/rabbit_exchange_type_headers.erl",
393394
"src/rabbit_exchange_type_invalid.erl",
395+
"src/rabbit_exchange_type_local_random.erl",
394396
"src/rabbit_exchange_type_topic.erl",
395397
"src/rabbit_feature_flags.erl",
396398
"src/rabbit_ff_controller.erl",
@@ -670,6 +672,7 @@ def all_srcs(name = "all_srcs"):
670672
"src/rabbit_exchange_type_fanout.erl",
671673
"src/rabbit_exchange_type_headers.erl",
672674
"src/rabbit_exchange_type_invalid.erl",
675+
"src/rabbit_exchange_type_local_random.erl",
673676
"src/rabbit_exchange_type_topic.erl",
674677
"src/rabbit_feature_flags.erl",
675678
"src/rabbit_ff_controller.erl",
@@ -2048,7 +2051,6 @@ def test_suite_beam_files(name = "test_suite_beam_files"):
20482051
erlc_opts = "//:test_erlc_opts",
20492052
deps = ["//deps/amqp_client:erlang_app"],
20502053
)
2051-
20522054
erlang_bytecode(
20532055
name = "test_event_recorder_beam",
20542056
testonly = True,
@@ -2129,3 +2131,12 @@ def test_suite_beam_files(name = "test_suite_beam_files"):
21292131
erlc_opts = "//:test_erlc_opts",
21302132
deps = ["//deps/amqp_client:erlang_app"],
21312133
)
2134+
erlang_bytecode(
2135+
name = "rabbit_local_random_exchange_SUITE_beam_files",
2136+
testonly = True,
2137+
srcs = ["test/rabbit_local_random_exchange_SUITE.erl"],
2138+
outs = ["test/rabbit_local_random_exchange_SUITE.beam"],
2139+
app_name = "rabbit",
2140+
erlc_opts = "//:test_erlc_opts",
2141+
deps = ["//deps/amqp_client:erlang_app"],
2142+
)
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
%% This Source Code Form is subject to the terms of the Mozilla Public
2+
%% License, v. 2.0. If a copy of the MPL was not distributed with this
3+
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
%%
5+
%% Copyright (c) 2007-2023 VMware, Inc. or its affiliates. All rights reserved.
6+
%%
7+
8+
-module(rabbit_exchange_type_local_random).
9+
-behaviour(rabbit_exchange_type).
10+
-include_lib("rabbit_common/include/rabbit.hrl").
11+
12+
-rabbit_feature_flag({?MODULE,
13+
#{desc => "Local random exchange",
14+
stability => stable
15+
}}).
16+
17+
-rabbit_boot_step({?MODULE,
18+
[{description, "exchange type local random"},
19+
{mfa, {rabbit_registry, register,
20+
[exchange, <<"x-local-random">>, ?MODULE]}},
21+
{requires, rabbit_registry},
22+
{enables, kernel_ready}
23+
]}).
24+
25+
-export([add_binding/3,
26+
assert_args_equivalence/2,
27+
create/2,
28+
delete/2,
29+
policy_changed/2,
30+
description/0,
31+
recover/2,
32+
remove_bindings/3,
33+
validate_binding/2,
34+
route/3,
35+
serialise_events/0,
36+
validate/1,
37+
info/1,
38+
info/2
39+
]).
40+
41+
description() ->
42+
[{name, <<"x-local-random">>},
43+
{description, <<"Picks one random local binding (queue) to route via (to).">>}].
44+
45+
route(#exchange{name = Name}, _Msg, _Opts) ->
46+
Matches = rabbit_router:match_routing_key(Name, [<<>>]),
47+
case lists:filter(fun filter_local_queue/1, Matches) of
48+
[] ->
49+
[];
50+
[_] = One ->
51+
One;
52+
LocalMatches ->
53+
Rand = rand:uniform(length(LocalMatches)),
54+
[lists:nth(Rand, LocalMatches)]
55+
end.
56+
57+
info(_X) -> [].
58+
info(_X, _) -> [].
59+
serialise_events() -> false.
60+
validate(_X) ->
61+
case rabbit_feature_flags:is_enabled(?MODULE) of
62+
true ->
63+
ok;
64+
false ->
65+
rabbit_misc:amqp_error(
66+
precondition_failed,
67+
"x-local-random exchange feature not available", [],
68+
'exchange.declare')
69+
end.
70+
71+
create(_Serial, _X) -> ok.
72+
recover(_X, _Bs) -> ok.
73+
delete(_Serial, _X) -> ok.
74+
policy_changed(_X1, _X2) -> ok.
75+
add_binding(_Serial, _X, _B) -> ok.
76+
remove_bindings(_Serial, _X, _Bs) -> ok.
77+
78+
validate_binding(_X, #binding{destination = Dest,
79+
key = <<>>}) ->
80+
case rabbit_amqqueue:lookup(Dest) of
81+
{ok, Q} ->
82+
case amqqueue:get_type(Q) of
83+
rabbit_classic_queue ->
84+
ok;
85+
Type ->
86+
{error, {binding_invalid,
87+
"Queue type ~ts not valid for this exchange type",
88+
[Type]}}
89+
end;
90+
_ ->
91+
{error, {binding_invalid,
92+
"Destination not found",
93+
[]}}
94+
end;
95+
validate_binding(_X, #binding{key = BKey}) ->
96+
{error, {binding_invalid,
97+
"Non empty binding '~s' key not permitted",
98+
[BKey]}}.
99+
100+
assert_args_equivalence(X, Args) ->
101+
rabbit_exchange:assert_args_equivalence(X, Args).
102+
103+
filter_local_queue(QName) ->
104+
%% TODO: introduce lookup function that _only_ gets the pid
105+
case rabbit_amqqueue:lookup(QName) of
106+
{ok, Q} ->
107+
case amqqueue:get_pid(Q) of
108+
Pid when is_pid(Pid) andalso
109+
node(Pid) =:= node() ->
110+
is_process_alive(Pid);
111+
_ ->
112+
false
113+
end;
114+
_ ->
115+
false
116+
end.

deps/rabbit/test/quorum_queue_SUITE.erl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,8 @@ init_per_group(Group, Config) ->
225225
Config1 = rabbit_ct_helpers:set_config(Config,
226226
[{rmq_nodes_count, ClusterSize},
227227
{rmq_nodename_suffix, Group},
228-
{tcp_ports_base}]),
228+
{tcp_ports_base, {skip_n_nodes, ClusterSize}}
229+
]),
229230
Config1b = rabbit_ct_helpers:set_config(Config1, [{net_ticktime, 10}]),
230231
Ret = rabbit_ct_helpers:run_steps(Config1b,
231232
[fun merge_app_env/1 ] ++
@@ -263,7 +264,7 @@ init_per_testcase(Testcase, Config) when Testcase == reconnect_consumer_and_publ
263264
Config2 = rabbit_ct_helpers:set_config(Config1,
264265
[{rmq_nodes_count, 3},
265266
{rmq_nodename_suffix, Testcase},
266-
{tcp_ports_base},
267+
{tcp_ports_base, {skip_n_nodes, 3}},
267268
{queue_name, Q},
268269
{alt_queue_name, <<Q/binary, "_alt">>}
269270
]),

0 commit comments

Comments
 (0)