9393/**
9494 * @author Tomaz Fernandes
9595 * @author Gary Russell
96+ * @author Wang Zhiyang
9697 * @since 2.7
9798 */
9899@ SpringJUnitConfig
@@ -122,6 +123,12 @@ public class RetryTopicIntegrationTests {
122123
123124 public final static String NOT_RETRYABLE_EXCEPTION_TOPIC = "noRetryTopic" ;
124125
126+ public final static String FIRST_REUSE_RETRY_TOPIC = "reuseRetry1" ;
127+
128+ public final static String SECOND_REUSE_RETRY_TOPIC = "reuseRetry2" ;
129+
130+ public final static String THIRD_REUSE_RETRY_TOPIC = "reuseRetry3" ;
131+
125132 private final static String MAIN_TOPIC_CONTAINER_FACTORY = "kafkaListenerContainerFactory" ;
126133
127134 @ Autowired
@@ -267,6 +274,29 @@ void shouldRetryManualTopicWithDefaultDlt(@Autowired KafkaListenerEndpointRegist
267274 }
268275 }
269276
277+ @ Test
278+ void shouldFirstReuseRetryTopic (@ Autowired FirstReuseRetryTopicListener listener1 ,
279+ @ Autowired SecondReuseRetryTopicListener listener2 , @ Autowired ThirdReuseRetryTopicListener listener3 ) {
280+
281+ logger .debug ("Sending message to topic " + FIRST_REUSE_RETRY_TOPIC );
282+ kafkaTemplate .send (FIRST_REUSE_RETRY_TOPIC , "Testing reuse topic 1" );
283+ logger .debug ("Sending message to topic " + SECOND_REUSE_RETRY_TOPIC );
284+ kafkaTemplate .send (SECOND_REUSE_RETRY_TOPIC , "Testing reuse topic 2" );
285+ logger .debug ("Sending message to topic " + THIRD_REUSE_RETRY_TOPIC );
286+ kafkaTemplate .send (THIRD_REUSE_RETRY_TOPIC , "Testing reuse topic 3" );
287+ assertThat (awaitLatch (latchContainer .countDownLatchReuseOne )).isTrue ();
288+ assertThat (awaitLatch (latchContainer .countDownLatchReuseTwo )).isTrue ();
289+ assertThat (awaitLatch (latchContainer .countDownLatchReuseThree )).isTrue ();
290+ assertThat (listener1 .topics ).containsExactly (FIRST_REUSE_RETRY_TOPIC ,
291+ FIRST_REUSE_RETRY_TOPIC + "-retry" );
292+ assertThat (listener2 .topics ).containsExactly (SECOND_REUSE_RETRY_TOPIC ,
293+ SECOND_REUSE_RETRY_TOPIC + "-retry-30" , SECOND_REUSE_RETRY_TOPIC + "-retry-60" ,
294+ SECOND_REUSE_RETRY_TOPIC + "-retry-100" , SECOND_REUSE_RETRY_TOPIC + "-retry-100" );
295+ assertThat (listener3 .topics ).containsExactly (THIRD_REUSE_RETRY_TOPIC ,
296+ THIRD_REUSE_RETRY_TOPIC + "-retry" , THIRD_REUSE_RETRY_TOPIC + "-retry" ,
297+ THIRD_REUSE_RETRY_TOPIC + "-retry" , THIRD_REUSE_RETRY_TOPIC + "-retry" );
298+ }
299+
270300 @ Test
271301 public void shouldGoStraightToDlt () {
272302 logger .debug ("Sending message to topic " + NOT_RETRYABLE_EXCEPTION_TOPIC );
@@ -473,6 +503,69 @@ public void annotatedDltMethod(Object message) {
473503 }
474504 }
475505
506+ @ Component
507+ static class FirstReuseRetryTopicListener {
508+
509+ final List <String > topics = Collections .synchronizedList (new ArrayList <>());
510+
511+ @ Autowired
512+ CountDownLatchContainer container ;
513+
514+ @ RetryableTopic (attempts = "2" , backoff = @ Backoff (50 ),
515+ sameIntervalTopicReuseStrategy = SameIntervalTopicReuseStrategy .SINGLE_TOPIC )
516+ @ KafkaListener (id = "reuseRetry1" , topics = FIRST_REUSE_RETRY_TOPIC ,
517+ containerFactory = "retryTopicListenerContainerFactory" )
518+ public void listen1 (String message , @ Header (KafkaHeaders .RECEIVED_TOPIC ) String receivedTopic ) {
519+ logger .debug ("Message {} received in topic {} " , message , receivedTopic );
520+ this .topics .add (receivedTopic );
521+ container .countDownLatchReuseOne .countDown ();
522+ throw new RuntimeException ("Another woooops... " + receivedTopic );
523+ }
524+
525+ }
526+
527+ @ Component
528+ static class SecondReuseRetryTopicListener {
529+
530+ final List <String > topics = Collections .synchronizedList (new ArrayList <>());
531+
532+ @ Autowired
533+ CountDownLatchContainer container ;
534+
535+ @ RetryableTopic (attempts = "5" , backoff = @ Backoff (delay = 30 , maxDelay = 100 , multiplier = 2 ),
536+ sameIntervalTopicReuseStrategy = SameIntervalTopicReuseStrategy .SINGLE_TOPIC )
537+ @ KafkaListener (id = "reuseRetry2" , topics = SECOND_REUSE_RETRY_TOPIC ,
538+ containerFactory = "retryTopicListenerContainerFactory" )
539+ public void listen2 (String message , @ Header (KafkaHeaders .RECEIVED_TOPIC ) String receivedTopic ) {
540+ logger .debug ("Message {} received in topic {} " , message , receivedTopic );
541+ this .topics .add (receivedTopic );
542+ container .countDownLatchReuseTwo .countDown ();
543+ throw new RuntimeException ("Another woooops... " + receivedTopic );
544+ }
545+
546+ }
547+
548+ @ Component
549+ static class ThirdReuseRetryTopicListener {
550+
551+ final List <String > topics = Collections .synchronizedList (new ArrayList <>());
552+
553+ @ Autowired
554+ CountDownLatchContainer container ;
555+
556+ @ RetryableTopic (attempts = "5" , backoff = @ Backoff (delay = 1 , maxDelay = 5 , multiplier = 1.4 ),
557+ sameIntervalTopicReuseStrategy = SameIntervalTopicReuseStrategy .SINGLE_TOPIC )
558+ @ KafkaListener (id = "reuseRetry3" , topics = THIRD_REUSE_RETRY_TOPIC ,
559+ containerFactory = "retryTopicListenerContainerFactory" )
560+ public void listen3 (String message , @ Header (KafkaHeaders .RECEIVED_TOPIC ) String receivedTopic ) {
561+ logger .debug ("Message {} received in topic {} " , message , receivedTopic );
562+ this .topics .add (receivedTopic );
563+ container .countDownLatchReuseThree .countDown ();
564+ throw new RuntimeException ("Another woooops... " + receivedTopic );
565+ }
566+
567+ }
568+
476569 @ Component
477570 static class CountDownLatchContainer {
478571
@@ -488,6 +581,9 @@ static class CountDownLatchContainer {
488581 CountDownLatch countDownLatchDltTwo = new CountDownLatch (1 );
489582 CountDownLatch countDownLatchDltThree = new CountDownLatch (1 );
490583 CountDownLatch countDownLatchDltFour = new CountDownLatch (1 );
584+ CountDownLatch countDownLatchReuseOne = new CountDownLatch (2 );
585+ CountDownLatch countDownLatchReuseTwo = new CountDownLatch (5 );
586+ CountDownLatch countDownLatchReuseThree = new CountDownLatch (5 );
491587 CountDownLatch customDltCountdownLatch = new CountDownLatch (1 );
492588 CountDownLatch customErrorHandlerCountdownLatch = new CountDownLatch (6 );
493589 CountDownLatch customMessageConverterCountdownLatch = new CountDownLatch (6 );
@@ -628,6 +724,21 @@ public NoRetryTopicListener noRetryTopicListener() {
628724 return new NoRetryTopicListener ();
629725 }
630726
727+ @ Bean
728+ public FirstReuseRetryTopicListener firstReuseRetryTopicListener () {
729+ return new FirstReuseRetryTopicListener ();
730+ }
731+
732+ @ Bean
733+ public SecondReuseRetryTopicListener secondReuseRetryTopicListener () {
734+ return new SecondReuseRetryTopicListener ();
735+ }
736+
737+ @ Bean
738+ public ThirdReuseRetryTopicListener thirdReuseRetryTopicListener () {
739+ return new ThirdReuseRetryTopicListener ();
740+ }
741+
631742 @ Bean
632743 CountDownLatchContainer latchContainer () {
633744 return new CountDownLatchContainer ();
0 commit comments