cxm940188 commented on code in PR #23525:
URL: https://github.com/apache/kafka/pull/23525#discussion_r4322202971


##########
metadata/src/test/java/org/apache/kafka/controller/QuorumControllerTest.java:
##########
@@ -1637,6 +1652,54 @@ public void testAppendRecordsAtomically() {
                         appender)).getMessage());
     }
 
+    @ParameterizedTest(name = "numRecords={0}, maxRecordsPerBatch={1}")
+    @CsvSource({
+        "1, 1",
+        "5, 1",
+        "5, 10",
+        "10, 10",
+        "15, 10",
+        "20, 10"
+    })
+    public void testAppendRecordsNonAtomicBatching(int numRecords, int 
maxRecordsPerBatch) {
+        List<ApiMessageAndVersion> records = new ArrayList<>();
+        for (int i = 0; i < numRecords; i++) {
+            records.add(rec(i));
+        }
+        RecordingAppender appender = new RecordingAppender();
+        long returned = QuorumController.appendRecords(log,
+            ControllerResult.of(records, null), maxRecordsPerBatch, appender);
+
+        List<Integer> expectedSizes = new ArrayList<>();
+        for (int i = 0; i < numRecords; i += maxRecordsPerBatch) {
+            expectedSizes.add(Math.min(maxRecordsPerBatch, numRecords - i));
+        }
+        assertEquals(expectedSizes, appender.batchSizes,
+            "batches should be exactly maxRecordsPerBatch-sized except the 
final one");
+        assertTrue(appender.batchSizes.stream().allMatch(s -> s > 0 && s <= 
maxRecordsPerBatch),
+            "every batch should be non-empty and no larger than 
maxRecordsPerBatch");
+        assertEquals(numRecords, 
appender.batchSizes.stream().mapToLong(Integer::longValue).sum(),
+            "no record should be dropped or duplicated");
+        assertEquals((long) numRecords, returned);
+    }
+
+    @Test
+    public void testNonAtomicWriteDoesNotTriggerControllerFailover() throws 
Throwable {

Review Comment:
   This integration test proves the **end-to-end** effect: a non-atomic write 
whose record count is an exact multiple of `maxRecordsPerBatch` must not cause 
the active controller to renounce leadership.
   
   - `setControllerMaxRecordsPerBatch(1)` makes every non-empty write an exact 
multiple.
   - `registerBrokersAndUnfence` drives a real `registerBroker` write through 
the real `ControllerWriteEvent → appendRecords → prepareAppend` path.
   - The trailing assertion checks `curClaimEpoch` is unchanged.
   
   The test throws at `registerBroker(...).get()` (an `ExecutionException`), 
not at the epoch assertion. With `maxRecordsPerBatch = 1` and one record, the 
unfixed loop appends an empty `subList(1, 1)`; `MockRaftClient.prepareAppend` 
throws `IllegalArgumentException("Batch cannot be empty")`; 
`EventHandlerExceptionInfo`'s catch-all marks it `causesFailover = true` and 
wraps it in `UnknownServerException`; the controller calls `renounce()` and the 
future completes exceptionally, so `.get()` throws.
   
   **Actual failure on trunk**
   
   ./gradlew metadata:test --tests 
"QuorumControllerTest.testNonAtomicWriteDoesNotTriggerControllerFailover"
   ------------
   > Task :metadata:test FAILED
   
   Gradle Test Executor 3 > QuorumControllerTest > 
testNonAtomicWriteDoesNotTriggerControllerFailover() FAILED
       java.util.concurrent.ExecutionException: 
org.apache.kafka.common.errors.UnknownServerException: 
java.lang.IllegalArgumentException: Batch cannot be empty
           at 
java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:396)
           at 
java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2073)
           at 
org.apache.kafka.controller.QuorumControllerIntegrationTestUtils.registerBrokersAndUnfence(QuorumControllerIntegrationTestUtils.java:134)
           at 
org.apache.kafka.controller.QuorumControllerTest.testNonAtomicWriteDoesNotTriggerControllerFailover(QuorumControllerTest.java:1695)
   
           Caused by:
           org.apache.kafka.common.errors.UnknownServerException: 
java.lang.IllegalArgumentException: Batch cannot be empty
               Caused by:
               java.lang.IllegalArgumentException: Batch cannot be empty
                   at 
org.apache.kafka.controller.MockRaftClient.prepareAppend(MockRaftClient.java:681)
                   at 
org.apache.kafka.controller.QuorumController$ControllerWriteEvent.lambda$run$0(QuorumController.java:822)
                   at 
org.apache.kafka.controller.QuorumController.appendRecords(QuorumController.java:923)
                   at 
org.apache.kafka.controller.QuorumController$ControllerWriteEvent.run(QuorumController.java:816)
                   at 
org.apache.kafka.queue.KafkaEventQueue$EventContext.run(KafkaEventQueue.java:134)
                   ...
   
   1 test completed, 1 failed
   BUILD FAILED in 45s
   --------------------
   
   The epoch assertion is the fixed-code sentinel and never runs on trunk.
   
   ---
   
   Do you have any other suggestions for this test — for example, restructuring 
it or removing it in favor of the unit-level coverage?



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