All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.tarantool.driver.core.RetryingTarantoolClient Maven / Gradle / Ivy

Go to download

Tarantool Cartridge driver for Tarantool versions 1.10+ based on Netty framework

There is a newer version: 0.14.0
Show newest version
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> call( String functionName, Class entityClass) throws TarantoolClientException { return wrapOperation(() -> client.call(functionName, entityClass)); } @Override public CompletableFuture> call( String functionName, CallResultMapper, SingleValueCallResult>> resultMapper) throws TarantoolClientException { return wrapOperation(() -> client.call(functionName, resultMapper)); } @Override public CompletableFuture> call( String functionName, List arguments, Class entityClass) throws TarantoolClientException { return wrapOperation(() -> client.call(functionName, arguments, entityClass)); } @Override public CompletableFuture> call( String functionName, List arguments, CallResultMapper, SingleValueCallResult>> resultMapper) throws TarantoolClientException { return wrapOperation(() -> client.call(functionName, arguments, resultMapper)); } @Override public CompletableFuture> call( String functionName, List arguments, MessagePackObjectMapper argumentsMapper, Class entityClass) throws TarantoolClientException { return wrapOperation(() -> client.call(functionName, arguments, argumentsMapper, entityClass)); } @Override public CompletableFuture> call( String functionName, List arguments, MessagePackObjectMapper argumentsMapper, CallResultMapper, SingleValueCallResult>> 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) { try { return wrapOperation(() -> CompletableFuture.supplyAsync(spaceSupplier, executor)).get(); } catch (InterruptedException e) { throw new CompletionException(e); } catch (ExecutionException e) { throw new CompletionException(e.getCause()); } } }