io.tarantool.driver.core.ProxyTarantoolClient 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.TarantoolCallOperations;
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.DDLMetadataContainerResult;
import io.tarantool.driver.api.metadata.TarantoolMetadataOperations;
import io.tarantool.driver.api.metadata.TarantoolMetadataProvider;
import io.tarantool.driver.api.metadata.TarantoolSpaceMetadata;
import io.tarantool.driver.api.proxy.ProxyOperationsMappingConfig;
import io.tarantool.driver.api.space.TarantoolSpaceOperations;
import io.tarantool.driver.core.metadata.DDLTarantoolSpaceMetadataConverter;
import io.tarantool.driver.core.metadata.ProxyMetadataProvider;
import io.tarantool.driver.core.metadata.TarantoolMetadata;
import io.tarantool.driver.exceptions.TarantoolClientException;
import io.tarantool.driver.exceptions.TarantoolSpaceNotFoundException;
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 io.tarantool.driver.utils.Assert;
import org.msgpack.value.Value;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
/**
* Client implementation that decorates a {@link TarantoolClient} instance, proxying all CRUD operations through the
* instance's call
method to the proxy functions defined on the Tarantool instance(s).
*
* Proxy functions to be called can be specified by overriding the methods of the implemented
* {@link ProxyOperationsMappingConfig} interface. These functions must be public API functions available on the
* Tarantool instance for the connected API user.
*
* It is recommended to use this client with the CRUD module (
* https://github.com/tarantool/crud) installed on the target Tarantool instance. Be sure that the server instances
* you are connecting to with this client have the {@code crud-router} role enabled.
*
* The default implementation of metadata retrieving function is provided by the DDL module
* (https://github.com/tarantool/ddl). It is available by default
* on the Cartridge instances. In the other cases, you'll have to expose the DDL module as public API on the target
* Tarantool instance or use some other implementation of that function.
*
* See
* https://github.com/tarantool/examples/blob/master/profile-storage/README.md
*
* @param target tuple type
* @param target tuple collection type
* @author Alexey Kuzin
* @author Sergey Volgin
*/
public abstract class ProxyTarantoolClient>
implements TarantoolClient {
private final TarantoolClientConfig config;
private final TarantoolClient client;
private final ProxyOperationsMappingConfig mappingConfig;
private final ProxyMetadataProvider metadataProvider;
private final AtomicReference metadataHolder = new AtomicReference<>();
/**
* Basic constructor
*
* @param decoratedClient configured Tarantool client
* @param mappingConfig config for proxy operations mapping
*/
public ProxyTarantoolClient(TarantoolClient decoratedClient, ProxyOperationsMappingConfig mappingConfig) {
Assert.notNull(decoratedClient, "Decorated client must not be null");
Assert.notNull(mappingConfig, "Proxy operations mapping config must not be null");
this.client = decoratedClient;
this.config = decoratedClient.getConfig();
this.mappingConfig = mappingConfig;
this.client.getConnectionListeners().clear();
this.metadataProvider = new ProxyMetadataProvider(client, mappingConfig.getGetSchemaFunctionName(),
DDLTarantoolSpaceMetadataConverter.getInstance(), DDLMetadataContainerResult.class);
}
@Override
public TarantoolSpaceOperations space(int spaceId) throws TarantoolClientException {
Assert.state(spaceId > 0, "Space ID must be greater than 0");
TarantoolMetadataOperations metadata = this.metadata();
Optional meta = metadata.getSpaceById(spaceId);
if (!meta.isPresent()) {
throw new TarantoolSpaceNotFoundException(spaceId);
}
return spaceOperations(config, this, mappingConfig, metadata, meta.get());
}
@Override
public TarantoolSpaceOperations space(String spaceName) {
Assert.hasText(spaceName, "Space name must not be null or empty");
TarantoolMetadataOperations metadata = this.metadata();
Optional meta = metadata.getSpaceByName(spaceName);
if (!meta.isPresent()) {
throw new TarantoolSpaceNotFoundException(spaceName);
}
return spaceOperations(config, this, mappingConfig, metadata, meta.get());
}
/**
* Creates a space API implementation instance for the specified space
*
* @param config Tarantool client configuration
* @param client configured client instance
* @param mappingConfig proxy operations mapping configuration
* @param metadata metadata operations
* @param spaceMetadata current space metadata
* @return space API implementation instance
*/
protected abstract TarantoolSpaceOperations spaceOperations(
TarantoolClientConfig config,
TarantoolCallOperations client,
ProxyOperationsMappingConfig mappingConfig,
TarantoolMetadataOperations metadata,
TarantoolSpaceMetadata spaceMetadata);
@Override
public TarantoolMetadataOperations metadata() throws TarantoolClientException {
if (metadataHolder.get() == null) {
this.metadataHolder.compareAndSet(null, new TarantoolMetadata(metadataProvider()));
}
return metadataHolder.get();
}
@Override
public TarantoolMetadataProvider metadataProvider() {
return metadataProvider;
}
@Override
public TarantoolClientConfig getConfig() {
return client.getConfig();
}
@Override
public TarantoolVersion getVersion() throws TarantoolClientException {
return client.getVersion();
}
@Override
public TarantoolConnectionListeners getConnectionListeners() {
return this.client.getConnectionListeners();
}
@Override
public ResultMapperFactoryFactory getResultMapperFactoryFactory() {
return client.getResultMapperFactoryFactory();
}
@Override
public CompletableFuture> call(String functionName) throws TarantoolClientException {
return client.call(functionName);
}
@Override
public CompletableFuture> call(String functionName, Object... arguments)
throws TarantoolClientException {
return client.call(functionName, Arrays.asList(arguments));
}
@Override
public CompletableFuture> call(String functionName, List> arguments)
throws TarantoolClientException {
return client.call(functionName, arguments);
}
@Override
public CompletableFuture> call(String functionName, List> arguments, MessagePackMapper mapper)
throws TarantoolClientException {
return client.call(functionName, arguments, mapper);
}
@Override
public CompletableFuture> call(String functionName, Class entityClass)
throws TarantoolClientException {
return client.call(functionName, entityClass);
}
@Override
public CompletableFuture> call(
String functionName,
CallResultMapper, SingleValueCallResult>> resultMapper)
throws TarantoolClientException {
return client.call(functionName, resultMapper);
}
@Override
public CompletableFuture> call(String functionName, List> arguments, Class entityClass)
throws TarantoolClientException {
return client.call(functionName, arguments, entityClass);
}
@Override
public CompletableFuture> call(
String functionName,
List> arguments,
CallResultMapper, SingleValueCallResult>> resultMapper)
throws TarantoolClientException {
return client.call(functionName, arguments, resultMapper);
}
@Override
public CompletableFuture> call(
String functionName,
List> arguments,
MessagePackObjectMapper argumentsMapper,
Class entityClass) throws TarantoolClientException {
return client.call(functionName, arguments, argumentsMapper, entityClass);
}
@Override
public CompletableFuture> call(
String functionName,
List> arguments,
MessagePackObjectMapper argumentsMapper,
CallResultMapper, SingleValueCallResult>> resultMapper)
throws TarantoolClientException {
return client.call(functionName, arguments, argumentsMapper, resultMapper);
}
@Override
public CompletableFuture callForSingleResult(
String functionName,
List> arguments,
MessagePackObjectMapper argumentsMapper,
Class resultClass)
throws TarantoolClientException {
return client.callForSingleResult(functionName, arguments, argumentsMapper, resultClass);
}
@Override
public CompletableFuture callForSingleResult(
String functionName,
List> arguments,
MessagePackObjectMapper argumentsMapper,
ValueConverter valueConverter)
throws TarantoolClientException {
return client.callForSingleResult(functionName, arguments, argumentsMapper, valueConverter);
}
@Override
public CompletableFuture callForSingleResult(
String functionName,
List> arguments,
MessagePackObjectMapper argumentsMapper,
CallResultMapper> resultMapper)
throws TarantoolClientException {
return client.callForSingleResult(functionName, arguments, argumentsMapper, resultMapper);
}
@Override
public CompletableFuture callForSingleResult(String functionName, List> arguments, Class resultClass)
throws TarantoolClientException {
return client.callForSingleResult(functionName, arguments, resultClass);
}
@Override
public CompletableFuture callForSingleResult(
String functionName,
List> arguments,
ValueConverter valueConverter)
throws TarantoolClientException {
return client.callForSingleResult(functionName, arguments, valueConverter);
}
@Override
public CompletableFuture callForSingleResult(
String functionName,
List> arguments,
CallResultMapper> resultMapper) throws TarantoolClientException {
return client.callForSingleResult(functionName, arguments, resultMapper);
}
@Override
public CompletableFuture callForSingleResult(String functionName, Class resultClass)
throws TarantoolClientException {
return client.callForSingleResult(functionName, resultClass);
}
@Override
public CompletableFuture callForSingleResult(String functionName, ValueConverter valueConverter)
throws TarantoolClientException {
return client.callForSingleResult(functionName, valueConverter);
}
@Override
public CompletableFuture callForSingleResult(
String functionName,
CallResultMapper> resultMapper) throws TarantoolClientException {
return client.callForSingleResult(functionName, resultMapper);
}
@Override
public > CompletableFuture callForMultiResult(
String functionName,
List> arguments,
MessagePackObjectMapper argumentsMapper,
Supplier resultContainerSupplier,
Class resultClass) throws TarantoolClientException {
return client.callForMultiResult(
functionName, arguments, argumentsMapper, resultContainerSupplier, resultClass);
}
@Override
public > CompletableFuture callForMultiResult(
String functionName,
List> arguments,
MessagePackObjectMapper argumentsMapper,
Supplier resultContainerSupplier,
ValueConverter valueConverter) throws TarantoolClientException {
return client.callForMultiResult(
functionName, arguments, argumentsMapper, resultContainerSupplier, valueConverter);
}
@Override
public > CompletableFuture callForMultiResult(
String functionName,
List> arguments,
MessagePackObjectMapper argumentsMapper,
CallResultMapper> resultMapper) throws TarantoolClientException {
return client.callForMultiResult(functionName, arguments, argumentsMapper, resultMapper);
}
@Override
public > CompletableFuture callForMultiResult(
String functionName,
List> arguments,
Supplier resultContainerSupplier,
Class resultClass)
throws TarantoolClientException {
return client.callForMultiResult(functionName, arguments, resultContainerSupplier, resultClass);
}
@Override
public > CompletableFuture callForMultiResult(
String functionName,
List> arguments,
Supplier resultContainerSupplier,
ValueConverter valueConverter)
throws TarantoolClientException {
return client.callForMultiResult(functionName, arguments, resultContainerSupplier, valueConverter);
}
@Override
public > CompletableFuture callForMultiResult(
String functionName,
List> arguments,
CallResultMapper> resultMapper) throws TarantoolClientException {
return client.callForMultiResult(functionName, arguments, resultMapper);
}
@Override
public > CompletableFuture callForMultiResult(
String functionName,
Supplier resultContainerSupplier,
Class resultClass)
throws TarantoolClientException {
return client.callForMultiResult(functionName, resultContainerSupplier, resultClass);
}
@Override
public > CompletableFuture callForMultiResult(
String functionName,
Supplier resultContainerSupplier,
ValueConverter valueConverter)
throws TarantoolClientException {
return client.callForMultiResult(functionName, resultContainerSupplier, valueConverter);
}
@Override
public > CompletableFuture callForMultiResult(
String functionName,
CallResultMapper> resultMapper)
throws TarantoolClientException {
return client.callForMultiResult(functionName, resultMapper);
}
@Override
public CompletableFuture> eval(String expression) throws TarantoolClientException {
return client.eval(expression);
}
@Override
public CompletableFuture> eval(String expression, List> arguments) throws TarantoolClientException {
return client.eval(expression, arguments);
}
@Override
public CompletableFuture> eval(String expression, MessagePackValueMapper resultMapper)
throws TarantoolClientException {
return client.eval(expression, resultMapper);
}
@Override
public CompletableFuture> eval(String expression, List> arguments, MessagePackValueMapper resultMapper)
throws TarantoolClientException {
return client.eval(expression, arguments, resultMapper);
}
@Override
public CompletableFuture> eval(
String expression,
List> arguments,
MessagePackObjectMapper argumentsMapper,
MessagePackValueMapper resultMapper) throws TarantoolClientException {
return client.eval(expression, arguments, argumentsMapper, resultMapper);
}
@Override
public boolean refresh() {
return this.client.refresh();
}
@Override
public void close() throws Exception {
this.client.close();
}
/**
* Getter for {@link ProxyOperationsMappingConfig}
*
* @return {@link ProxyOperationsMappingConfig} instance
*/
ProxyOperationsMappingConfig getMappingConfig() {
return mappingConfig;
}
/**
* Getter for decorated client
*
* @return decorated client {@link TarantoolClient}
*/
TarantoolClient getClient() {
return client;
}
}