io.quarkus.redis.runtime.datasource.ReactiveRedisDataSourceImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of quarkus-redis-client Show documentation
Show all versions of quarkus-redis-client Show documentation
Connect to Redis in either imperative or reactive style
package io.quarkus.redis.runtime.datasource;
import static io.quarkus.redis.runtime.datasource.Validation.notNullOrEmpty;
import static io.smallrye.mutiny.helpers.ParameterValidation.doesNotContainNull;
import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull;
import static io.smallrye.mutiny.helpers.ParameterValidation.positiveOrZero;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import com.fasterxml.jackson.core.type.TypeReference;
import io.quarkus.redis.datasource.ReactiveRedisDataSource;
import io.quarkus.redis.datasource.autosuggest.ReactiveAutoSuggestCommands;
import io.quarkus.redis.datasource.bitmap.ReactiveBitMapCommands;
import io.quarkus.redis.datasource.bloom.ReactiveBloomCommands;
import io.quarkus.redis.datasource.countmin.ReactiveCountMinCommands;
import io.quarkus.redis.datasource.cuckoo.ReactiveCuckooCommands;
import io.quarkus.redis.datasource.geo.ReactiveGeoCommands;
import io.quarkus.redis.datasource.graph.ReactiveGraphCommands;
import io.quarkus.redis.datasource.hash.ReactiveHashCommands;
import io.quarkus.redis.datasource.hyperloglog.ReactiveHyperLogLogCommands;
import io.quarkus.redis.datasource.json.ReactiveJsonCommands;
import io.quarkus.redis.datasource.keys.ReactiveKeyCommands;
import io.quarkus.redis.datasource.list.ReactiveListCommands;
import io.quarkus.redis.datasource.pubsub.ReactivePubSubCommands;
import io.quarkus.redis.datasource.search.ReactiveSearchCommands;
import io.quarkus.redis.datasource.set.ReactiveSetCommands;
import io.quarkus.redis.datasource.sortedset.ReactiveSortedSetCommands;
import io.quarkus.redis.datasource.stream.ReactiveStreamCommands;
import io.quarkus.redis.datasource.string.ReactiveStringCommands;
import io.quarkus.redis.datasource.timeseries.ReactiveTimeSeriesCommands;
import io.quarkus.redis.datasource.topk.ReactiveTopKCommands;
import io.quarkus.redis.datasource.transactions.OptimisticLockingTransactionResult;
import io.quarkus.redis.datasource.transactions.ReactiveTransactionalRedisDataSource;
import io.quarkus.redis.datasource.transactions.TransactionResult;
import io.quarkus.redis.datasource.value.ReactiveValueCommands;
import io.smallrye.mutiny.Uni;
import io.vertx.mutiny.core.Vertx;
import io.vertx.mutiny.redis.client.Command;
import io.vertx.mutiny.redis.client.Redis;
import io.vertx.mutiny.redis.client.RedisAPI;
import io.vertx.mutiny.redis.client.RedisConnection;
import io.vertx.mutiny.redis.client.Request;
import io.vertx.mutiny.redis.client.Response;
public class ReactiveRedisDataSourceImpl implements ReactiveRedisDataSource, RedisCommandExecutor {
final Redis redis;
final RedisConnection connection;
private final Vertx vertx;
public ReactiveRedisDataSourceImpl(Vertx vertx, Redis redis, RedisAPI api) {
nonNull(redis, "redis");
nonNull(api, "api");
nonNull(vertx, "vertx");
this.vertx = vertx;
this.redis = redis;
this.connection = null;
}
public ReactiveRedisDataSourceImpl(Vertx vertx, Redis redis, RedisConnection connection) {
nonNull(redis, "redis");
nonNull(connection, "connection");
nonNull(vertx, "vertx");
this.vertx = vertx;
this.redis = redis;
this.connection = connection;
}
@Override
public Uni execute(Request request) {
if (connection != null) {
return connection.send(request);
}
return redis.send(request);
}
@Override
public Uni withTransaction(Function> function) {
nonNull(function, "function");
return redis.connect()
.onItem().transformToUni(connection -> {
ReactiveRedisDataSourceImpl singleConnectionDS = new ReactiveRedisDataSourceImpl(vertx, redis, connection);
TransactionHolder th = new TransactionHolder();
return connection.send(Request.cmd(Command.MULTI))
.chain(x -> function.apply(new ReactiveTransactionalRedisDataSourceImpl(singleConnectionDS, th)))
.chain(ignored -> {
if (!th.discarded()) {
return connection.send(Request.cmd(Command.EXEC));
} else {
return Uni.createFrom().nullItem();
}
})
.onTermination().call(connection::close)
.map(r -> toTransactionResult(r, th));
});
}
@Override
public Uni withTransaction(Function> function,
String... keys) {
nonNull(function, "function");
notNullOrEmpty(keys, "keys");
doesNotContainNull(keys, "keys");
return redis.connect()
.onItem().transformToUni(connection -> {
ReactiveRedisDataSourceImpl singleConnectionDS = new ReactiveRedisDataSourceImpl(vertx, redis, connection);
TransactionHolder th = new TransactionHolder();
return watch(connection, keys) // WATCH keys
.chain(() -> connection.send(Request.cmd(Command.MULTI))
.chain(x -> function
.apply(new ReactiveTransactionalRedisDataSourceImpl(singleConnectionDS, th)))
.onItemOrFailure().transformToUni((x, failure) -> {
if (!th.discarded() && failure == null) {
return connection.send(Request.cmd(Command.EXEC));
} else {
if (!th.discarded()) {
return connection.send(Request.cmd(Command.DISCARD));
}
return Uni.createFrom().nullItem();
}
})
.onTermination().call(connection::close)
.map(r -> toTransactionResult(r, th)));
});
}
private Uni watch(RedisConnection connection, String... keys) {
List watched = List.of(keys);
Request request = Request.cmd(Command.WATCH);
for (String s : watched) {
request.arg(s);
}
return connection.send(request)
.replaceWithVoid();
}
@Override
public Uni> withTransaction(Function> preTxBlock,
BiFunction> tx, String... watchedKeys) {
nonNull(tx, "tx");
notNullOrEmpty(watchedKeys, "watchedKeys");
doesNotContainNull(watchedKeys, "watchedKeys");
nonNull(preTxBlock, "preTxBlock");
return redis.connect()
.onItem().transformToUni(connection -> {
ReactiveRedisDataSourceImpl singleConnectionDS = new ReactiveRedisDataSourceImpl(vertx, redis, connection);
TransactionHolder th = new TransactionHolder();
return watch(connection, watchedKeys) // WATCH keys
.chain(x -> preTxBlock.apply(new ReactiveRedisDataSourceImpl(vertx, redis, connection)))// Execute the pre-tx-block
.chain(input -> connection.send(Request.cmd(Command.MULTI))
.chain(x -> tx
.apply(input, new ReactiveTransactionalRedisDataSourceImpl(singleConnectionDS, th)))
.onItemOrFailure().transformToUni((x, failure) -> {
if (!th.discarded() && failure == null) {
return connection.send(Request.cmd(Command.EXEC));
} else {
if (!th.discarded()) {
return connection.send(Request.cmd(Command.DISCARD))
.replaceWithNull();
}
return Uni.createFrom().nullItem();
}
})
.onTermination().call(connection::close)
.map(r -> toTransactionResult(r, input, th)));
});
}
public static TransactionResult toTransactionResult(Response response, TransactionHolder th) {
if (response == null) {
// Discarded
return TransactionResultImpl.DISCARDED;
}
return new TransactionResultImpl(th.discarded(), th.map(response));
}
public static OptimisticLockingTransactionResult toTransactionResult(Response response, I input,
TransactionHolder th) {
if (response == null) {
// Discarded
return OptimisticLockingTransactionResultImpl.discarded(input);
}
return new OptimisticLockingTransactionResultImpl<>(th.discarded(), input, th.map(response));
}
@Override
public Uni execute(String command, String... args) {
nonNull(command, "command");
return execute(CommandMap.normalize(Command.create(command)), args);
}
@Override
public Uni execute(Command command, String... args) {
nonNull(command, "command");
command = CommandMap.normalize(command);
Request request = Request.cmd(command);
for (String arg : args) {
request.arg(arg);
}
return execute(request);
}
@Override
public Uni execute(io.vertx.redis.client.Command command, String... args) {
nonNull(command, "command");
command = CommandMap.normalize(command);
Request request = Request.newInstance(io.vertx.redis.client.Request.cmd(command));
for (String arg : args) {
request.arg(arg);
}
return execute(request);
}
@Override
public Uni withConnection(Function> function) {
if (connection != null) {
// We are already on a connection, keep this one
return function.apply(this);
}
return redis.connect()
.onItem().transformToUni(connection -> {
ReactiveRedisDataSourceImpl singleConnectionDS = new ReactiveRedisDataSourceImpl(vertx, redis, connection);
return function.apply(singleConnectionDS)
.onTermination().call(connection::close);
});
}
@Override
public Uni select(long index) {
positiveOrZero(index, "index");
return execute(Request.cmd(Command.SELECT).arg(index)).replaceWithVoid();
}
@Override
public Uni flushall() {
return execute(Request.cmd(Command.FLUSHALL)).replaceWithVoid();
}
@Override
public ReactiveHashCommands hash(Class redisKeyType, Class fieldType, Class valueType) {
return new ReactiveHashCommandsImpl<>(this, redisKeyType, fieldType, valueType);
}
@Override
public ReactiveHashCommands hash(TypeReference redisKeyType, TypeReference fieldType,
TypeReference valueType) {
return new ReactiveHashCommandsImpl<>(this, redisKeyType.getType(), fieldType.getType(), valueType.getType());
}
@Override
public ReactiveGeoCommands geo(Class redisKeyType, Class memberType) {
return new ReactiveGeoCommandsImpl<>(this, redisKeyType, memberType);
}
@Override
public ReactiveGeoCommands geo(TypeReference redisKeyType, TypeReference memberType) {
return new ReactiveGeoCommandsImpl<>(this, redisKeyType.getType(), memberType.getType());
}
@Override
public ReactiveKeyCommands key(Class redisKeyType) {
return new ReactiveKeyCommandsImpl<>(this, redisKeyType);
}
@Override
public ReactiveKeyCommands key(TypeReference redisKeyType) {
return new ReactiveKeyCommandsImpl<>(this, redisKeyType.getType());
}
@Override
public ReactiveSortedSetCommands sortedSet(Class redisKeyType, Class valueType) {
return new ReactiveSortedSetCommandsImpl<>(this, redisKeyType, valueType);
}
@Override
public ReactiveSortedSetCommands sortedSet(TypeReference redisKeyType, TypeReference valueType) {
return new ReactiveSortedSetCommandsImpl<>(this, redisKeyType.getType(), valueType.getType());
}
@Override
public ReactiveStringCommands string(Class redisKeyType, Class valueType) {
return new ReactiveStringCommandsImpl<>(this, redisKeyType, valueType);
}
@Override
public ReactiveValueCommands value(Class redisKeyType, Class valueType) {
return new ReactiveStringCommandsImpl<>(this, redisKeyType, valueType);
}
@Override
public ReactiveValueCommands value(TypeReference redisKeyType, TypeReference valueType) {
return new ReactiveStringCommandsImpl<>(this, redisKeyType.getType(), valueType.getType());
}
@Override
public ReactiveSetCommands set(Class redisKeyType, Class memberType) {
return new ReactiveSetCommandsImpl<>(this, redisKeyType, memberType);
}
@Override
public ReactiveSetCommands set(TypeReference redisKeyType, TypeReference memberType) {
return new ReactiveSetCommandsImpl<>(this, redisKeyType.getType(), memberType.getType());
}
@Override
public ReactiveListCommands list(Class redisKeyType, Class memberType) {
return new ReactiveListCommandsImpl<>(this, redisKeyType, memberType);
}
@Override
public ReactiveListCommands list(TypeReference redisKeyType, TypeReference memberType) {
return new ReactiveListCommandsImpl<>(this, redisKeyType.getType(), memberType.getType());
}
@Override
public ReactiveHyperLogLogCommands hyperloglog(Class redisKeyType, Class memberType) {
return new ReactiveHyperLogLogCommandsImpl<>(this, redisKeyType, memberType);
}
@Override
public ReactiveHyperLogLogCommands hyperloglog(TypeReference redisKeyType, TypeReference memberType) {
return new ReactiveHyperLogLogCommandsImpl<>(this, redisKeyType.getType(), memberType.getType());
}
@Override
public ReactiveBitMapCommands bitmap(Class redisKeyType) {
return new ReactiveBitMapCommandsImpl<>(this, redisKeyType);
}
@Override
public ReactiveBitMapCommands bitmap(TypeReference redisKeyType) {
return new ReactiveBitMapCommandsImpl<>(this, redisKeyType.getType());
}
@Override
public ReactiveStreamCommands stream(Class redisKeyType, Class fieldType, Class valueType) {
return new ReactiveStreamCommandsImpl<>(this, redisKeyType, fieldType, valueType);
}
@Override
public ReactiveStreamCommands stream(TypeReference redisKeyType, TypeReference fieldType,
TypeReference valueType) {
return new ReactiveStreamCommandsImpl<>(this, redisKeyType.getType(), fieldType.getType(), valueType.getType());
}
@Override
public ReactiveJsonCommands json(Class redisKeyType) {
return new ReactiveJsonCommandsImpl<>(this, redisKeyType);
}
@Override
public ReactiveJsonCommands json(TypeReference redisKeyType) {
return new ReactiveJsonCommandsImpl<>(this, redisKeyType.getType());
}
@Override
public ReactiveBloomCommands bloom(Class redisKeyType, Class valueType) {
return new ReactiveBloomCommandsImpl<>(this, redisKeyType, valueType);
}
@Override
public ReactiveBloomCommands bloom(TypeReference redisKeyType, TypeReference valueType) {
return new ReactiveBloomCommandsImpl<>(this, redisKeyType.getType(), valueType.getType());
}
@Override
public ReactiveCuckooCommands cuckoo(Class redisKeyType, Class valueType) {
return new ReactiveCuckooCommandsImpl<>(this, redisKeyType, valueType);
}
@Override
public ReactiveCuckooCommands cuckoo(TypeReference redisKeyType, TypeReference valueType) {
return new ReactiveCuckooCommandsImpl<>(this, redisKeyType.getType(), valueType.getType());
}
@Override
public ReactiveCountMinCommands countmin(Class redisKeyType, Class valueType) {
return new ReactiveCountMinCommandsImpl<>(this, redisKeyType, valueType);
}
@Override
public ReactiveCountMinCommands countmin(TypeReference redisKeyType, TypeReference valueType) {
return new ReactiveCountMinCommandsImpl<>(this, redisKeyType.getType(), valueType.getType());
}
@Override
public ReactiveTopKCommands topk(Class redisKeyType, Class valueType) {
return new ReactiveTopKCommandsImpl<>(this, redisKeyType, valueType);
}
@Override
public ReactiveTopKCommands topk(TypeReference redisKeyType, TypeReference valueType) {
return new ReactiveTopKCommandsImpl<>(this, redisKeyType.getType(), valueType.getType());
}
@Override
public ReactiveGraphCommands graph(Class redisKeyType) {
return new ReactiveGraphCommandsImpl<>(this, redisKeyType);
}
@Override
public ReactivePubSubCommands pubsub(Class messageType) {
return new ReactivePubSubCommandsImpl<>(this, messageType);
}
@Override
public ReactivePubSubCommands pubsub(TypeReference messageType) {
return new ReactivePubSubCommandsImpl<>(this, messageType.getType());
}
@Override
public ReactiveSearchCommands search(Class redisKeyType) {
return new ReactiveSearchCommandsImpl<>(this, redisKeyType);
}
@Override
public ReactiveAutoSuggestCommands autosuggest(Class redisKeyType) {
return new ReactiveAutoSuggestCommandsImpl<>(this, redisKeyType);
}
@Override
public ReactiveAutoSuggestCommands autosuggest(TypeReference redisKeyType) {
return new ReactiveAutoSuggestCommandsImpl<>(this, redisKeyType.getType());
}
@Override
public ReactiveTimeSeriesCommands timeseries(Class redisKeyType) {
return new ReactiveTimeSeriesCommandsImpl<>(this, redisKeyType);
}
@Override
public ReactiveTimeSeriesCommands timeseries(TypeReference redisKeyType) {
return new ReactiveTimeSeriesCommandsImpl<>(this, redisKeyType.getType());
}
@Override
public Redis getRedis() {
return redis;
}
public Vertx getVertx() {
return vertx;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy