Skip to content

Commit 50ebeb0

Browse files
committed
AZ aware placement: test for AZ outage
When AZ-aware placement is used, we should assign members to all AZs, even if there are no running nodes in a given AZ.
1 parent 19ec5f0 commit 50ebeb0

1 file changed

Lines changed: 36 additions & 0 deletions

File tree

deps/rabbit/test/unit_queue_location_SUITE.erl

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ az_aware_tests() -> [
4141
az_aware_below_threshold_balanced,
4242
az_aware_fewer_nodes_than_size,
4343
az_aware_running_nodes_preferred,
44+
az_aware_entire_az_down,
4445
az_aware_node_tags_for_nodes_offline_nodes
4546
].
4647

@@ -392,6 +393,41 @@ az_aware_running_nodes_preferred(_Config) ->
392393
?assertNot(lists:member(n2, Members)),
393394
ok = meck:unload([rabbit_member_placement_az, rabbit_queue_type]).
394395

396+
%% An entire AZ can be without any running node (e.g. an outage). Unlike the
397+
%% non-AZ-aware strategies, which simply prefer whichever nodes are running,
398+
%% AZ-aware placement must still assign a member to the down AZ (picking one
399+
%% of its stopped nodes) rather than over-allocating to the AZs that are up.
400+
%% Balance across AZs is favoured over short-term node availability.
401+
az_aware_entire_az_down(_Config) ->
402+
ok = meck:new(rabbit_member_placement_az, [passthrough]),
403+
ok = meck:expect(rabbit_member_placement_az, node_tags_for_nodes,
404+
fun([n1, n2, n3, n4, n5, n6], <<"az">>) ->
405+
#{n1 => <<"az1">>, n2 => <<"az1">>,
406+
n3 => <<"az2">>, n4 => <<"az2">>,
407+
n5 => <<"az3">>, n6 => <<"az3">>}
408+
end),
409+
ok = meck:new(rabbit_queue_type, [passthrough]),
410+
ok = meck:expect(rabbit_queue_type, get_nodes, fun({fake_queue, N}) -> [N] end),
411+
AllNodes = [n1, n2, n3, n4, n5, n6],
412+
%% Both az3 nodes are stopped: the whole AZ is unavailable.
413+
RunningNodes = [n1, n2, n3, n4],
414+
QueueType = rabbit_quorum_queue,
415+
GetQueues = fun() -> [] end,
416+
QueueCount = 0,
417+
QueueCountStartRandom = 1000,
418+
{Members, _} = rabbit_queue_location:select_members(3, QueueType, AllNodes, RunningNodes,
419+
QueueCount, QueueCountStartRandom,
420+
GetQueues, <<"az">>),
421+
?assertEqual(3, length(Members)),
422+
AZMap = #{n1 => <<"az1">>, n2 => <<"az1">>,
423+
n3 => <<"az2">>, n4 => <<"az2">>,
424+
n5 => <<"az3">>, n6 => <<"az3">>},
425+
AZsUsed = lists:sort(lists:uniq([maps:get(N, AZMap) || N <- Members])),
426+
%% az3 must still be represented even though none of its nodes are running.
427+
?assertEqual([<<"az1">>, <<"az2">>, <<"az3">>], AZsUsed),
428+
?assert(lists:member(n5, Members) orelse lists:member(n6, Members)),
429+
ok = meck:unload([rabbit_member_placement_az, rabbit_queue_type]).
430+
395431
az_aware_node_tags_for_nodes_offline_nodes(_Config) ->
396432
ok = meck:new(rabbit_db_node_metadata, [passthrough]),
397433
ok = meck:expect(rabbit_db_node_metadata, get,

0 commit comments

Comments
 (0)