question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Header lost in DLQ failure strategy

See original GitHub issue

Describe the bug

I am implementing a retry policy in my project in quarkus. Here’s the pitch : I produce a Kafka message who’s consumed in several place in my project. If for any reason one of this consumer fails to handle this message, it’s nacked and publish in a retry topic using the dead-letter-queue failure strategy.

The messages from this topic are handle by another consumer who try to republish it in the original topic while adding a “retryCount” header. The message will then be consumed again by the faulty consumer, who will either succeed or fail again and publish it back in the retry topic.

Here is my issue :

The headers won’t persist after first retry. After first fail, the message is succesfully pushed in the error topic, then pushed back in its original topic with the new custom header, but if the consumer fail once more and push the message in the error topic again, my custom header doesn’t exist anymore.

https://github.com/smallrye/smallrye-reactive-messaging/blob/d09d8b97cba72988f7c06f6ceec81b4a1a322a7d/smallrye-reactive-messaging-kafka/src/main/java/io/smallrye/reactive/messaging/kafka/fault/KafkaDeadLetterQueue.java#L129 This seems to show that headers are kept when pushed in DLQ but in my consumer, it doesn’t

@ApplicationScoped
@ActivateRequestContext
@Slf4j
public class KafkaErrorConsumer {
private final KafkaRetry kafkaRetry;
private String insanity = "Insanity is doing the same thing over and over again and expecting a different result";

@Inject
public KafkaErrorConsumer(KafkaRetry kafkaRetry) {
    this‧kafkaRetry = kafkaRetry;
}

@NonBlocking
@Incoming(KafkaTopics.KAFKA_ERROR_EVENT)

public CompletionStage<Void> handle(Message<String> event) throws BusinessException, InterruptedException {

var metadata = event‧getMetadata(IncomingKafkaRecordMetadata‧class)
                    .orElseThrow(() -> new IllegalArgumentException("Expected a message coming from Kafka"));
String reason = new String(metadata‧getHeaders().lastHeader("dead-letter-reason").value());
String topic = new String(metadata‧getHeaders().lastHeader("dead-letter-topic").value());

Instant timeStamp = metadata‧getTimestamp();
if (!reason‧equals(insanity)) {
    log‧info("""
                                
            Received failed event : {}
            from : {}
            because of : {}""", event‧getPayload(), topic, reason);
    kafkaRetry‧execute(event, topic);

    return event‧ack();
} else {
    metadata‧getHeaders().forEach(header -> log‧info(new String(header‧value())));

I enter the “else” durind second retry, so the custom header shoud be there, as it was added after first fail, but it’s not.

Expected behavior

headers should be kept while pushing the message in the DLQ, as shown in this : https://github.com/smallrye/smallrye-reactive-messaging/blob/d09d8b97cba72988f7c06f6ceec81b4a1a322a7d/smallrye-reactive-messaging-kafka/src/main/java/io/smallrye/reactive/messaging/kafka/fault/KafkaDeadLetterQueue.java#L129

Actual behavior

Headers are overwritten and metadata‧getHeaders().lastHeader("retryCount") return null

How to Reproduce?

How to rerpoduce :

  1. nack a message in a topic with dead letter queue failure strategy enabled via quarkus conf
  2. consume this message, add a custom header, push it in its original topic
  3. consume this message again, check the custom header, nack the message if the header is present so it goes in the DLQ topic
  4. consume this message once more, custom header is gone

Output of uname -a or ver

Linux 5.14.7-2-MANJARO #1 SMP PREEMPT Wed Sep 22 12:22:56 UTC 2021 x86_64 GNU/Linux

Output of java -version

openjdk version “17” 2021-09-14 OpenJDK Runtime Environment (build 17+35-2724) OpenJDK 64-Bit Server VM (build 17+35-2724, mixed mode, sharing)

GraalVM version (if different from Java)

No response

Quarkus version or git rev

2.2.3.Final

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.8.2 (NON_CANONICAL)

Additional information

No response

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:12 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
sergejomoncommented, Dec 6, 2021

Ok ! So that would make sens : header are kept from C to B but not from B to C. I’ll try to update to quarkus 2 and last version of smallrye in service B and I’ll update this issue accordingly. Thank you for your time 🙂


De : Clement Escoffier @.> Envoyé : lundi 6 décembre 2021 08:19 À : quarkusio/quarkus @.> Cc : Serge @.>; Author @.> Objet : Re: [quarkusio/quarkus] Header lost in DLQ failure strategy (#20537)

The in-memory is just for tests, so we can ignore it. I believe that Service B, which uses an “old” version of Quarkus may not have the feature we are discussing here. A and C should have it.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/quarkusio/quarkus/issues/20537#issuecomment-986503295, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AJLB2ZUUHI6DKZLJTZXMPFTUPRPXDANCNFSM5FLLEMDQ. Triage notifications on the go with GitHub Mobile for iOShttps://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Androidhttps://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

0reactions
cescoffiercommented, Dec 6, 2021

The in-memory is just for tests, so we can ignore it. I believe that Service B, which uses an “old” version of Quarkus may not have the feature we are discussing here. A and C should have it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Error Handling via Dead Letter Queue in Apache Kafka
This blog post explores best practices for implementing error handling using a Dead Letter Queue in Apache Kafka infrastructure.
Read more >
How to custom header message exception in DLQ
If a dead-letter queue (DLQ) is configured, RabbitMQ routes the failed message (unchanged) to the DLQ. If set to true, the binder republishs ......
Read more >
Kafka Connect Deep Dive – Error Handling and Dead Letter ...
Recording the failure reason for a message: Message headers. Headers are additional metadata stored with the Kafka message's key, value and ...
Read more >
Error Handling via Dead Letter Queue in Apache Kafka
This blog post explores best practices for implementing error handling using a Dead Letter Queue in Apache Kafka infrastructure.
Read more >
How do I process messages on the dead letter queue (DLQ)?
The message is not lost – it wasn't created, and the DLQ was not used. If a message comes in from another queue...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found