@@ -304,6 +304,62 @@ class PlaintextConsumerCommitTest extends AbstractConsumerTest {
304304 consumeAndVerifyRecords(consumer = otherConsumer, numRecords = 1 , startingOffset = 5 , startingTimestamp = startingTimestamp)
305305 }
306306
307+ @ ParameterizedTest (name = TestInfoUtils .TestWithParameterizedQuorumAndGroupProtocolNames )
308+ @ MethodSource (Array (" getTestQuorumAndGroupProtocolParametersAll" ))
309+ def testCommitAsyncCompletedBeforeConsumerCloses (quorum : String , groupProtocol : String ): Unit = {
310+ // This is testing the contract that asynchronous offset commit are completed before the consumer
311+ // is closed, even when no commit sync is performed as part of the close (due to auto-commit
312+ // disabled, or simply because there no consumed offsets).
313+ val producer = createProducer()
314+ sendRecords(producer, numRecords = 3 , tp)
315+ sendRecords(producer, numRecords = 3 , tp2)
316+
317+ val consumer = createConsumer()
318+ consumer.assign(List (tp, tp2).asJava)
319+
320+ // Try without looking up the coordinator first
321+ val cb = new CountConsumerCommitCallback
322+ consumer.commitAsync(Map [TopicPartition , OffsetAndMetadata ]((tp, new OffsetAndMetadata (1L ))).asJava, cb)
323+ consumer.commitAsync(Map [TopicPartition , OffsetAndMetadata ]((tp2, new OffsetAndMetadata (1L ))).asJava, cb)
324+ consumer.close()
325+ assertEquals(2 , cb.successCount)
326+ }
327+
328+ @ ParameterizedTest (name = TestInfoUtils .TestWithParameterizedQuorumAndGroupProtocolNames )
329+ @ MethodSource (Array (" getTestQuorumAndGroupProtocolParametersAll" ))
330+ def testCommitAsyncCompletedBeforeCommitSyncReturns (quorum : String , groupProtocol : String ): Unit = {
331+ // This is testing the contract that asynchronous offset commits sent previously with the
332+ // `commitAsync` are guaranteed to have their callbacks invoked prior to completion of
333+ // `commitSync` (given that it does not time out).
334+ val producer = createProducer()
335+ sendRecords(producer, numRecords = 3 , tp)
336+ sendRecords(producer, numRecords = 3 , tp2)
337+
338+ val consumer = createConsumer()
339+ consumer.assign(List (tp, tp2).asJava)
340+
341+ // Try without looking up the coordinator first
342+ val cb = new CountConsumerCommitCallback
343+ consumer.commitAsync(Map [TopicPartition , OffsetAndMetadata ]((tp, new OffsetAndMetadata (1L ))).asJava, cb)
344+ consumer.commitSync(Map .empty[TopicPartition , OffsetAndMetadata ].asJava)
345+ assertEquals(1 , consumer.committed(Set (tp).asJava).get(tp).offset)
346+ assertEquals(1 , cb.successCount)
347+
348+ // Try with coordinator known
349+ consumer.commitAsync(Map [TopicPartition , OffsetAndMetadata ]((tp, new OffsetAndMetadata (2L ))).asJava, cb)
350+ consumer.commitSync(Map [TopicPartition , OffsetAndMetadata ]((tp2, new OffsetAndMetadata (2L ))).asJava)
351+ assertEquals(2 , consumer.committed(Set (tp).asJava).get(tp).offset)
352+ assertEquals(2 , consumer.committed(Set (tp2).asJava).get(tp2).offset)
353+ assertEquals(2 , cb.successCount)
354+
355+ // Try with empty sync commit
356+ consumer.commitAsync(Map [TopicPartition , OffsetAndMetadata ]((tp, new OffsetAndMetadata (3L ))).asJava, cb)
357+ consumer.commitSync(Map .empty[TopicPartition , OffsetAndMetadata ].asJava)
358+ assertEquals(3 , consumer.committed(Set (tp).asJava).get(tp).offset)
359+ assertEquals(2 , consumer.committed(Set (tp2).asJava).get(tp2).offset)
360+ assertEquals(3 , cb.successCount)
361+ }
362+
307363 def changeConsumerSubscriptionAndValidateAssignment [K , V ](consumer : Consumer [K , V ],
308364 topicsToSubscribe : List [String ],
309365 expectedAssignment : Set [TopicPartition ],
@@ -314,6 +370,8 @@ class PlaintextConsumerCommitTest extends AbstractConsumerTest {
314370}
315371
316372object PlaintextConsumerCommitTest {
373+ def getTestQuorumAndGroupProtocolParametersConsumerGroupProtocolOnly : Stream [Arguments ] =
374+ BaseConsumerTest .getTestQuorumAndGroupProtocolParametersConsumerGroupProtocolOnly()
317375
318376 def getTestQuorumAndGroupProtocolParametersAll : Stream [Arguments ] =
319377 BaseConsumerTest .getTestQuorumAndGroupProtocolParametersAll()
0 commit comments