MINOR: Several fixes and improvements for FeatureControlManager#12207
MINOR: Several fixes and improvements for FeatureControlManager#12207cmccabe merged 8 commits intoapache:trunkfrom
Conversation
This PR fixes a bug where FeatureControlManager#replay(FeatureLevelRecord) was throwing an exception if not all controllers in the quorum supported the feature being applied. While we do want to validate this, it needs to be validated earlier, before the record is committed to the log. Once the record has been committed to the log it should always be applied if the current controller supports it. Fix another bug where removing a feature was not supported once it had been configured. Note that because we reserve feature level 0 for "feature not enabled", we don't need to use Optional<VersionRange>; we can just return a range of 0-0 when the feature is not supported. Allow the metadata version to be downgraded when UpgradeType.UNSAFE_DOWNGRADE has been set. Previously we were unconditionally denying this even when this was set. Add a builder for FeatureControlManager, so that we can easily add new parameters to the constructor in the future. This will also be useful for creating FeatureControlManagers that are initialized to a specific MetadataVersion.
5d9960f to
ed44532
Compare
| } | ||
|
|
||
| public void replay(FeatureLevelRecord record) { | ||
| if (!canSupportVersion(record.name(), record.featureLevel())) { |
There was a problem hiding this comment.
This made me wonder about bootstrapping and if we could load in an unknown version. However, looking at BootstrapMetadata#load, we will parse the feature level as a MetadataVersion before returning so we would throw an exception as we read the bootstrap records into memory. This could happen if someone generates a bootstrap snapshot at version N and then tries to load it into a cluster at N-1
There was a problem hiding this comment.
Yeah.
It's fine to do a sanity check based on local supported versions. Pulling in the quorum is where it is incorrect (which might be an argument for pulling localSupportedFeatures out of QuorumFeatures, but one step at a time.)
| } | ||
| } | ||
|
|
||
| ControllerResult<Map<String, ApiError>> initializeMetadataVersion(short initVersion) { |
There was a problem hiding this comment.
Yea, this was leftover from a previous iteration on the bootstrapping logic where the controller was just getting the initial metadata version.
| return invalidMetadataVersion(newVersionLevel, "The quorum does not support metadata.version."); | ||
| } | ||
|
|
||
| if (newVersionLevel <= 0) { |
There was a problem hiding this comment.
Should we allow a metadata.version of zero? Seems like it might complicate things to support a non-present metadata.version at runtime. Would that mean we need to revert back to reading the IBP from config?
There was a problem hiding this comment.
I was thinking about this too.
I would like to get rid of MetadataVersion.UNINITIALIZED as a concept. There are a few places where the MV isn't stored and it should be (pre-3.3 snapshots, for example) but we can just treat those as MetadataVersion.3_0_0IV1
That would allow us to just say that MV for a kraft cluster was always > 0
But this PR was already getting too big so I held off on that.
| * @param level The feature level. | ||
| * @return The reason why the feature level is not supported, or Optional.empty if it is supported. | ||
| */ | ||
| public Optional<String> reasonNotSupported(String featureName, short level) { |
There was a problem hiding this comment.
The name sort of seems like we're expecting it not to be supported. Maybe call it something like checkIfQuorumSupported? I think it would be good to include "quorum" in here to avoid confusion with the "local" compatibility check
There was a problem hiding this comment.
the problem with "check" or "validate" is that it sort of implies that we throw an exception if the validation fails, whereas this returns a reason string.
I liked avoiding exceptions here since it avoids messing with questions like what is the exception type and how do you pull out the string (which is what you really want)
| FeatureControlManager manager = new FeatureControlManager.Builder(). | ||
| build(); | ||
| manager.updateFeatures(Collections.singletonMap("foo", | ||
| Map<String, FeatureUpdate.UpgradeType> upgradeTypes, |
|
@cmccabe changes look good. Looks like there is a compile error in FeatureControlManagerTest |
|
One thing I did just now was get rid of RemoveFeatureLevelRecord since it’s redundant. We can just set level = 0 to remove a feature level I also fixed it so that we support this case fully. In particular 0 is handled just like any other level — if there are brokers that don’t support level 0, you can’t turn it off. I don't think we'll have any such features any time soon, but this is conceptually simple and will help in the future |
mumrah
left a comment
There was a problem hiding this comment.
Removing RemoveFeatureLevelRecord seems fine, I guess we haven't really had any code to produce that record yet so no possibility of deserialization issues.
One minor thing inline, besides that LGTM 👍
| } | ||
|
|
||
| if (newVersion <= 0) { | ||
| if (newVersion < 0) { |
There was a problem hiding this comment.
The error message below should be updated.
This PR fixes a bug where FeatureControlManager#replay(FeatureLevelRecord) was throwing an
exception if not all controllers in the quorum supported the feature being applied. While we do
want to validate this, it needs to be validated earlier, before the record is committed to the log.
Once the record has been committed to the log it should always be applied if the current controller
supports it.
Fix another bug where removing a feature was not supported once it had been configured. Note that
because we reserve feature level 0 for "feature not enabled", we don't need to use
Optional; we can just return a range of 0-0 when the feature is not supported.
In error messages, give more detail about what the problem is when a controller in the quorum cannot
handle a new version. For example, "Local controller 0 does not support this feature" rather than just
"quorum does not support this feature".
Allow the metadata version to be downgraded when UpgradeType.UNSAFE_DOWNGRADE has been set.
Previously we were unconditionally denying this even when this was set.
Add a builder for FeatureControlManager, so that we can easily add new parameters to the
constructor in the future. This will also be useful for creating FeatureControlManagers that are
initialized to a specific MetadataVersion.