Skip to content

Commit 3325def

Browse files
committed
rabbit_feature_flags: Take callback definition from correct node
[Why] The feature flag controller that is responsible for enabling a feature flag may be on a node that doesn't know this feature flag. This is supported by there is a bug when it queries the callback definition for that feature flag: it uses its own registry which does not have anything about this feature flag. This leads to a crash because the `run_callback/5` funtion tries to use the `undefined` atom returned by the registry as a map: crasher: initial call: rabbit_ff_controller:init/1 pid: <0.374.0> registered_name: rabbit_ff_controller exception error: bad map: undefined in function rabbit_ff_controller:run_callback/5 in call from rabbit_ff_controller:do_enable/3 (rabbit_ff_controller.erl, line 1244) in call from rabbit_ff_controller:update_feature_state_and_enable/2 (rabbit_ff_controller.erl, line 1180) in call from rabbit_ff_controller:enable_with_registry_locked/2 (rabbit_ff_controller.erl, line 1050) in call from rabbit_ff_controller:enable_many_locked/2 (rabbit_ff_controller.erl, line 991) in call from rabbit_ff_controller:enable_many/2 (rabbit_ff_controller.erl, line 979) in call from rabbit_ff_controller:updating_feature_flag_states/3 (rabbit_ff_controller.erl, line 307) in call from gen_statem:loop_state_callback/11 (gen_statem.erl, line 3735) [How] The callback definition is now queried from the first node in the list given as argument. For the common use case where all nodes know about a feature flag, the first node is the local one, so there should be no latency caused by the RPC. See #12963.
1 parent d8ca61c commit 3325def

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

deps/rabbit/src/rabbit_ff_controller.erl

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1840,8 +1840,13 @@ enable_dependencies1(
18401840
rabbit_deprecated_features:is_feature_used_callback_ret() |
18411841
run_callback_error()}.
18421842

1843-
run_callback(Nodes, FeatureName, Command, Extra, Timeout) ->
1844-
FeatureProps = rabbit_ff_registry_wrapper:get(FeatureName),
1843+
run_callback([FirstNode | _] = Nodes, FeatureName, Command, Extra, Timeout) ->
1844+
%% We need to take the callback definition from a node in the `Nodes' list
1845+
%% because the local node may not know this feature flag and thus does not
1846+
%% have the callback definition.
1847+
FeatureProps = erpc:call(
1848+
FirstNode,
1849+
rabbit_ff_registry_wrapper, get, [FeatureName]),
18451850
Callbacks = maps:get(callbacks, FeatureProps, #{}),
18461851
case Callbacks of
18471852
#{Command := {CallbackMod, CallbackFun}}

deps/rabbit/test/feature_flags_SUITE.erl

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@
4545
clustering_ok_with_new_ff_enabled_from_plugin_on_some_nodes/1,
4646
clustering_ok_with_supported_required_ff/1,
4747
activating_plugin_with_new_ff_disabled/1,
48-
activating_plugin_with_new_ff_enabled/1
48+
activating_plugin_with_new_ff_enabled/1,
49+
enable_plugin_feature_flag_after_deactivating_plugin/1
4950
]).
5051

5152
suite() ->
@@ -95,7 +96,8 @@ groups() ->
9596
{activating_plugin, [],
9697
[
9798
activating_plugin_with_new_ff_disabled,
98-
activating_plugin_with_new_ff_enabled
99+
activating_plugin_with_new_ff_enabled,
100+
enable_plugin_feature_flag_after_deactivating_plugin
99101
]}
100102
],
101103

@@ -1260,6 +1262,36 @@ activating_plugin_with_new_ff_enabled(Config) ->
12601262
end,
12611263
ok.
12621264

1265+
enable_plugin_feature_flag_after_deactivating_plugin(Config) ->
1266+
FFSubsysOk = is_feature_flag_subsystem_available(Config),
1267+
1268+
log_feature_flags_of_all_nodes(Config),
1269+
case FFSubsysOk of
1270+
true ->
1271+
?assertEqual([false, false],
1272+
is_feature_flag_supported(Config, plugin_ff)),
1273+
?assertEqual([false, false],
1274+
is_feature_flag_enabled(Config, plugin_ff));
1275+
false ->
1276+
ok
1277+
end,
1278+
1279+
rabbit_ct_broker_helpers:enable_plugin(Config, 1, "my_plugin"),
1280+
rabbit_ct_broker_helpers:disable_plugin(Config, 1, "my_plugin"),
1281+
1282+
log_feature_flags_of_all_nodes(Config),
1283+
case FFSubsysOk of
1284+
true ->
1285+
enable_feature_flag_on(Config, 0, plugin_ff),
1286+
?assertEqual([true, true],
1287+
is_feature_flag_supported(Config, plugin_ff)),
1288+
?assertEqual([false, true],
1289+
is_feature_flag_enabled(Config, plugin_ff));
1290+
false ->
1291+
ok
1292+
end,
1293+
ok.
1294+
12631295
%% -------------------------------------------------------------------
12641296
%% Internal helpers.
12651297
%% -------------------------------------------------------------------

0 commit comments

Comments
 (0)