@@ -3081,6 +3081,51 @@ private void testCommitRetriesGuts(boolean sync) throws Exception {
30813081 }
30823082 }
30833083
3084+ @ Test
3085+ @ SuppressWarnings ({ "unchecked" , "rawtypes" })
3086+ void commitAfterHandleManual () throws InterruptedException {
3087+ ConsumerFactory <Integer , String > cf = mock (ConsumerFactory .class );
3088+ Consumer <Integer , String > consumer = mock (Consumer .class );
3089+ given (cf .createConsumer (eq ("grp" ), eq ("clientId" ), isNull (), any ())).willReturn (consumer );
3090+ Map <String , Object > cfProps = new HashMap <>();
3091+ cfProps .put (ConsumerConfig .DEFAULT_API_TIMEOUT_MS_CONFIG , 45000 ); // wins
3092+ given (cf .getConfigurationProperties ()).willReturn (cfProps );
3093+ final Map <TopicPartition , List <ConsumerRecord <Integer , String >>> records = new HashMap <>();
3094+ records .put (new TopicPartition ("foo" , 0 ), Arrays .asList (
3095+ new ConsumerRecord <>("foo" , 0 , 0L , 1 , "foo" )));
3096+ ConsumerRecords <Integer , String > consumerRecords = new ConsumerRecords <>(records );
3097+ ConsumerRecords <Integer , String > emptyRecords = new ConsumerRecords <>(Collections .emptyMap ());
3098+ AtomicBoolean first = new AtomicBoolean (true );
3099+ given (consumer .poll (any (Duration .class ))).willAnswer (i -> {
3100+ Thread .sleep (50 );
3101+ return first .getAndSet (false ) ? consumerRecords : emptyRecords ;
3102+ });
3103+ TopicPartitionOffset [] topicPartition = new TopicPartitionOffset [] {
3104+ new TopicPartitionOffset ("foo" , 0 ) };
3105+ ContainerProperties containerProps = new ContainerProperties (topicPartition );
3106+ containerProps .setAckMode (AckMode .MANUAL );
3107+ containerProps .setGroupId ("grp" );
3108+ containerProps .setClientId ("clientId" );
3109+ containerProps .setIdleEventInterval (100L );
3110+ containerProps .setMessageListener ((MessageListener ) r -> {
3111+ throw new RuntimeException ("test" );
3112+ });
3113+ KafkaMessageListenerContainer <Integer , String > container =
3114+ new KafkaMessageListenerContainer <>(cf , containerProps );
3115+ AtomicBoolean recovered = new AtomicBoolean ();
3116+ CountDownLatch latch = new CountDownLatch (1 );
3117+ container .setErrorHandler (new SeekToCurrentErrorHandler ((rec , ex ) -> {
3118+ recovered .set (true );
3119+ latch .countDown ();
3120+ },
3121+ new FixedBackOff (0 , 0 )));
3122+ container .start ();
3123+ assertThat (latch .await (10 , TimeUnit .SECONDS )).isTrue ();
3124+ container .stop ();
3125+ assertThat (recovered .get ()).isTrue ();
3126+ verify (consumer ).commitSync (any (), any ());
3127+ }
3128+
30843129 private Consumer <?, ?> spyOnConsumer (KafkaMessageListenerContainer <Integer , String > container ) {
30853130 Consumer <?, ?> consumer =
30863131 KafkaTestUtils .getPropertyValue (container , "listenerConsumer.consumer" , Consumer .class );
0 commit comments