Skip to content

Auto Config Non-Blocking Retries with asyncAcks #2702

@wapkch

Description

@wapkch

In what version(s) of Spring for Apache Kafka are you seeing this issue?

3.0.7

Describe the bug

when using asyncAcks together with RetryableTopic, the retried message will not be invoked on KafkaListener.

To Reproduce

@RestController
@SpringBootApplication
public class SpringkafkaAsyncacksDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringkafkaAsyncacksDemoApplication.class, args);
    }

    @Autowired
    private KafkaTemplate<Object, Object> template;

    @PostMapping(path = "/send/{what}")
    public void sendFoo(@PathVariable String what) {
        this.template.send("topic1", what);
    }

    @KafkaListener(id = "fooGroup", topics = "topic1")
    @RetryableTopic(attempts = "5", backoff = @Backoff(delay = 2_000, maxDelay = 10_000, multiplier = 2))
    public void onMessage(ConsumerRecord<String, ?> record, Acknowledgment acknowledgment, Consumer<?, ?> consumer) {
        if (record.value().equals("fail")) {
            throw new RuntimeException("failed");
        }
        acknowledgment.acknowledge();
    }

}

application.properties

spring.kafka.listener.async-acks=true
spring.kafka.retry.topic.enabled=true
spring.kafka.listener.ack-mode=manual
  1. Run local kafka server
  2. Start the application
  3. Access http://localhost:8080/send/fail, and the retried message will not be invoked on KafkaListener.

Expected behavior

I expect Non-Blocking Retries can work with asyncAcks.

I konw using asyncAcks in above case is meaningless, but sometimes the async processing in @KafkaListener is useful. For example:

@Component
public class FooConsumer {

    @KafkaListener(id = "fooGroup", topics = "topic1")
    @RetryableTopic(attempts = "5", backoff = @Backoff(delay = 2_000, maxDelay = 10_000, multiplier = 2))
    public void onMessage(ConsumerRecord<String, ?> record, Acknowledgment acknowledgment, Consumer<?, ?> consumer) {
       threadPoolTaskExecutor.submit(() -> {
           try {
                 doConsume(record);
                 acknowledgment.acknowledge();
           } catch (Exception ex) {
                 container.getCommonErrorHandler().handleOne(new RuntimeException(), record, consumer, container);
           }
        });
    }

}

Sample

https://github.com/wapkch/springkafka-asyncacks-demo

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions