io.tarantool.driver.core.RetryingTarantoolClient Maven / Gradle / Ivy
Show all versions of cartridge-driver Show documentation
package io.tarantool.driver.core;
import io.tarantool.driver.TarantoolVersion;
import io.tarantool.driver.api.MultiValueCallResult;
import io.tarantool.driver.api.SingleValueCallResult;
import io.tarantool.driver.api.TarantoolClient;
import io.tarantool.driver.api.TarantoolClientConfig;
import io.tarantool.driver.api.TarantoolResult;
import io.tarantool.driver.api.connection.TarantoolConnectionListeners;
import io.tarantool.driver.api.metadata.TarantoolMetadataOperations;
import io.tarantool.driver.api.metadata.TarantoolMetadataProvider;
import io.tarantool.driver.api.retry.RequestRetryPolicy;
import io.tarantool.driver.api.retry.RequestRetryPolicyFactory;
import io.tarantool.driver.api.space.TarantoolSpaceOperations;
import io.tarantool.driver.core.space.RetryingTarantoolSpace;
import io.tarantool.driver.exceptions.TarantoolClientException;
import io.tarantool.driver.mappers.CallResultMapper;
import io.tarantool.driver.mappers.MessagePackMapper;
import io.tarantool.driver.mappers.MessagePackObjectMapper;
import io.tarantool.driver.mappers.MessagePackValueMapper;
import io.tarantool.driver.mappers.converters.ValueConverter;
import io.tarantool.driver.mappers.factories.ResultMapperFactoryFactory;
import io.tarantool.driver.protocol.Packable;
import org.msgpack.value.Value;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.function.Supplier;
/**
* Client implementation that decorates a {@link TarantoolClient} instance, allowing to specify a retry policy for
* all requests made through this client instance.
*
* Retry policy is applied before the possible exception is propagated to the user in the wrapping CompletableFuture.
* Since that, the timeout specified for waiting the future result, bounds externally the overall operation time.
*
* @param target tuple type
* @param target tuple collection type
* @author Alexey Kuzin
*/
public abstract class RetryingTarantoolClient>
implements TarantoolClient {
private final TarantoolClient client;
private final RequestRetryPolicyFactory retryPolicyFactory;
private final Executor executor;
/**
* Basic constructor. {@link Executors#newWorkStealingPool()} is used for executor by default.
*
* @param decoratedClient configured Tarantool client
* @param retryPolicyFactory request retrying policy settings
*/
public RetryingTarantoolClient(
TarantoolClient decoratedClient,
RequestRetryPolicyFactory retryPolicyFactory) {
this(decoratedClient, retryPolicyFactory, Executors.newWorkStealingPool());
}
/**
* Basic constructor
*
* @param decoratedClient configured Tarantool client
* @param retryPolicyFactory request retrying policy settings
* @param executor executor service for retry callbacks
*/
public RetryingTarantoolClient(
TarantoolClient decoratedClient,
RequestRetryPolicyFactory retryPolicyFactory,
Executor executor) {
this.client = decoratedClient;
this.retryPolicyFactory = retryPolicyFactory;
this.executor = executor;
}
@Override
public TarantoolMetadataProvider metadataProvider() {
return client.metadataProvider();
}
@Override
public TarantoolClientConfig getConfig() {
return client.getConfig();
}
@Override
public TarantoolVersion getVersion() throws TarantoolClientException {
return client.getVersion();
}
@Override
public TarantoolSpaceOperations space(String spaceName) throws TarantoolClientException {
TarantoolSpaceOperations wrappedSpace = getTarantoolSpaceOperationsRetrying(
() -> client.space(spaceName));
return spaceOperations(wrappedSpace, retryPolicyFactory, executor);
}
@Override
public TarantoolSpaceOperations space(int spaceId) throws TarantoolClientException {
TarantoolSpaceOperations wrappedSpace = getTarantoolSpaceOperationsRetrying(
() -> client.space(spaceId));
return spaceOperations(wrappedSpace, retryPolicyFactory, executor);
}
/**
* Creates a space API implementation instance for the specified space
*
* @param decoratedSpaceOperations space API implementation form the decorated Tarantool client instance
* @param retryPolicyFactory request retrying policy factory
* @param executor executor service for retry callbacks
* @return space API implementation instance
*/
protected abstract RetryingTarantoolSpace spaceOperations(
TarantoolSpaceOperations decoratedSpaceOperations,
RequestRetryPolicyFactory retryPolicyFactory,
Executor executor);
@Override
public TarantoolMetadataOperations metadata() throws TarantoolClientException {
return client.metadata();
}
@Override
public TarantoolConnectionListeners getConnectionListeners() {
return client.getConnectionListeners();
}
@Override
public CompletableFuture> call(String functionName) throws TarantoolClientException {
return wrapOperation(() -> client.call(functionName));
}
@Override
public CompletableFuture> call(String functionName, Object... arguments) throws TarantoolClientException {
return wrapOperation(() -> client.call(functionName, arguments));
}
@Override
public CompletableFuture> call(String functionName, List> arguments) throws TarantoolClientException {
return wrapOperation(() -> client.call(functionName, arguments));
}
@Override
public CompletableFuture> call(
String functionName,
List> arguments,
MessagePackMapper mapper) throws TarantoolClientException {
return wrapOperation(() -> client.call(functionName, arguments, mapper));
}
@Override
public CompletableFuture> callForTupleResult(String functionName, Class entityClass)
throws TarantoolClientException {
return wrapOperation(() -> client.callForTupleResult(functionName, entityClass));
}
@Override
public CompletableFuture call(String functionName,
CallResultMapper> resultMapper) throws TarantoolClientException {
return wrapOperation(() -> client.call(functionName, resultMapper));
}
@Override
public CompletableFuture> callForTupleResult(String functionName, List> arguments,
Class entityClass) throws TarantoolClientException {
return wrapOperation(() -> client.callForTupleResult(functionName, arguments, entityClass));
}
@Override
public CompletableFuture call(String functionName, List> arguments,
CallResultMapper> resultMapper) throws TarantoolClientException {
return wrapOperation(() -> client.call(functionName, arguments, resultMapper));
}
@Override
public CompletableFuture> callForTupleResult(String functionName, List> arguments,
MessagePackObjectMapper argumentsMapper, Class entityClass) throws TarantoolClientException {
return wrapOperation(() -> client.callForTupleResult(functionName, arguments, argumentsMapper, entityClass));
}
@Override
public CompletableFuture call(String functionName, List> arguments,
MessagePackObjectMapper argumentsMapper, CallResultMapper> resultMapper)
throws TarantoolClientException {
return wrapOperation(() -> client.call(functionName, arguments, argumentsMapper, resultMapper));
}
@Override
public CompletableFuture callForSingleResult(
String functionName,
List> arguments,
MessagePackObjectMapper argumentsMapper,
Class resultClass) throws TarantoolClientException {
return wrapOperation(() -> client.callForSingleResult(functionName, arguments, argumentsMapper, resultClass));
}
@Override
public CompletableFuture callForSingleResult(
String functionName,
List> arguments,
MessagePackObjectMapper argumentsMapper,
ValueConverter valueConverter)
throws TarantoolClientException {
return wrapOperation(() ->
client.callForSingleResult(functionName, arguments, argumentsMapper, valueConverter));
}
@Override
public CompletableFuture callForSingleResult(
String functionName,
List> arguments,
MessagePackObjectMapper argumentsMapper,
CallResultMapper> resultMapper)
throws TarantoolClientException {
return wrapOperation(() -> client.callForSingleResult(functionName, arguments, argumentsMapper, resultMapper));
}
@Override
public CompletableFuture callForSingleResult(String functionName, List> arguments, Class resultClass)
throws TarantoolClientException {
return wrapOperation(() -> client.callForSingleResult(functionName, arguments, resultClass));
}
@Override
public CompletableFuture callForSingleResult(
String functionName,
List> arguments,
ValueConverter valueConverter)
throws TarantoolClientException {
return wrapOperation(() -> client.callForSingleResult(functionName, arguments, valueConverter));
}
@Override
public CompletableFuture callForSingleResult(
String functionName,
List> arguments,
CallResultMapper> resultMapper)
throws TarantoolClientException {
return wrapOperation(() -> client.callForSingleResult(functionName, arguments, resultMapper));
}
@Override
public CompletableFuture callForSingleResult(String functionName, Class resultClass)
throws TarantoolClientException {
return wrapOperation(() -> client.callForSingleResult(functionName, resultClass));
}
@Override
public CompletableFuture callForSingleResult(String functionName, ValueConverter valueConverter)
throws TarantoolClientException {
return wrapOperation(() -> client.callForSingleResult(functionName, valueConverter));
}
@Override
public CompletableFuture callForSingleResult(
String functionName,
CallResultMapper> resultMapper)
throws TarantoolClientException {
return wrapOperation(() -> client.callForSingleResult(functionName, resultMapper));
}
@Override
public > CompletableFuture callForMultiResult(
String functionName,
List> arguments,
MessagePackObjectMapper argumentsMapper,
Supplier resultContainerSupplier,
Class resultClass)
throws TarantoolClientException {
return wrapOperation(() -> client.callForMultiResult(
functionName, arguments, argumentsMapper, resultContainerSupplier, resultClass));
}
@Override
public > CompletableFuture callForMultiResult(
String functionName,
List> arguments,
MessagePackObjectMapper argumentsMapper,
Supplier resultContainerSupplier,
ValueConverter valueConverter)
throws TarantoolClientException {
return wrapOperation(() -> client.callForMultiResult(
functionName, arguments, argumentsMapper, resultContainerSupplier, valueConverter));
}
@Override
public > CompletableFuture callForMultiResult(
String functionName,
List> arguments,
MessagePackObjectMapper argumentsMapper,
CallResultMapper> resultMapper)
throws TarantoolClientException {
return wrapOperation(() -> client.callForMultiResult(functionName, arguments, argumentsMapper, resultMapper));
}
@Override
public > CompletableFuture callForMultiResult(
String functionName,
List> arguments,
Supplier resultContainerSupplier,
Class resultClass)
throws TarantoolClientException {
return wrapOperation(() -> client.callForMultiResult(
functionName, arguments, resultContainerSupplier, resultClass));
}
@Override
public > CompletableFuture callForMultiResult(
String functionName,
List> arguments,
Supplier resultContainerSupplier,
ValueConverter valueConverter)
throws TarantoolClientException {
return wrapOperation(() -> client.callForMultiResult(
functionName, arguments, resultContainerSupplier, valueConverter));
}
@Override
public > CompletableFuture callForMultiResult(
String functionName,
List> arguments,
CallResultMapper> resultMapper) throws TarantoolClientException {
return wrapOperation(() -> client.callForMultiResult(functionName, arguments, resultMapper));
}
@Override
public > CompletableFuture callForMultiResult(
String functionName,
Supplier resultContainerSupplier,
Class resultClass)
throws TarantoolClientException {
return wrapOperation(() -> client.callForMultiResult(functionName, resultContainerSupplier, resultClass));
}
@Override
public > CompletableFuture callForMultiResult(
String functionName,
Supplier resultContainerSupplier,
ValueConverter valueConverter)
throws TarantoolClientException {
return wrapOperation(() -> client.callForMultiResult(functionName, resultContainerSupplier, valueConverter));
}
@Override
public > CompletableFuture callForMultiResult(
String functionName,
CallResultMapper> resultMapper) throws TarantoolClientException {
return wrapOperation(() -> client.callForMultiResult(functionName, resultMapper));
}
@Override
public ResultMapperFactoryFactory getResultMapperFactoryFactory() {
return client.getResultMapperFactoryFactory();
}
@Override
public CompletableFuture> eval(String expression) throws TarantoolClientException {
return wrapOperation(() -> client.eval(expression));
}
@Override
public CompletableFuture> eval(String expression, List> arguments) throws TarantoolClientException {
return wrapOperation(() -> client.eval(expression, arguments));
}
@Override
public CompletableFuture> eval(
String expression,
MessagePackValueMapper resultMapper) throws TarantoolClientException {
return wrapOperation(() -> client.eval(expression, resultMapper));
}
@Override
public CompletableFuture> eval(
String expression,
List> arguments,
MessagePackValueMapper resultMapper) throws TarantoolClientException {
return wrapOperation(() -> client.eval(expression, arguments, resultMapper));
}
@Override
public CompletableFuture> eval(
String expression, List> arguments,
MessagePackObjectMapper argumentsMapper,
MessagePackValueMapper resultMapper) throws TarantoolClientException {
return wrapOperation(() -> client.eval(expression, arguments, argumentsMapper, resultMapper));
}
@Override
public boolean refresh() {
return this.client.refresh();
}
@Override
public void close() throws Exception {
client.close();
}
/**
* Getter for {@link RequestRetryPolicyFactory}
*
* @return {@link RequestRetryPolicyFactory}
*/
protected RequestRetryPolicyFactory getRetryPolicyFactory() {
return retryPolicyFactory;
}
/**
* Getter for decorated client
*
* @return decorated client {@link TarantoolClient}
*/
protected TarantoolClient getClient() {
return client;
}
private CompletableFuture wrapOperation(Supplier> operation) {
RequestRetryPolicy retryPolicy = retryPolicyFactory.create();
return retryPolicy.wrapOperation(operation, executor);
}
private TarantoolSpaceOperations getTarantoolSpaceOperationsRetrying(
Supplier> spaceSupplier) {
CompletableFuture> wrapperForSync = new CompletableFuture<>();
try {
return wrapOperation(() -> {
wrapperForSync.complete(spaceSupplier.get());
return wrapperForSync;
}).get();
} catch (InterruptedException e) {
throw new CompletionException(e);
} catch (ExecutionException e) {
throw new CompletionException(e.getCause());
}
}
}