org.apache.kafka.common.requests.AddPartitionsToTxnRequest Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.kafka.common.requests;
import org.apache.kafka.common.TopicPartition;
import org.apache.kafka.common.message.AddPartitionsToTxnRequestData;
import org.apache.kafka.common.message.AddPartitionsToTxnRequestData.AddPartitionsToTxnTopic;
import org.apache.kafka.common.message.AddPartitionsToTxnRequestData.AddPartitionsToTxnTransaction;
import org.apache.kafka.common.message.AddPartitionsToTxnRequestData.AddPartitionsToTxnTransactionCollection;
import org.apache.kafka.common.message.AddPartitionsToTxnRequestData.AddPartitionsToTxnTopicCollection;
import org.apache.kafka.common.message.AddPartitionsToTxnResponseData;
import org.apache.kafka.common.message.AddPartitionsToTxnResponseData.AddPartitionsToTxnPartitionResult;
import org.apache.kafka.common.message.AddPartitionsToTxnResponseData.AddPartitionsToTxnPartitionResultCollection;
import org.apache.kafka.common.message.AddPartitionsToTxnResponseData.AddPartitionsToTxnResult;
import org.apache.kafka.common.message.AddPartitionsToTxnResponseData.AddPartitionsToTxnTopicResult;
import org.apache.kafka.common.message.AddPartitionsToTxnResponseData.AddPartitionsToTxnTopicResultCollection;
import org.apache.kafka.common.protocol.ApiKeys;
import org.apache.kafka.common.protocol.ByteBufferAccessor;
import org.apache.kafka.common.protocol.Errors;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class AddPartitionsToTxnRequest extends AbstractRequest {
private static final short LAST_CLIENT_VERSION = (short) 3;
// Note: earliest broker version is also the first version to support verification requests.
private static final short EARLIEST_BROKER_VERSION = (short) 4;
private final AddPartitionsToTxnRequestData data;
public static class Builder extends AbstractRequest.Builder {
public final AddPartitionsToTxnRequestData data;
public static Builder forClient(String transactionalId,
long producerId,
short producerEpoch,
List partitions) {
AddPartitionsToTxnTopicCollection topics = buildTxnTopicCollection(partitions);
return new Builder(ApiKeys.ADD_PARTITIONS_TO_TXN.oldestVersion(), LAST_CLIENT_VERSION,
new AddPartitionsToTxnRequestData()
.setV3AndBelowTransactionalId(transactionalId)
.setV3AndBelowProducerId(producerId)
.setV3AndBelowProducerEpoch(producerEpoch)
.setV3AndBelowTopics(topics));
}
public static Builder forBroker(AddPartitionsToTxnTransactionCollection transactions) {
return new Builder(EARLIEST_BROKER_VERSION, ApiKeys.ADD_PARTITIONS_TO_TXN.latestVersion(),
new AddPartitionsToTxnRequestData()
.setTransactions(transactions));
}
private Builder(short minVersion, short maxVersion, AddPartitionsToTxnRequestData data) {
super(ApiKeys.ADD_PARTITIONS_TO_TXN, minVersion, maxVersion);
this.data = data;
}
private static AddPartitionsToTxnTopicCollection buildTxnTopicCollection(final List partitions) {
Map> partitionMap = new HashMap<>();
for (TopicPartition topicPartition : partitions) {
String topicName = topicPartition.topic();
partitionMap.compute(topicName, (key, subPartitions) -> {
if (subPartitions == null) {
subPartitions = new ArrayList<>();
}
subPartitions.add(topicPartition.partition());
return subPartitions;
});
}
AddPartitionsToTxnTopicCollection topics = new AddPartitionsToTxnTopicCollection();
for (Map.Entry> partitionEntry : partitionMap.entrySet()) {
topics.add(new AddPartitionsToTxnTopic()
.setName(partitionEntry.getKey())
.setPartitions(partitionEntry.getValue()));
}
return topics;
}
@Override
public AddPartitionsToTxnRequest build(short version) {
return new AddPartitionsToTxnRequest(data, version);
}
@Override
public String toString() {
return data.toString();
}
}
public AddPartitionsToTxnRequest(final AddPartitionsToTxnRequestData data, short version) {
super(ApiKeys.ADD_PARTITIONS_TO_TXN, version);
this.data = data;
}
@Override
public AddPartitionsToTxnRequestData data() {
return data;
}
@Override
public AddPartitionsToTxnResponse getErrorResponse(int throttleTimeMs, Throwable e) {
Errors error = Errors.forException(e);
AddPartitionsToTxnResponseData response = new AddPartitionsToTxnResponseData();
if (version() < EARLIEST_BROKER_VERSION) {
response.setResultsByTopicV3AndBelow(errorResponseForTopics(data.v3AndBelowTopics(), error));
} else {
response.setErrorCode(error.code());
}
response.setThrottleTimeMs(throttleTimeMs);
return new AddPartitionsToTxnResponse(response);
}
public static List getPartitions(AddPartitionsToTxnTopicCollection topics) {
List partitions = new ArrayList<>();
for (AddPartitionsToTxnTopic topicCollection : topics) {
for (Integer partition : topicCollection.partitions()) {
partitions.add(new TopicPartition(topicCollection.name(), partition));
}
}
return partitions;
}
public Map> partitionsByTransaction() {
Map> partitionsByTransaction = new HashMap<>();
for (AddPartitionsToTxnTransaction transaction : data.transactions()) {
List partitions = getPartitions(transaction.topics());
partitionsByTransaction.put(transaction.transactionalId(), partitions);
}
return partitionsByTransaction;
}
// Takes a version 3 or below request (client request) and returns a v4+ singleton (one transaction ID) request.
public AddPartitionsToTxnRequest normalizeRequest() {
return new AddPartitionsToTxnRequest(new AddPartitionsToTxnRequestData().setTransactions(singletonTransaction()), version());
}
// This method returns true if all the transactions in it are verify only. One reason to distinguish is to separate
// requests that will need to write to log in the non error case (adding partitions) from ones that will not (verify only).
public boolean allVerifyOnlyRequest() {
return version() > LAST_CLIENT_VERSION &&
data.transactions().stream().allMatch(AddPartitionsToTxnTransaction::verifyOnly);
}
private AddPartitionsToTxnTransactionCollection singletonTransaction() {
AddPartitionsToTxnTransactionCollection singleTxn = new AddPartitionsToTxnTransactionCollection();
singleTxn.add(new AddPartitionsToTxnTransaction()
.setTransactionalId(data.v3AndBelowTransactionalId())
.setProducerId(data.v3AndBelowProducerId())
.setProducerEpoch(data.v3AndBelowProducerEpoch())
.setTopics(data.v3AndBelowTopics()));
return singleTxn;
}
public AddPartitionsToTxnResult errorResponseForTransaction(String transactionalId, Errors e) {
AddPartitionsToTxnResult txnResult = new AddPartitionsToTxnResult().setTransactionalId(transactionalId);
AddPartitionsToTxnTopicResultCollection topicResults = errorResponseForTopics(data.transactions().find(transactionalId).topics(), e);
txnResult.setTopicResults(topicResults);
return txnResult;
}
private AddPartitionsToTxnTopicResultCollection errorResponseForTopics(AddPartitionsToTxnTopicCollection topics, Errors e) {
AddPartitionsToTxnTopicResultCollection topicResults = new AddPartitionsToTxnTopicResultCollection();
for (AddPartitionsToTxnTopic topic : topics) {
AddPartitionsToTxnTopicResult topicResult = new AddPartitionsToTxnTopicResult().setName(topic.name());
AddPartitionsToTxnPartitionResultCollection partitionResult = new AddPartitionsToTxnPartitionResultCollection();
for (Integer partition : topic.partitions()) {
partitionResult.add(new AddPartitionsToTxnPartitionResult()
.setPartitionIndex(partition)
.setPartitionErrorCode(e.code()));
}
topicResult.setResultsByPartition(partitionResult);
topicResults.add(topicResult);
}
return topicResults;
}
public static AddPartitionsToTxnRequest parse(ByteBuffer buffer, short version) {
return new AddPartitionsToTxnRequest(new AddPartitionsToTxnRequestData(new ByteBufferAccessor(buffer), version), version);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy