
org.apache.kafka.clients.consumer.internals.RequestFuture 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.clients.consumer.internals;
import org.apache.kafka.common.errors.RetriableException;
import org.apache.kafka.common.protocol.Errors;
import java.util.ArrayList;
import java.util.List;
/**
* Result of an asynchronous request from {@link ConsumerNetworkClient}. Use {@link ConsumerNetworkClient#poll(long)}
* (and variants) to finish a request future. Use {@link #isDone()} to check if the future is complete, and
* {@link #succeeded()} to check if the request completed successfully. Typical usage might look like this:
*
*
* RequestFuture future = client.send(api, request);
* client.poll(future);
*
* if (future.succeeded()) {
* ClientResponse response = future.value();
* // Handle response
* } else {
* throw future.exception();
* }
*
*
* @param Return type of the result (Can be Void if there is no response)
*/
public class RequestFuture {
private boolean isDone = false;
private T value;
private RuntimeException exception;
private List> listeners = new ArrayList<>();
/**
* Check whether the response is ready to be handled
* @return true if the response is ready, false otherwise
*/
public boolean isDone() {
return isDone;
}
/**
* Get the value corresponding to this request (only available if the request succeeded)
* @return the value if it exists or null
*/
public T value() {
return value;
}
/**
* Check if the request succeeded;
* @return true if the request completed and was successful
*/
public boolean succeeded() {
return isDone && exception == null;
}
/**
* Check if the request failed.
* @return true if the request completed with a failure
*/
public boolean failed() {
return isDone && exception != null;
}
/**
* Check if the request is retriable (convenience method for checking if
* the exception is an instance of {@link RetriableException}.
* @return true if it is retriable, false otherwise
*/
public boolean isRetriable() {
return exception instanceof RetriableException;
}
/**
* Get the exception from a failed result (only available if the request failed)
* @return The exception if it exists or null
*/
public RuntimeException exception() {
return exception;
}
/**
* Complete the request successfully. After this call, {@link #succeeded()} will return true
* and the value can be obtained through {@link #value()}.
* @param value corresponding value (or null if there is none)
*/
public void complete(T value) {
if (isDone)
throw new IllegalStateException("Invalid attempt to complete a request future which is already complete");
this.value = value;
this.isDone = true;
fireSuccess();
}
/**
* Raise an exception. The request will be marked as failed, and the caller can either
* handle the exception or throw it.
* @param e corresponding exception to be passed to caller
*/
public void raise(RuntimeException e) {
if (isDone)
throw new IllegalStateException("Invalid attempt to complete a request future which is already complete");
this.exception = e;
this.isDone = true;
fireFailure();
}
/**
* Raise an error. The request will be marked as failed.
* @param error corresponding error to be passed to caller
*/
public void raise(Errors error) {
raise(error.exception());
}
private void fireSuccess() {
for (RequestFutureListener listener : listeners)
listener.onSuccess(value);
}
private void fireFailure() {
for (RequestFutureListener listener : listeners)
listener.onFailure(exception);
}
/**
* Add a listener which will be notified when the future completes
* @param listener
*/
public void addListener(RequestFutureListener listener) {
if (isDone) {
if (exception != null)
listener.onFailure(exception);
else
listener.onSuccess(value);
} else {
this.listeners.add(listener);
}
}
/**
* Convert from a request future of one type to another type
* @param adapter The adapter which does the conversion
* @param The type of the future adapted to
* @return The new future
*/
public RequestFuture compose(final RequestFutureAdapter adapter) {
final RequestFuture adapted = new RequestFuture();
addListener(new RequestFutureListener() {
@Override
public void onSuccess(T value) {
adapter.onSuccess(value, adapted);
}
@Override
public void onFailure(RuntimeException e) {
adapter.onFailure(e, adapted);
}
});
return adapted;
}
public void chain(final RequestFuture future) {
addListener(new RequestFutureListener() {
@Override
public void onSuccess(T value) {
future.complete(value);
}
@Override
public void onFailure(RuntimeException e) {
future.raise(e);
}
});
}
public static RequestFuture failure(RuntimeException e) {
RequestFuture future = new RequestFuture();
future.raise(e);
return future;
}
public static RequestFuture voidSuccess() {
RequestFuture future = new RequestFuture();
future.complete(null);
return future;
}
public static RequestFuture coordinatorNotAvailable() {
return failure(Errors.GROUP_COORDINATOR_NOT_AVAILABLE.exception());
}
public static RequestFuture leaderNotAvailable() {
return failure(Errors.LEADER_NOT_AVAILABLE.exception());
}
public static RequestFuture noBrokersAvailable() {
return failure(new NoAvailableBrokersException());
}
public static RequestFuture staleMetadata() {
return failure(new StaleMetadataException());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy