dongnuo123 commented on code in PR #17886:
URL: https://github.com/apache/kafka/pull/17886#discussion_r1868454445
##########
server-common/src/main/java/org/apache/kafka/server/common/Features.java:
##########
@@ -177,4 +223,92 @@ public static Features featureFromName(String featureName)
{
public static Map<String, Short> featureImplsToMap(List<FeatureVersion>
features) {
return
features.stream().collect(Collectors.toMap(FeatureVersion::featureName,
FeatureVersion::featureLevel));
}
+
+ public boolean isProductionReady(short featureVersion) {
+ return featureVersion <= latestProduction();
+ }
+
+ public boolean hasFeatureVersion(FeatureVersion featureVersion) {
+ for (FeatureVersion v : featureVersions()) {
+ if (v == featureVersion) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * The method ensures that the following statements are met:
+ * 1. The latest production value is one of the feature values.
+ * 2. The latest production value >= the default value.
+ * 3. The dependencies of the latest production value <= their latest
production values.
+ * 4. The dependencies of the default value <= their default values.
+ *
+ * Suppose we have feature X as the feature being validated.
+ * Invalid examples:
+ * - The feature X has default version = XV_10 (dependency = {}),
latest production = XV_5 (dependency = {})
+ * (Violating rule 2. The latest production value XV_5 is smaller
than the default value)
+ * - The feature X has default version = XV_10 (dependency = {Y:
YV_3}), latest production = XV_11 (dependency = {Y: YV_4})
+ * The feature Y has default version = YV_3 (dependency = {}),
latest production = YV_3 (dependency = {})
+ * (Violating rule 3. For latest production XV_11, Y's latest
production YV_3 is smaller than the dependency value YV_4)
+ * - The feature X has default version = XV_10 (dependency = {Y:
YV_4}), latest production = XV_11 (dependency = {Y: YV_4})
+ * The feature Y has default version = YV_3 (dependency = {}),
latest production = YV_4 (dependency = {})
+ * (Violating rule 4. For default version XV_10, Y's default value
YV_3 is smaller than the dependency value YV_4)
+ * Valid examples:
+ * - The feature X has default version = XV_10 (dependency = {}),
latest production = XV_10 (dependency = {})
+ * - The feature X has default version = XV_10 (dependency = {Y:
YV_3}), latest production = XV_11 (dependency = {Y: YV_4})
+ * The feature Y has default version = YV_3 (dependency = {}),
latest production = YV_4 (dependency = {})
+ * - The feature X has default version = latest production = XV_10
(dependency = {MetadataVersion: IBP_4_0_IV0})
+ * (Some features can depend on MetadataVersion, which is not
checked in this method)
+ *
+ * @param features the feature to validate.
+ * @return true if the feature is valid, false otherwise.
+ * @throws IllegalArgumentException if the feature violates any of the
rules thus is not valid.
+ */
+ public static void validateDefaultValueAndLatestProductionValue(
+ Features features
+ ) throws IllegalArgumentException {
+ FeatureVersion defaultVersion =
features.defaultVersion(MetadataVersion.LATEST_PRODUCTION);
+ FeatureVersion latestProduction = features.latestProduction;
+
+ if (!features.hasFeatureVersion(latestProduction)) {
+ throw new IllegalArgumentException(String.format("Feature %s has
latest production version %s=%s " +
+ "which is not one of its feature versions.",
+ features.name(), latestProduction.featureName(),
latestProduction.featureLevel()));
+ }
+
+ if (latestProduction.featureLevel() < defaultVersion.featureLevel()) {
+ throw new IllegalArgumentException(String.format("Feature %s has
latest production value %s " +
+ "smaller than its default value %s.",
+ features.name(), latestProduction.featureLevel(),
defaultVersion.featureLevel()));
+ }
+
+ for (Map.Entry<String, Short> dependency:
latestProduction.dependencies().entrySet()) {
+ String dependencyFeatureName = dependency.getKey();
+ // There might be dependency on MetadataVersion which is not a
feature, so we skip checking it.
+ if (!dependencyFeatureName.equals(MetadataVersion.FEATURE_NAME)) {
+ Features dependencyFeature =
featureFromName(dependencyFeatureName);
+ if
(!dependencyFeature.isProductionReady(dependency.getValue())) {
+ throw new IllegalArgumentException(String.format("Latest
production FeatureVersion %s=%s " +
+ "has a dependency %s=%s that is not production
ready. (%s latest production: %s)",
+ features.name(), latestProduction.featureLevel(),
dependencyFeature.name(), dependency.getValue(),
+ dependencyFeature.name(),
dependencyFeature.latestProduction()));
+ }
+ }
+ }
+
+ for (Map.Entry<String, Short> dependency:
defaultVersion.dependencies().entrySet()) {
Review Comment:
I guess it doesn't hurt to check MVs that are larger than
`MetadataVersion.LATEST_PRODUCTION`?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]