KAFKA-16192: Introduce transaction.version and usage of flexible records to coordinators#16183
KAFKA-16192: Introduce transaction.version and usage of flexible records to coordinators#16183jolshan merged 16 commits intoapache:trunkfrom
Conversation
| IBP_4_0_IVO(21, "4.0", "IV0", false), | ||
|
|
||
| // Introduce version 1 of the TransactionVersion feature (KIP-890). | ||
| IBP_4_0_IV1(22, "4.0", "IV1", false); |
There was a problem hiding this comment.
Do we need a separate MV version? We could bind TV to IBP_4_0_IVO. It's still in the future, so this should be ok as far as the bootstrap is concerned.
There was a problem hiding this comment.
I don't think we need it if we plan to make them both production ready at the same time
There was a problem hiding this comment.
I think for now the current plan is to release both in 4.0, we could reflect this in the code (if the plans change we could change the code accordingly).
There was a problem hiding this comment.
Sorry I misunderstood your question. I thought you were referring to the TVs being the same. I think we should keep separate from group version for now since I assume these will be released at different times. But don't feel super strongly.
| // Version 1 enables flexible transactional state records. (KIP-890) | ||
| TV_1(1, MetadataVersion.IBP_4_0_IV1, Collections.emptyMap()), |
There was a problem hiding this comment.
I wonder why we need a version to enable flexible records. Couldn't we use the version supporting it when we enable version 2? I may have missed something.
There was a problem hiding this comment.
This was a discussion I had with @cmccabe. I think the idea was that even if we want to disable transaction version, we may still want to keep our flexible records due to the compatibility reasons. I know Jeff worked on that KIP to ignore the fields, but this was an extra safeguard.
There was a problem hiding this comment.
Understood. As you said, this is not strictly necessary but it does not hurt.
| IBP_4_0_IVO(21, "4.0", "IV0", false), | ||
|
|
||
| // Introduce version 1 of the TransactionVersion feature (KIP-890). | ||
| IBP_4_0_IV1(22, "4.0", "IV1", false); |
| // generate the message for this transaction metadata | ||
| val keyBytes = TransactionLog.keyToBytes(transactionalId) | ||
| val valueBytes = TransactionLog.valueToBytes(newMetadata) | ||
| val valueBytes = TransactionLog.valueToBytes(newMetadata, usesFlexibleRecords()) |
There was a problem hiding this comment.
Should we add a test to ensure that this new logic works as expected?
There was a problem hiding this comment.
Functionally there is no difference now, so a test didn't come to my mind easily. I guess the best thing is to just look at the version of the record generated. I can add that.
| // Version 1 enables flexible transactional state records. (KIP-890) | ||
| TV_1(1, MetadataVersion.IBP_4_0_IV1, Collections.emptyMap()), |
There was a problem hiding this comment.
Understood. As you said, this is not strictly necessary but it does not hurt.
|
Ack -- I suppose so. I was hoping it would be merged by today 😅 |
|
In the meantime I will fix the test failure. Whoops. |
|
Yeehaw time to rebase |
|
I think I also need to fix the case where max version is 0 as well. 🤔 |
| // Add ELR related supports (KIP-966). | ||
| IBP_3_9_IV1(22, "3.9", "IV1", true), | ||
|
|
||
| IBP_3_9_IV2(23, "3.9", "IV2", false), |
There was a problem hiding this comment.
Could we add a comment that this is for bootstrapping TV?
There was a problem hiding this comment.
Sounds good. I also need to make a few other changes when I rebase, so be on the lookout for more soon :)
I planned to make the update where we don't send features as part of the registration/api versions if the version range is 0-0. I need to do this because Colin's fix only changes the min version. It is safe because a version range 0-0 is essentially the same as not supporting the feature. We will have it here until the MV is marked as production ready.
There was a problem hiding this comment.
I planned to make the update where we don't send features as part of the registration/api versions if the version range is 0-0.
Is that for the old versions of the requests or both the old and the latest version?
There was a problem hiding this comment.
I think we can just do it regardless of the version of the request. I was planning to do it in Quorum/BrokerFeatures files, which would just be the controller/broker's own view of supported features. Alternatively I can do it in the request.
cc: @cmccabe
There was a problem hiding this comment.
Looks like Colin already pushed this as part of the kraft.version PR. I will just resolve the conflicts and update the comment you mention.
There was a problem hiding this comment.
Should we add a new MV just for bootstrapping a new feature or just piggyback on an existing one (e.g., IBP_3_9_IV1)?
I planned to make the update where we don't send features as part of the registration/api versions if the version range is 0-0.
Colin's PR only skipped a finalized version 0 feature in ApiResponse. Do you plan to do that for supported features for registration/api? Range 0-0 can now happen since some of the v1 features are not stable yet.
There was a problem hiding this comment.
Hmmm-- I thought Colin's PR would cover what I need to cover since I didn't think his MV was stable yet either
There was a problem hiding this comment.
I've updated the PR to include the change for broker registration
| // Add ELR related supports (KIP-966). | ||
| IBP_3_9_IV1(22, "3.9", "IV1", true), | ||
|
|
||
| IBP_3_9_IV2(23, "3.9", "IV2", false), |
There was a problem hiding this comment.
Should we add a new MV just for bootstrapping a new feature or just piggyback on an existing one (e.g., IBP_3_9_IV1)?
I planned to make the update where we don't send features as part of the registration/api versions if the version range is 0-0.
Colin's PR only skipped a finalized version 0 feature in ApiResponse. Do you plan to do that for supported features for registration/api? Range 0-0 can now happen since some of the v1 features are not stable yet.
|
Will look at the apiversions test failures 👍 |
| _supportedFeatures.asScala.foreach { | ||
| case (name, range) => features.add(new BrokerRegistrationRequestData.Feature(). | ||
| // Do not include features with the range 0-0. | ||
| case (name, range) if range.max() > 0 => features.add(new BrokerRegistrationRequestData.Feature(). |
There was a problem hiding this comment.
We should do the same for supported features in ApiVersionResponse in the following code in BrokerFeatures, right? Also, to avoid duplicating the code, perhaps it's better to do the filtering logic in BrokerFeatures?
def defaultSupportedFeatures(unstableFeatureVersionsEnabled: Boolean): Features[SupportedVersionRange] = {
val features = new util.HashMap[String, SupportedVersionRange]()
features.put(MetadataVersion.FEATURE_NAME,
new SupportedVersionRange(
MetadataVersion.MINIMUM_KRAFT_VERSION.featureLevel(),
if (unstableFeatureVersionsEnabled) {
MetadataVersion.latestTesting.featureLevel
} else {
MetadataVersion.latestProduction.featureLevel
}))
PRODUCTION_FEATURES.forEach { feature => features.put(feature.featureName,
new SupportedVersionRange(0,
if (unstableFeatureVersionsEnabled) {
feature.latestTesting
} else {
feature.latestProduction
}))
}
Features.supportedFeatures(features)
}
There was a problem hiding this comment.
I had considered putting it in BrokerFeatures/QuorumFeatures, but decided against it.
Are you suggesting that I remove how Colin wrote the code (in the ApiVersionsResponse itself).
I was trying to avoid removing his code, but if you think it is better that way I can do it. (I will also need to move the test I wrote elsewhere)
There was a problem hiding this comment.
The main thing is that we need to exclude range 0-0 for supported features in ApiVersionResponse too. Colin's code in ApiVersionsResponse doesn't seem to do what you are doing here for BrokerRegistrationRequest by excluding range 0-0 for supported features. It only changes minVersion v0 to v1 for older requests.
There was a problem hiding this comment.
Yeah. It is already excluded from Colin's commit. If we want to share the logic we can move it to Broker/QuorumFeatures, but I wasn't sure if there was a reason why Colin did it in the response before.
cc: @cmccabe
There was a problem hiding this comment.
From my point of view:
-
We should never report a
0-0supported versions range in an RPC. There is no point! This applies to bothApiVersionsResponseandBrokerRegistrationRequest. -
Obviously a
1-0range is even worse, being incorrect as well as useless. -
Having a HashMap or something that contains a
0-0range is fine, and may simplify the code in some ways. For example if we have code that changes the maximum supported range based on a config, it would probably be annoying to have to mutate the HashMap or use a different hash map if that config was on or off.
I don't feel really strongly about the third point, but I suspect that the code will be messier if you try to remove features with supported version 0-0 from the internal data structures than if you don't.
There was a problem hiding this comment.
My proposal was that in defaultSupportedFeatues, we iterate over the features and add them to a map. Instead of just adding them all, we check if the range is 0-0. If so, we don't add them. (No removal needed) Thus, we don't need specific logic in the apis to remove the feature later.
The only concern is if somehow the features map expected a feature to exist. Not sure I follow mutating if the config is on or off. I assume we can't change the config to enable unstable features dynamically. (If we did, we'd have to mutate the map anyway)
There was a problem hiding this comment.
Code I refer to is:
There was a problem hiding this comment.
Pushed code with this example.
There was a problem hiding this comment.
@jolshan : If you think it's easier to just omit them from the map, that's fine.
I still think we should be checking that these things don't exist later on (and for example, throw an exception if they do) to avoid regressions if someone changes something (as has been happening a lot lately. :) )
There was a problem hiding this comment.
I'm happy to try to make things safer. Can you point me to an example of where you would expect to check if things exist? Do you mean like when building the request? Or something else?
|
Given that Kraft version starts at 0, I guess we should have all versions start a zero for consistency. I also noticed one test asserts all features with version zero bootstrap with minimum kraft version. |
|
@jolshan : Thanks for the updated PR. The following test failure seems related to the PR. |
| expectedFeatures.put(feature.featureName(), VersionRange.of( | ||
| feature.minimumProduction(), | ||
| maxVersion | ||
| )); |
There was a problem hiding this comment.
The code in the test is pretty much the same as the actual code. Does this and the next test add much value?
There was a problem hiding this comment.
I would say maybe if someone changes in the file, we would catch that this is desired behavior and the test would fail?
I can add a comment if that helps.
|
Some of the gradle task executors failed so I will run again. |
…rds to coordinators (apache#16183) This change includes adding transaction.version (part of KIP-1022) New transaction version 1 is introduced to support writing flexible fields in transaction state log messages. Transaction version 2 is created in anticipation for further KIP-890 changes. Neither are made production ready. Tests for the new transaction version and new MV are created. Also include change to not report a feature as supported if the range is 0-0. Reviewers: Jun Rao <junrao@apache.org>, David Jacot <djacot@confluent.io>, Artem Livshits <alivshits@confluent.io>, Colin P. McCabe <cmccabe@apache.org>
This change includes adding transaction.version (part of KIP-1022)
New transaction version 1 is introduced to support writing flexible fields in transaction state log messages.
Transaction version 2 is created in anticipation for further KIP-890 changes.
Neither are made production ready. Tests for the new transaction version and new MV are created.
Committer Checklist (excluded from commit message)