0

I have a requirement to consume from a kafka topic,do some work on records and produce to another topic with spring-kafka 2.1.7.Other requiremenrs are transactional for once only semantics,retry and error handling.On failure to commit a record I should do 3 retries ,log each of the retry messaage to retry topic anf on failure of all retries send the record to a dead letter topic . I looked at https://github.com/spring-projects/spring-kafka/issues/575 and it has excellent details on solving the problem. The thing that I am struggling with is how to log each of the retry message with details like consumer offset ,topic it was trying to commit,etc .Is there a way to get these from retry call back ?. The retrylistener snippet below is registered with a org.springframework.kafka.listener.LoggingErrorHandler that is set as container property to ConcurrentKafkaListenerContainerFactory ?

         @Bean
         public RetryListener retryListener(KafkaTemplate<String,SpecificRecord> kafkaTemplate) {
             return new RetryListenerSupport() {

                public void onError(RetryContext context, RetryCallback callback, Throwable throwable) {
                    int retryCount =context.getRetryCount();
                    kafkaTemplate) .send(new ProducerRecord<String,SpecificRecord>("topic_name",record));
                }
             };
         }
Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
rookie
  • 386
  • 6
  • 19

1 Answers1

0

The RetryContext is populated with some useful info in the RetryingMessageListenerAdapter:

context.setAttribute(CONTEXT_RECORD, record);
switch (RetryingMessageListenerAdapter.this.delegateType) {
    case ACKNOWLEDGING_CONSUMER_AWARE:
        context.setAttribute(CONTEXT_ACKNOWLEDGMENT, acknowledgment);
        context.setAttribute(CONTEXT_CONSUMER, consumer);
        RetryingMessageListenerAdapter.this.delegate.onMessage(record, acknowledgment, consumer);
        break;
    case ACKNOWLEDGING:
        context.setAttribute(CONTEXT_ACKNOWLEDGMENT, acknowledgment);
        RetryingMessageListenerAdapter.this.delegate.onMessage(record, acknowledgment);
        break;
    case CONSUMER_AWARE:
        context.setAttribute(CONTEXT_CONSUMER, consumer);
        RetryingMessageListenerAdapter.this.delegate.onMessage(record, consumer);
        break;
    case SIMPLE:
        RetryingMessageListenerAdapter.this.delegate.onMessage(record);
}
Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • Thanks Artem. That worked nicely . I have a case where if I receive a particular type of exception from down stream , I should send a notification with a different message to another topic and should not do retries . This exception can happen before doing the producer.send() and producer.sendoffsetsToTransaction, so I am guessing this will not invoke the retry template since transaction manager is not involved here .Would catching that exception and doing an acknowledge work on this case ?. Idea is to process the next record from the consumer without doing a retry if this happens. – rookie Aug 02 '18 at 18:40
  • That's correct. whenever you don't re-throw exception, but ack manually, there is no retry logic involved and you simply go to the next record for processing. – Artem Bilan Aug 02 '18 at 18:42
  • Thank you Artem .I tested this and works .I am not sure if this question belongs here but it will throw it in . From reading kafka docs there could be cases where producer gets an exception from which it cannot recover . What happens in these scenarios when using spring kafka . Is a new producer created ? – rookie Aug 03 '18 at 15:58
  • Right, we have fixed that recently: https://github.com/spring-projects/spring-kafka/issues/753, https://spring.io/blog/2018/08/01/new-spring-integration-amqp-kafka-maintenance-and-milestone-releases – Artem Bilan Aug 03 '18 at 16:31