Skip to content

Commit b90445d

Browse files
committed
KAFKA-19397: Not relaying on metadata to map between topic id and name.
- Metadata doesn't have the full view of topicNames to ids during rebootstrap of client or when topic has been deleted/recreated. The solution is to pass down topic id and stop trying to figure it out later in the logic.
1 parent edd0efd commit b90445d

File tree

2 files changed

+28
-7
lines changed

2 files changed

+28
-7
lines changed

clients/src/main/java/org/apache/kafka/clients/producer/internals/Sender.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.apache.kafka.common.KafkaException;
2828
import org.apache.kafka.common.MetricName;
2929
import org.apache.kafka.common.Node;
30+
import org.apache.kafka.common.TopicIdPartition;
3031
import org.apache.kafka.common.TopicPartition;
3132
import org.apache.kafka.common.Uuid;
3233
import org.apache.kafka.common.errors.AuthenticationException;
@@ -565,7 +566,7 @@ private boolean awaitNodeReady(Node node, FindCoordinatorRequest.CoordinatorType
565566
/**
566567
* Handle a produce response
567568
*/
568-
private void handleProduceResponse(ClientResponse response, Map<TopicPartition, ProducerBatch> batches, long now) {
569+
private void handleProduceResponse(ClientResponse response, Map<TopicIdPartition, ProducerBatch> batches, long now) {
569570
RequestHeader requestHeader = response.requestHeader();
570571
int correlationId = requestHeader.correlationId();
571572
if (response.wasTimedOut()) {
@@ -595,9 +596,6 @@ private void handleProduceResponse(ClientResponse response, Map<TopicPartition,
595596
// This will be set by completeBatch.
596597
Map<TopicPartition, Metadata.LeaderIdAndEpoch> partitionsWithUpdatedLeaderInfo = new HashMap<>();
597598
produceResponse.data().responses().forEach(r -> r.partitionResponses().forEach(p -> {
598-
// Version 13 drop topic name and add support to topic id. However, metadata can be used to map topic id to topic name.
599-
String topicName = metadata.topicNames().getOrDefault(r.topicId(), r.name());
600-
TopicPartition tp = new TopicPartition(topicName, p.index());
601599
ProduceResponse.PartitionResponse partResp = new ProduceResponse.PartitionResponse(
602600
Errors.forCode(p.errorCode()),
603601
p.baseOffset(),
@@ -609,7 +607,22 @@ private void handleProduceResponse(ClientResponse response, Map<TopicPartition,
609607
.collect(Collectors.toList()),
610608
p.errorMessage(),
611609
p.currentLeader());
612-
ProducerBatch batch = batches.get(tp);
610+
ProducerBatch batch = null;
611+
// Version 13 drop topic name and add support to topic id.
612+
// We need to find batch based on topic id and partition index only as
613+
// topic name in the response might be empty.
614+
List<ProducerBatch> matchedBatchesForTopicId = batches.entrySet().stream()
615+
.filter(entry -> entry.getKey().matchesTopicIdForPartition(r.topicId(), p.index()))
616+
.map(Map.Entry::getValue)
617+
.collect(Collectors.toList());
618+
619+
if (matchedBatchesForTopicId.size() > 1) {
620+
matchedBatchesForTopicId.forEach((matchedBatch) ->
621+
failBatch(matchedBatch, new RuntimeException("More than one batch with same topic id and partition."), false));
622+
} else {
623+
batch = matchedBatchesForTopicId.stream().findFirst().orElse(null);
624+
}
625+
613626
completeBatch(batch, partResp, correlationId, now, partitionsWithUpdatedLeaderInfo);
614627
}));
615628

@@ -855,7 +868,7 @@ private void sendProduceRequest(long now, int destination, short acks, int timeo
855868
if (batches.isEmpty())
856869
return;
857870

858-
final Map<TopicPartition, ProducerBatch> recordsByPartition = new HashMap<>(batches.size());
871+
final Map<TopicIdPartition, ProducerBatch> recordsByPartition = new HashMap<>(batches.size());
859872
Map<String, Uuid> topicIds = topicIdsForBatches(batches);
860873

861874
ProduceRequestData.TopicProduceDataCollection tpd = new ProduceRequestData.TopicProduceDataCollection();
@@ -874,7 +887,7 @@ private void sendProduceRequest(long now, int destination, short acks, int timeo
874887
tpData.partitionData().add(new ProduceRequestData.PartitionProduceData()
875888
.setIndex(tp.partition())
876889
.setRecords(records));
877-
recordsByPartition.put(tp, batch);
890+
recordsByPartition.put(new TopicIdPartition(topicId, tp), batch);
878891
}
879892

880893
String transactionalId = null;

clients/src/main/java/org/apache/kafka/common/TopicIdPartition.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ public TopicPartition topicPartition() {
7878
return topicPartition;
7979
}
8080

81+
/**
82+
* @return true if topic has same topicId and partition index as topic names some time might be empty.
83+
*/
84+
public boolean matchesTopicIdForPartition(Uuid topicId, int partition) {
85+
return topicId.equals(topicId) &&
86+
topicPartition.partition() == partition();
87+
}
88+
8189
@Override
8290
public boolean equals(Object o) {
8391
if (this == o) {

0 commit comments

Comments
 (0)