Don't request redelivery of dead letter messages
If we send a message to the dead letter topic, we shouldn't also
request that the same message be redelivered.
The process to send to DLQ does do an acknowledge(), but acknowledge
is async and not guaranteed, so it can race with the redelivery
request.
@@ -1268,15 +1268,15 @@ public class ConsumerImpl<T> extends ConsumerBase<T> implements ConnectionHandle
.collect(Collectors.toSet()), MAX_REDELIVER_UNACKNOWLEDGED);
MessageIdData.Builder builder = MessageIdData.newBuilder();
batches.forEach(ids -> {
- List<MessageIdData> messageIdDatas = ids.stream().map(messageId -> {
- // process message possible to dead letter topic
- processPossibleToDLQ(messageId);
- // attempt to remove message from batchMessageAckTracker
+ List<MessageIdData> messageIdDatas = ids.stream()
+ .filter(messageId -> !processPossibleToDLQ(messageId))
+ .map(messageId -> {
builder.setPartition(messageId.getPartitionIndex());
builder.setLedgerId(messageId.getLedgerId());
builder.setEntryId(messageId.getEntryId());
return builder.build();
}).collect(Collectors.toList());
+
ByteBuf cmd = Commands.newRedeliverUnacknowledgedMessages(consumerId, messageIdDatas);
cnx.ctx().writeAndFlush(cmd, cnx.ctx().voidPromise());
messageIdDatas.forEach(MessageIdData::recycle);
@@ -1299,7 +1299,7 @@ public class ConsumerImpl<T> extends ConsumerBase<T> implements ConnectionHandle
}
}
- private void processPossibleToDLQ(MessageIdImpl messageId) {
+ private boolean processPossibleToDLQ(MessageIdImpl messageId) {
List<MessageImpl<T>> deadLetterMessages = null;
if (possibleSendToDeadLetterTopicMessages != null) {
if (messageId instanceof BatchMessageIdImpl) {
@@ -1329,11 +1329,13 @@ public class ConsumerImpl<T> extends ConsumerBase<T> implements ConnectionHandle
.send();
}
acknowledge(messageId);
+ return true;
} catch (Exception e) {
log.error("Send to dead letter topic exception with topic: {}, messageId: {}", deadLetterProducer.getTopic(), messageId, e);
}
}
}
+ return false;
}
@Override
