AndrewJSchofield commented on code in PR #23317:
URL: https://github.com/apache/kafka/pull/23317#discussion_r3950272566


##########
generator/src/main/java/org/apache/kafka/message/ApiMessageTypeGenerator.java:
##########
@@ -35,6 +36,8 @@ public final class ApiMessageTypeGenerator implements 
TypeClassGenerator {
     private final CodeBuffer buffer;
     private final TreeMap<Short, ApiData> apis;
     private final EnumMap<RequestListenerType, List<ApiData>> apisByListener = 
new EnumMap<>(RequestListenerType.class);
+    private MessageSpec requestHeaderSpec;

Review Comment:
   I wonder why these are not logically contained within the `requestSpec` and 
`responseSpec` of the `ApiData` itself.



##########
generator/src/main/java/org/apache/kafka/message/ApiMessageTypeGenerator.java:
##########
@@ -141,6 +152,7 @@ public void generateAndWrite(BufferedWriter writer) throws 
IOException {
     }
 
     private void generate() {
+        validateHeaderVersions();

Review Comment:
   This validation code should not be called in the generation phase.



##########
clients/src/test/java/org/apache/kafka/common/message/ApiMessageTypeTest.java:
##########
@@ -98,6 +102,64 @@ public void testHeaderVersion() {
 
         assertEquals((short) 2, 
ApiMessageType.CREATE_TOPICS.requestHeaderVersion((short) 5));
         assertEquals((short) 1, 
ApiMessageType.CREATE_TOPICS.responseHeaderVersion((short) 5));
+
+        // SaslHandshake and OffsetDelete are non-flexible: header v1 request 
/ v0 response at every version.
+        assertEquals((short) 1, 
ApiMessageType.SASL_HANDSHAKE.requestHeaderVersion((short) 0));
+        assertEquals((short) 0, 
ApiMessageType.SASL_HANDSHAKE.responseHeaderVersion((short) 0));
+        assertEquals((short) 1, 
ApiMessageType.SASL_HANDSHAKE.requestHeaderVersion((short) 1));
+        assertEquals((short) 0, 
ApiMessageType.SASL_HANDSHAKE.responseHeaderVersion((short) 1));
+
+        assertEquals((short) 1, 
ApiMessageType.OFFSET_DELETE.requestHeaderVersion((short) 0));
+        assertEquals((short) 0, 
ApiMessageType.OFFSET_DELETE.responseHeaderVersion((short) 0));
+
+        // ApiVersions request follows the flexible rule, but the response 
always uses a v0 header (KIP-511).
+        assertEquals((short) 1, 
ApiMessageType.API_VERSIONS.requestHeaderVersion((short) 0));
+        assertEquals((short) 1, 
ApiMessageType.API_VERSIONS.requestHeaderVersion((short) 2));
+        assertEquals((short) 2, 
ApiMessageType.API_VERSIONS.requestHeaderVersion((short) 3));
+        assertEquals((short) 0, 
ApiMessageType.API_VERSIONS.responseHeaderVersion((short) 0));
+        assertEquals((short) 0, 
ApiMessageType.API_VERSIONS.responseHeaderVersion((short) 3));
+
+        // Envelope is flexible from v0: header v2 request / v1 response 
everywhere.
+        assertEquals((short) 2, 
ApiMessageType.ENVELOPE.requestHeaderVersion((short) 0));
+        assertEquals((short) 1, 
ApiMessageType.ENVELOPE.responseHeaderVersion((short) 0));
+    }
+
+    /**
+     * The header versions generated from the headerVersions maps match the 
versions implied by body
+     * flexibility for every existing API and version: a flexible 
request/response uses header v2/v1,
+     * a non-flexible one uses header v1/v0. The sole exception is 
ApiVersionsResponse, which always
+     * uses a v0 header so that older brokers can parse the response header 
(KIP-511).
+     */
+    @Test
+    public void testHeaderVersionsMatchSchemaFlexibility() {
+        for (ApiMessageType type : ApiMessageType.values()) {
+            if (type.lowestSupportedVersion() > 
type.highestSupportedVersion(true))
+                continue;
+            for (short version = type.lowestSupportedVersion();
+                    version <= type.highestSupportedVersion(true); version++) {
+                short expectedRequestHeader = 
isFlexible(type.requestSchemas()[version]) ? (short) 2 : (short) 1;
+                assertEquals(expectedRequestHeader, 
type.requestHeaderVersion(version),

Review Comment:
   This is going to age badly. When you add v3 request headers, then the 
request header implied by `isFlexible` is no longer sufficient. I suppose that 
you can assert `>=`. I'm still contemplating how to test RPC header consistency 
across AK releases so we don't inadvertently make new code use a higher header 
version than expected.



##########
clients/src/main/resources/common/message/AlterPartitionRequest.json:
##########
@@ -26,6 +26,9 @@
   // Version 3 adds the NewIsrEpochs field and deprecates the NewIsr field 
(KIP-903).
   "validVersions": "2-3",
   "flexibleVersions": "0+",
+  "headerVersions": {

Review Comment:
   In a few cases, we have RPCs in which the oldest versions are no longer 
valid versions. The JSON schemas still describe all of the versions, even 
though the most recent brokers no longer support them. That's why you see 
`validVersions: 2-3` but `flexibleVersions: 0+`. My view is that the header 
versions ought to cover the entire range too, so I would expect `"0+": "2"` 
here. There are some other RPCs, such as `ShareFetch` which this would also 
affect.



##########
clients/src/main/java/org/apache/kafka/clients/NodeApiVersions.java:
##########
@@ -234,7 +234,9 @@ private String apiVersionToText(ApiVersion apiVersion) {
                 bld.append(" [unusable: node too old]");
             } else {
                 short latestUsableVersion = Utils.min(apiKey.latestVersion(), 
supportedVersion.maxVersion());
-                bld.append(" [usable: 
").append(latestUsableVersion).append("]");
+                bld.append(" [usable: ").append(latestUsableVersion)
+                    .append(", request header: 
").append(apiKey.requestHeaderVersion(latestUsableVersion))

Review Comment:
   I think this change should be reverted. It is nice to be able to see the 
effect of the PR interactively, but it was not mentioned in the KIP and I was 
not anticipating this change to these command-line tools. The revised output 
doesn't quite seem that useful to me in practice because it's just the request 
header version of the latest usable RPC version, and the real picture is much 
more complicated (and not really something that I think we should put in the 
output of the tools).



-- 
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]

Reply via email to