106
106
get_state /1 ,
107
107
get_stability /1 ,
108
108
get_require_level /1 ,
109
+ get_experiment_level /1 ,
109
110
check_node_compatibility /1 , check_node_compatibility /2 ,
110
111
sync_feature_flags_with_cluster /2 ,
111
112
refresh_feature_flags_after_app_load /0 ,
149
150
doc_url => string (),
150
151
stability => stability (),
151
152
require_level => require_level (),
153
+ experiment_level => experiment_level (),
152
154
depends_on => [feature_name ()],
153
155
callbacks =>
154
156
#{callback_name () => callback_fun_name ()}}.
186
188
doc_url => string (),
187
189
stability => stability (),
188
190
require_level => require_level (),
191
+ experiment_level => experiment_level (),
189
192
depends_on => [feature_name ()],
190
193
callbacks =>
191
194
#{callback_name () => callback_fun_name ()},
219
222
% % A soft required feature flag will be automatically enabled when a RabbitMQ
220
223
% % node is upgraded to a version where it is required.
221
224
225
+ -type experiment_level () :: unsupported | supported .
226
+ % % The level of support of an experimental feature flag.
227
+ % %
228
+ % % At first, an experimental feature flag is offered to give a chance to users
229
+ % % to try it and give feedback as part of the design and development of the
230
+ % % feature. At this stage, it is unsupported: it must not be enabled in a
231
+ % % production environment and upgrade to a later version of RabbitMQ while
232
+ % % this experimental feature flag is enabled is not supported.
233
+ % %
234
+ % % Then, the experimental feature flag becomes supported. At this point, it is
235
+ % % stable enough that upgrading is guarantied and help will be provided.
236
+ % % However it is not mature enough to be marked as stable (which would make it
237
+ % % enabled by default in a new deployment or when running `rabbitmqctl
238
+ % % enable_feature_flag all'.
239
+ % %
240
+ % % The next step is to change its stability to `stable'. Once done, the
241
+ % % `experiment_level()' field is irrelevant.
242
+
222
243
-type callback_fun_name () :: {Module :: module (), Function :: atom ()}.
223
244
% % The name of the module and function to call when changing the state of
224
245
% % the feature flag.
327
348
feature_state / 0 ,
328
349
feature_states / 0 ,
329
350
stability / 0 ,
351
+ require_level / 0 ,
352
+ experiment_level / 0 ,
330
353
callback_fun_name / 0 ,
331
354
callbacks / 0 ,
332
355
callback_name / 0 ,
@@ -696,30 +719,38 @@ info() ->
696
719
info (Options ) when is_map (Options ) ->
697
720
rabbit_ff_extra :info (Options ).
698
721
699
- - spec get_state (feature_name ()) -> enabled | disabled | unavailable .
722
+ - spec get_state (feature_name ()) -> enabled |
723
+ state_changing |
724
+ disabled |
725
+ unavailable .
700
726
% % @doc
701
727
% % Returns the state of a feature flag.
702
728
% %
703
729
% % The possible states are:
704
730
% % <ul>
705
731
% % <li>`enabled': the feature flag is enabled.</li>
732
+ % % <li>`state_changing': the feature flag is being enabled.</li>
706
733
% % <li>`disabled': the feature flag is supported by all nodes in the
707
734
% % cluster but currently disabled.</li>
708
735
% % <li>`unavailable': the feature flag is unsupported by at least one
709
736
% % node in the cluster and can not be enabled for now.</li>
710
737
% % </ul>
711
738
% %
712
739
% % @param FeatureName The name of the feature flag to check.
713
- % % @returns `enabled', `disabled' or `unavailable'.
740
+ % % @returns `enabled', `state_changing', ` disabled' or `unavailable'.
714
741
715
742
get_state (FeatureName ) when is_atom (FeatureName ) ->
716
- IsEnabled = is_enabled (FeatureName ),
743
+ IsEnabled = is_enabled (FeatureName , non_blocking ),
717
744
case IsEnabled of
718
- true -> enabled ;
719
- false -> case is_supported (FeatureName ) of
720
- true -> disabled ;
721
- false -> unavailable
722
- end
745
+ true ->
746
+ enabled ;
747
+ state_changing ->
748
+ state_changing ;
749
+ false ->
750
+ case is_supported (FeatureName ) of
751
+ true -> disabled ;
752
+ false -> unavailable
753
+ end
723
754
end .
724
755
725
756
- spec get_stability
@@ -809,6 +840,45 @@ get_require_level(FeatureProps) when ?IS_DEPRECATION(FeatureProps) ->
809
840
_ -> none
810
841
end .
811
842
843
+ - spec get_experiment_level
844
+ (FeatureName ) -> ExperimentLevel | undefined when
845
+ FeatureName :: feature_name (),
846
+ ExperimentLevel :: experiment_level () | none ;
847
+ (FeatureProps ) -> ExperimentLevel when
848
+ FeatureProps ::
849
+ feature_props_extended () |
850
+ rabbit_deprecated_features :feature_props_extended (),
851
+ ExperimentLevel :: experiment_level () | none .
852
+ % % @doc
853
+ % % Returns the experimental level of an experimental feature flag.
854
+ % %
855
+ % % The possible experiment levels are:
856
+ % % <ul>
857
+ % % <li>`unsupported': the experimental feature flag must not be enabled in
858
+ % % production and upgrades with it enabled is unsupported.</li>
859
+ % % <li>`supported': the experimental feature flag is not yet stable enough but
860
+ % % upgrades are guarantied to be possible. This is returned too if the
861
+ % % feature flag is stable or required.</li>
862
+ % % </ul>
863
+ % %
864
+ % % @param FeatureName The name of the feature flag to check.
865
+ % % @param FeatureProps A feature flag properties map.
866
+ % % @returns `unsupported', `supported', or `undefined' if the given feature
867
+ % % flag name doesn't correspond to a known feature flag.
868
+
869
+ get_experiment_level (FeatureName ) when is_atom (FeatureName ) ->
870
+ case rabbit_ff_registry_wrapper :get (FeatureName ) of
871
+ undefined -> undefined ;
872
+ FeatureProps -> get_experiment_level (FeatureProps )
873
+ end ;
874
+ get_experiment_level (FeatureProps ) when ? IS_FEATURE_FLAG (FeatureProps ) ->
875
+ case get_stability (FeatureProps ) of
876
+ experimental -> maps :get (experiment_level , FeatureProps , unsupported );
877
+ _ -> supported
878
+ end ;
879
+ get_experiment_level (FeatureProps ) when ? IS_DEPRECATION (FeatureProps ) ->
880
+ supported .
881
+
812
882
% % -------------------------------------------------------------------
813
883
% % Feature flags registry.
814
884
% % -------------------------------------------------------------------
@@ -968,6 +1038,7 @@ assert_feature_flag_is_valid(FeatureName, FeatureProps) ->
968
1038
doc_url ,
969
1039
stability ,
970
1040
require_level ,
1041
+ experiment_level ,
971
1042
depends_on ,
972
1043
callbacks ],
973
1044
? assertEqual ([], maps :keys (FeatureProps ) -- ValidProps ),
@@ -979,6 +1050,17 @@ assert_feature_flag_is_valid(FeatureName, FeatureProps) ->
979
1050
? assert (Stability =:= stable orelse
980
1051
Stability =:= experimental orelse
981
1052
Stability =:= required ),
1053
+ ? assert (Stability =:= experimental orelse
1054
+ not maps :is_key (experiment_level , FeatureProps )),
1055
+ ? assert (Stability =:= required orelse
1056
+ not maps :is_key (require_level , FeatureProps )),
1057
+ RequireLevel = maps :get (require_level , FeatureProps , soft ),
1058
+ ? assert (RequireLevel =:= hard orelse RequireLevel =:= soft ),
1059
+ ExperimentLevel = maps :get (
1060
+ experiment_level , FeatureProps ,
1061
+ unsupported ),
1062
+ ? assert (ExperimentLevel =:= unsupported orelse
1063
+ ExperimentLevel =:= supported ),
982
1064
? assertNot (maps :is_key (migration_fun , FeatureProps )),
983
1065
? assertNot (maps :is_key (warning , FeatureProps )),
984
1066
case FeatureProps of
0 commit comments