use of org.apache.kafka.common.requests.AbstractResponse in project kafka by apache.
the class KafkaAdminClient method listPartitionReassignments.
@Override
public ListPartitionReassignmentsResult listPartitionReassignments(Optional<Set<TopicPartition>> partitions, ListPartitionReassignmentsOptions options) {
final KafkaFutureImpl<Map<TopicPartition, PartitionReassignment>> partitionReassignmentsFuture = new KafkaFutureImpl<>();
if (partitions.isPresent()) {
for (TopicPartition tp : partitions.get()) {
String topic = tp.topic();
int partition = tp.partition();
if (topicNameIsUnrepresentable(topic)) {
partitionReassignmentsFuture.completeExceptionally(new InvalidTopicException("The given topic name '" + topic + "' cannot be represented in a request."));
} else if (partition < 0) {
partitionReassignmentsFuture.completeExceptionally(new InvalidTopicException("The given partition index " + partition + " is not valid."));
}
if (partitionReassignmentsFuture.isCompletedExceptionally())
return new ListPartitionReassignmentsResult(partitionReassignmentsFuture);
}
}
final long now = time.milliseconds();
runnable.call(new Call("listPartitionReassignments", calcDeadlineMs(now, options.timeoutMs()), new ControllerNodeProvider()) {
@Override
ListPartitionReassignmentsRequest.Builder createRequest(int timeoutMs) {
ListPartitionReassignmentsRequestData listData = new ListPartitionReassignmentsRequestData();
listData.setTimeoutMs(timeoutMs);
if (partitions.isPresent()) {
Map<String, ListPartitionReassignmentsTopics> reassignmentTopicByTopicName = new HashMap<>();
for (TopicPartition tp : partitions.get()) {
if (!reassignmentTopicByTopicName.containsKey(tp.topic()))
reassignmentTopicByTopicName.put(tp.topic(), new ListPartitionReassignmentsTopics().setName(tp.topic()));
reassignmentTopicByTopicName.get(tp.topic()).partitionIndexes().add(tp.partition());
}
listData.setTopics(new ArrayList<>(reassignmentTopicByTopicName.values()));
}
return new ListPartitionReassignmentsRequest.Builder(listData);
}
@Override
void handleResponse(AbstractResponse abstractResponse) {
ListPartitionReassignmentsResponse response = (ListPartitionReassignmentsResponse) abstractResponse;
Errors error = Errors.forCode(response.data().errorCode());
switch(error) {
case NONE:
break;
case NOT_CONTROLLER:
handleNotControllerError(error);
break;
default:
partitionReassignmentsFuture.completeExceptionally(new ApiError(error, response.data().errorMessage()).exception());
break;
}
Map<TopicPartition, PartitionReassignment> reassignmentMap = new HashMap<>();
for (OngoingTopicReassignment topicReassignment : response.data().topics()) {
String topicName = topicReassignment.name();
for (OngoingPartitionReassignment partitionReassignment : topicReassignment.partitions()) {
reassignmentMap.put(new TopicPartition(topicName, partitionReassignment.partitionIndex()), new PartitionReassignment(partitionReassignment.replicas(), partitionReassignment.addingReplicas(), partitionReassignment.removingReplicas()));
}
}
partitionReassignmentsFuture.complete(reassignmentMap);
}
@Override
void handleFailure(Throwable throwable) {
partitionReassignmentsFuture.completeExceptionally(throwable);
}
}, now);
return new ListPartitionReassignmentsResult(partitionReassignmentsFuture);
}
use of org.apache.kafka.common.requests.AbstractResponse in project kafka by apache.
the class KafkaAdminClient method getMetadataCall.
/**
* Returns a {@code Call} object to fetch the cluster metadata. Takes a List of Calls
* parameter to schedule actions that need to be taken using the metadata. The param is a Supplier
* so that it can be lazily created, so that it can use the results of the metadata call in its
* construction.
*
* @param <T> The type of return value of the KafkaFuture, like ListOffsetsResultInfo, etc.
* @param <O> The type of configuration option, like ListOffsetsOptions, etc
*/
private <T, O extends AbstractOptions<O>> Call getMetadataCall(MetadataOperationContext<T, O> context, Supplier<List<Call>> nextCalls) {
return new Call("metadata", context.deadline(), new LeastLoadedNodeProvider()) {
@Override
MetadataRequest.Builder createRequest(int timeoutMs) {
return new MetadataRequest.Builder(new MetadataRequestData().setTopics(convertToMetadataRequestTopic(context.topics())).setAllowAutoTopicCreation(false));
}
@Override
void handleResponse(AbstractResponse abstractResponse) {
MetadataResponse response = (MetadataResponse) abstractResponse;
MetadataOperationContext.handleMetadataErrors(response);
context.setResponse(Optional.of(response));
for (Call call : nextCalls.get()) {
runnable.call(call, time.milliseconds());
}
}
@Override
void handleFailure(Throwable throwable) {
for (KafkaFutureImpl<T> future : context.futures().values()) {
future.completeExceptionally(throwable);
}
}
};
}
use of org.apache.kafka.common.requests.AbstractResponse in project kafka by apache.
the class KafkaAdminClient method getCreatePartitionsCall.
private Call getCreatePartitionsCall(final CreatePartitionsOptions options, final Map<String, KafkaFutureImpl<Void>> futures, final CreatePartitionsTopicCollection topics, final Map<String, ThrottlingQuotaExceededException> quotaExceededExceptions, final long now, final long deadline) {
return new Call("createPartitions", deadline, new ControllerNodeProvider()) {
@Override
public CreatePartitionsRequest.Builder createRequest(int timeoutMs) {
return new CreatePartitionsRequest.Builder(new CreatePartitionsRequestData().setTopics(topics).setValidateOnly(options.validateOnly()).setTimeoutMs(timeoutMs));
}
@Override
public void handleResponse(AbstractResponse abstractResponse) {
// Check for controller change
handleNotControllerError(abstractResponse);
// Handle server responses for particular topics.
final CreatePartitionsResponse response = (CreatePartitionsResponse) abstractResponse;
final CreatePartitionsTopicCollection retryTopics = new CreatePartitionsTopicCollection();
final Map<String, ThrottlingQuotaExceededException> retryTopicQuotaExceededExceptions = new HashMap<>();
for (CreatePartitionsTopicResult result : response.data().results()) {
KafkaFutureImpl<Void> future = futures.get(result.name());
if (future == null) {
log.warn("Server response mentioned unknown topic {}", result.name());
} else {
ApiError error = new ApiError(result.errorCode(), result.errorMessage());
if (error.isFailure()) {
if (error.is(Errors.THROTTLING_QUOTA_EXCEEDED)) {
ThrottlingQuotaExceededException quotaExceededException = new ThrottlingQuotaExceededException(response.throttleTimeMs(), error.messageWithFallback());
if (options.shouldRetryOnQuotaViolation()) {
retryTopics.add(topics.find(result.name()).duplicate());
retryTopicQuotaExceededExceptions.put(result.name(), quotaExceededException);
} else {
future.completeExceptionally(quotaExceededException);
}
} else {
future.completeExceptionally(error.exception());
}
} else {
future.complete(null);
}
}
}
// If there are topics to retry, retry them; complete unrealized futures otherwise.
if (retryTopics.isEmpty()) {
// The server should send back a response for every topic. But do a sanity check anyway.
completeUnrealizedFutures(futures.entrySet().stream(), topic -> "The controller response did not contain a result for topic " + topic);
} else {
final long now = time.milliseconds();
final Call call = getCreatePartitionsCall(options, futures, retryTopics, retryTopicQuotaExceededExceptions, now, deadline);
runnable.call(call, now);
}
}
@Override
void handleFailure(Throwable throwable) {
// If there were any topics retries due to a quota exceeded exception, we propagate
// the initial error back to the caller if the request timed out.
maybeCompleteQuotaExceededException(options.shouldRetryOnQuotaViolation(), throwable, futures, quotaExceededExceptions, (int) (time.milliseconds() - now));
// Fail all the other remaining futures
completeAllExceptionally(futures.values(), throwable);
}
};
}
use of org.apache.kafka.common.requests.AbstractResponse in project kafka by apache.
the class KafkaAdminClient method updateFeatures.
@Override
public UpdateFeaturesResult updateFeatures(final Map<String, FeatureUpdate> featureUpdates, final UpdateFeaturesOptions options) {
if (featureUpdates.isEmpty()) {
throw new IllegalArgumentException("Feature updates can not be null or empty.");
}
final Map<String, KafkaFutureImpl<Void>> updateFutures = new HashMap<>();
for (final Map.Entry<String, FeatureUpdate> entry : featureUpdates.entrySet()) {
final String feature = entry.getKey();
if (Utils.isBlank(feature)) {
throw new IllegalArgumentException("Provided feature can not be empty.");
}
updateFutures.put(entry.getKey(), new KafkaFutureImpl<>());
}
final long now = time.milliseconds();
final Call call = new Call("updateFeatures", calcDeadlineMs(now, options.timeoutMs()), new ControllerNodeProvider()) {
@Override
UpdateFeaturesRequest.Builder createRequest(int timeoutMs) {
final UpdateFeaturesRequestData.FeatureUpdateKeyCollection featureUpdatesRequestData = new UpdateFeaturesRequestData.FeatureUpdateKeyCollection();
for (Map.Entry<String, FeatureUpdate> entry : featureUpdates.entrySet()) {
final String feature = entry.getKey();
final FeatureUpdate update = entry.getValue();
final UpdateFeaturesRequestData.FeatureUpdateKey requestItem = new UpdateFeaturesRequestData.FeatureUpdateKey();
requestItem.setFeature(feature);
requestItem.setMaxVersionLevel(update.maxVersionLevel());
requestItem.setAllowDowngrade(update.allowDowngrade());
featureUpdatesRequestData.add(requestItem);
}
return new UpdateFeaturesRequest.Builder(new UpdateFeaturesRequestData().setTimeoutMs(timeoutMs).setFeatureUpdates(featureUpdatesRequestData));
}
@Override
void handleResponse(AbstractResponse abstractResponse) {
final UpdateFeaturesResponse response = (UpdateFeaturesResponse) abstractResponse;
ApiError topLevelError = response.topLevelError();
switch(topLevelError.error()) {
case NONE:
for (final UpdatableFeatureResult result : response.data().results()) {
final KafkaFutureImpl<Void> future = updateFutures.get(result.feature());
if (future == null) {
log.warn("Server response mentioned unknown feature {}", result.feature());
} else {
final Errors error = Errors.forCode(result.errorCode());
if (error == Errors.NONE) {
future.complete(null);
} else {
future.completeExceptionally(error.exception(result.errorMessage()));
}
}
}
// The server should send back a response for every feature, but we do a sanity check anyway.
completeUnrealizedFutures(updateFutures.entrySet().stream(), feature -> "The controller response did not contain a result for feature " + feature);
break;
case NOT_CONTROLLER:
handleNotControllerError(topLevelError.error());
break;
default:
for (final Map.Entry<String, KafkaFutureImpl<Void>> entry : updateFutures.entrySet()) {
entry.getValue().completeExceptionally(topLevelError.exception());
}
break;
}
}
@Override
void handleFailure(Throwable throwable) {
completeAllExceptionally(updateFutures.values(), throwable);
}
};
runnable.call(call, now);
return new UpdateFeaturesResult(new HashMap<>(updateFutures));
}
Aggregations