/*
* Copyright 2015 Red Hat, Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.vertx.redis.impl;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.core.net.SocketAddress;
import io.vertx.redis.RedisClient;
import io.vertx.redis.RedisOptions;
import io.vertx.redis.RedisTransaction;
import io.vertx.redis.Script;
import io.vertx.redis.client.*;
import io.vertx.redis.op.*;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
import static io.vertx.redis.client.Command.*;
@Deprecated
public final class RedisClientImpl implements RedisClient {
private final String BASE_ADDRESS = "io.vertx.redis";
private final Vertx vertx;
private final RedisOptions options;
private final AtomicReference> redis = new AtomicReference<>();
private final EventBus eb;
private final String connectionString;
public RedisClientImpl(Vertx vertx, RedisOptions options) {
this.vertx = vertx;
this.options = options;
this.eb = vertx.eventBus();
// parse the options to a connection string
String connString = "";
if (options.isDomainSocket()) {
connString += "unix://" + options.getDomainSocketAddress() + "?";
} else {
connString += "redis";
if (options.isSsl()) {
connString += "s";
}
connString += "://" + options.getHost() + ":" + options.getPort() + "/?";
}
String auth = options.getAuth();
if (auth != null) {
try {
auth = URLEncoder.encode(auth, "UTF-8");
} catch (UnsupportedEncodingException ignored) {
}
connString += "password=" + auth + "&";
}
if (options.getSelect() != null) {
connString += "db=" + options.getSelect();
}
this.connectionString = connString;
}
/**
* A helper method to package method parameters into JsonArray payload.
*
* Null parameters are ignored.
*
* @param parameters Call parameters
* @return JsonArray that can be passed to send()
*/
@SuppressWarnings("unchecked")
private static List> toPayload(Object... parameters) {
List result = new ArrayList<>(parameters.length);
for (Object param : parameters) {
// unwrap
if (param instanceof JsonArray) {
param = ((JsonArray) param).getList();
}
// unwrap
if (param instanceof JsonObject) {
param = ((JsonObject) param).getMap();
}
if (param instanceof Collection) {
((Collection) param).stream().filter(Objects::nonNull).forEach(result::add);
} else if (param instanceof Map) {
for (Map.Entry, ?> pair : ((Map, ?>) param).entrySet()) {
result.add(pair.getKey());
result.add(pair.getValue());
}
} else if (param instanceof Stream) {
((Stream) param).forEach(e -> {
if (e instanceof Object[]) {
Collections.addAll(result, (Object[]) e);
} else {
result.add(e);
}
});
} else if (param != null) {
result.add(param);
}
}
return result;
}
private void send(Command command, List arguments, Handler> handler) {
final Request req = Request.cmd(command);
if (arguments != null) {
for (Object o : arguments) {
if (o == null) {
req.nullArg();
} else if (o instanceof Buffer) {
req.arg((Buffer) o);
} else {
req.arg(o.toString());
}
}
}
CompletableFuture fut = redis.get();
if (fut == null) {
CompletableFuture f = new CompletableFuture<>();
if (redis.compareAndSet(null, f)) {
fut = f;
Redis.createClient(vertx, new io.vertx.redis.client.RedisOptions()
.setNetClientOptions(options)
.setConnectionString(connectionString)).connect(onReady -> {
if (onReady.succeeded()) {
// handle pub/sub
onReady.result().handler(this::handlePubSubMessage);
f.complete(onReady.result());
} else {
f.completeExceptionally(onReady.cause());
}
});
} else {
fut = redis.get();
}
}
fut.whenComplete((client, err) -> {
if (err == null) {
client.send(req, handler);
} else {
handler.handle(Future.failedFuture(err));
}
});
}
private void handlePubSubMessage(Response response) {
JsonArray data = toJsonArray(response);
// Detect valid published messages according to https://redis.io/topics/pubsub
if (!"message".equals(data.getString(0)))
return;
String channel = data.getString(1);
final String vertxChannel = BASE_ADDRESS + "." + channel;
JsonObject replyMessage = new JsonObject();
replyMessage.put("status", "ok");
JsonObject message = new JsonObject();
message.put("channel", channel);
message.put("message", data.getString(2));
replyMessage.put("value", message);
eb.send(vertxChannel, replyMessage);
}
private void sendLong(Command command, List arguments, Handler> handler) {
send(command, arguments, ar -> {
if (ar.failed()) {
handler.handle(Future.failedFuture(ar.cause()));
} else {
handler.handle(Future.succeededFuture(ar.result().toLong()));
}
});
}
private void sendString(Command command, List arguments, Handler> handler) {
send(command, arguments, ar -> {
if (ar.failed()) {
handler.handle(Future.failedFuture(ar.cause()));
} else {
handler.handle(Future.succeededFuture(ar.result() != null ? ar.result().toString() : null));
}
});
}
private static JsonArray toJsonArray(Response response) {
final JsonArray json = new JsonArray();
if (response.type() != ResponseType.MULTI) {
switch (response.type()) {
case INTEGER:
json.add(response.toLong());
break;
case SIMPLE:
case BULK:
json.add(response.toString());
break;
}
return json;
}
for (Response r : response) {
if (r == null) {
json.addNull();
} else {
switch (r.type()) {
case INTEGER:
json.add(r.toLong());
break;
case SIMPLE:
case BULK:
json.add(r.toString());
break;
case MULTI:
json.add(toJsonArray(r));
break;
}
}
}
return json;
}
private void sendJsonArray(Command command, List arguments, Handler> handler) {
send(command, arguments, ar -> {
if (ar.failed()) {
handler.handle(Future.failedFuture(ar.cause()));
} else {
handler.handle(Future.succeededFuture(ar.result() != null ? toJsonArray(ar.result()) : null));
}
});
}
private void sendVoid(Command command, List arguments, Handler> handler) {
send(command, arguments, ar -> {
if (ar.failed()) {
handler.handle(Future.failedFuture(ar.cause()));
} else {
handler.handle(Future.succeededFuture());
}
});
}
private void sendBuffer(Command command, List arguments, Handler> handler) {
send(command, arguments, ar -> {
if (ar.failed()) {
handler.handle(Future.failedFuture(ar.cause()));
} else {
handler.handle(Future.succeededFuture(ar.result() != null ? ar.result().toBuffer() : null));
}
});
}
private static JsonObject toJsonObject(Response response) {
final JsonObject json = new JsonObject();
for (String key : response.getKeys()) {
Response value = response.get(key);
switch (value.type()) {
case INTEGER:
json.put(key, value.toLong());
break;
case SIMPLE:
case BULK:
json.put(key, value.toString());
break;
case MULTI:
json.put(key, toJsonArray(value));
break;
}
}
return json;
}
private void sendJsonObject(Command command, List arguments, Handler> handler) {
send(command, arguments, ar -> {
if (ar.failed()) {
handler.handle(Future.failedFuture(ar.cause()));
} else {
handler.handle(Future.succeededFuture(ar.result() != null ? toJsonObject(ar.result()) : null));
}
});
}
@Override
public void close(Handler> handler) {
CompletableFuture prev = redis.getAndSet(null);
if (prev != null) {
prev.whenComplete((client, err) -> {
if (err == null) {
client.close();
if (handler != null) {
handler.handle(Future.succeededFuture());
}
} else {
if (handler != null) {
handler.handle(Future.failedFuture(err.getCause()));
}
}
});
}
}
@Override
public RedisClient append(String key, String value, Handler> handler) {
sendLong(APPEND, toPayload(key, value), handler);
return this;
}
@Override
public RedisClient auth(String password, Handler> handler) {
sendString(AUTH, toPayload(password), handler);
return this;
}
@Override
public RedisClient bgrewriteaof(Handler> handler) {
sendString(BGREWRITEAOF, null, handler);
return this;
}
@Override
public RedisClient bgsave(Handler> handler) {
sendString(BGSAVE, null, handler);
return this;
}
@Override
public RedisClient bitcount(String key, Handler> handler) {
sendLong(BITCOUNT, toPayload(key), handler);
return this;
}
public RedisClient bitcountRange(String key, long start, long end, Handler> handler) {
sendLong(BITCOUNT, toPayload(key, start, end), handler);
return this;
}
@Override
public RedisClient bitop(BitOperation operation, String destkey, List keys, Handler> handler) {
sendLong(BITOP, toPayload(operation.name(), destkey, keys), handler);
return this;
}
@Override
public RedisClient bitpos(String key, int bit, Handler> handler) {
sendLong(BITPOS, toPayload(key, bit), handler);
return this;
}
@Override
public RedisClient bitposFrom(String key, int bit, int start, Handler> handler) {
sendLong(BITPOS, toPayload(key, bit, start), handler);
return this;
}
@Override
public RedisClient bitposRange(String key, int bit, int start, int stop, Handler> handler) {
sendLong(BITPOS, toPayload(key, bit, start, stop), handler);
return this;
}
@Override
public RedisClient blpop(String key, int seconds, Handler> handler) {
sendJsonArray(BLPOP, toPayload(key, seconds), handler);
return this;
}
@Override
public RedisClient blpopMany(List keys, int seconds, Handler> handler) {
sendJsonArray(BLPOP, toPayload(keys, seconds), handler);
return this;
}
@Override
public RedisClient brpop(String key, int seconds, Handler> handler) {
sendJsonArray(BRPOP, toPayload(key, seconds), handler);
return this;
}
@Override
public RedisClient brpopMany(List keys, int seconds, Handler> handler) {
sendJsonArray(BRPOP, toPayload(keys, seconds), handler);
return this;
}
@Override
public RedisClient brpoplpush(String key, String destkey, int seconds, Handler> handler) {
sendString(BRPOPLPUSH, toPayload(key, destkey, seconds), handler);
return this;
}
@Override
public RedisClient clientKill(KillFilter filter, Handler> handler) {
sendLong(CLIENT, toPayload("kill", filter.toJsonArray().getList()), handler);
return this;
}
@Override
public RedisClient clientList(Handler> handler) {
sendString(CLIENT, toPayload("list"), handler);
return this;
}
@Override
public RedisClient clientGetname(Handler> handler) {
sendString(CLIENT, toPayload("GETNAME"), handler);
return this;
}
@Override
public RedisClient clientPause(long millis, Handler> handler) {
sendString(CLIENT, toPayload("PAUSE", millis), handler);
return this;
}
@Override
public RedisClient clientSetname(String name, Handler> handler) {
sendString(CLIENT, toPayload("SETNAME", name), handler);
return this;
}
@Override
public RedisClient clusterAddslots(List slots, Handler> handler) {
sendVoid(CLUSTER, toPayload("ADDSLOTS"), handler);
return this;
}
@Override
public RedisClient clusterCountFailureReports(String nodeId, Handler> handler) {
sendLong(CLUSTER, toPayload("COUNT-FAILURE-REPORTS", nodeId), handler);
return this;
}
@Override
public RedisClient clusterCountkeysinslot(long slot, Handler> handler) {
sendLong(CLUSTER, toPayload("COUNTKEYSINSLOT", slot), handler);
return this;
}
@Override
public RedisClient clusterDelslots(long slot, Handler> handler) {
sendVoid(CLUSTER, toPayload("DELSLOTS", slot), handler);
return this;
}
@Override
public RedisClient clusterDelslotsMany(List slots, Handler> handler) {
sendVoid(CLUSTER, toPayload("DELSLOTS", slots), handler);
return this;
}
@Override
public RedisClient clusterFailover(Handler> handler) {
sendVoid(CLUSTER, toPayload("FAILOVER"), handler);
return this;
}
@Override
public RedisClient clusterFailOverWithOptions(FailoverOptions options, Handler> handler) {
sendVoid(CLUSTER, toPayload("FAILOVER", options), handler);
return this;
}
@Override
public RedisClient clusterForget(String nodeId, Handler> handler) {
sendVoid(CLUSTER, toPayload("FORGET", nodeId), handler);
return this;
}
@Override
public RedisClient clusterGetkeysinslot(long slot, long count, Handler> handler) {
sendJsonArray(CLUSTER, toPayload("GETKEYSINSLOT", slot, count), handler);
return this;
}
@Override
public RedisClient clusterInfo(Handler> handler) {
sendJsonArray(CLUSTER, toPayload("INFO"), handler);
return this;
}
@Override
public RedisClient clusterKeyslot(String key, Handler> handler) {
sendLong(CLUSTER, toPayload("KEYSLOT", key), handler);
return this;
}
@Override
public RedisClient clusterMeet(String ip, long port, Handler> handler) {
sendVoid(CLUSTER, toPayload("MEET", ip, port), handler);
return this;
}
@Override
public RedisClient clusterNodes(Handler> handler) {
sendJsonArray(CLUSTER, toPayload("NODES"), handler);
return this;
}
@Override
public RedisClient clusterReplicate(String nodeId, Handler> handler) {
sendVoid(CLUSTER, toPayload("REPLICATE", nodeId), handler);
return this;
}
@Override
public RedisClient clusterReset(Handler> handler) {
sendVoid(CLUSTER, toPayload("RESET"), handler);
return this;
}
@Override
public RedisClient clusterResetWithOptions(ResetOptions options, Handler> handler) {
sendVoid(CLUSTER, toPayload("RESET", options), handler);
return this;
}
@Override
public RedisClient clusterSaveconfig(Handler> handler) {
sendVoid(CLUSTER, toPayload("SAVECONFIG"), handler);
return this;
}
@Override
public RedisClient clusterSetConfigEpoch(long epoch, Handler> handler) {
sendVoid(CLUSTER, toPayload("SET-CONFIG-EPOCH", epoch), handler);
return this;
}
@Override
public RedisClient clusterSetslot(long slot, SlotCmd subcommand, Handler> handler) {
sendVoid(CLUSTER, toPayload("SETSLOT", slot, subcommand), handler);
return this;
}
@Override
public RedisClient clusterSetslotWithNode(long slot, SlotCmd subcommand, String nodeId, Handler> handler) {
sendVoid(CLUSTER, toPayload("SETSLOT", slot, subcommand, nodeId), handler);
return this;
}
@Override
public RedisClient clusterSlaves(String nodeId, Handler> handler) {
sendJsonArray(CLUSTER, toPayload("SLAVES", nodeId), handler);
return this;
}
@Override
public RedisClient clusterSlots(Handler> handler) {
sendJsonArray(CLUSTER, toPayload("SLOTS"), handler);
return this;
}
@Override
public RedisClient command(Handler> handler) {
sendJsonArray(COMMAND, null, handler);
return this;
}
@Override
public RedisClient commandCount(Handler> handler) {
sendLong(COMMAND, toPayload("COUNT"), handler);
return this;
}
@Override
public RedisClient commandGetkeys(Handler> handler) {
sendJsonArray(COMMAND, toPayload("GETKEYS"), handler);
return this;
}
@Override
public RedisClient commandInfo(List commands, Handler> handler) {
sendJsonArray(COMMAND, toPayload("INFO", commands), handler);
return this;
}
@Override
public RedisClient configGet(String parameter, Handler> handler) {
sendJsonArray(CONFIG, toPayload("GET", parameter), handler);
return this;
}
@Override
public RedisClient configRewrite(Handler> handler) {
sendString(CONFIG, toPayload("REWRITE"), handler);
return this;
}
@Override
public RedisClient configSet(String parameter, String value, Handler> handler) {
sendString(CONFIG, toPayload("SET", parameter, value), handler);
return this;
}
@Override
public RedisClient configResetstat(Handler> handler) {
sendString(CONFIG, toPayload("RESETSTAT"), handler);
return this;
}
@Override
public RedisClient dbsize(Handler> handler) {
sendLong(DBSIZE, null, handler);
return this;
}
@Override
public RedisClient debugObject(String key, Handler> handler) {
sendString(DEBUG, toPayload("OBJECT", key), handler);
return this;
}
@Override
public RedisClient debugSegfault(Handler> handler) {
sendString(DEBUG, toPayload("SEGFAULT"), handler);
return this;
}
@Override
public RedisClient decr(String key, Handler> handler) {
sendLong(DECR, toPayload(key), handler);
return this;
}
@Override
public RedisClient decrby(String key, long decrement, Handler> handler) {
sendLong(DECRBY, toPayload(key, decrement), handler);
return this;
}
@Override
public RedisClient del(String key, Handler> handler) {
sendLong(DEL, toPayload(key), handler);
return this;
}
@Override
public RedisClient delMany(List keys, Handler> handler) {
sendLong(DEL, toPayload(keys), handler);
return this;
}
@Override
public RedisClient dump(String key, Handler> handler) {
sendString(DUMP, toPayload(key), dump -> {
if (dump.failed()) {
handler.handle(dump);
} else {
handler.handle(Future.succeededFuture(RedisEncoding.encode(dump.result())));
}
});
return this;
}
@Override
public RedisClient echo(String message, Handler> handler) {
sendString(ECHO, toPayload(message), handler);
return this;
}
@Override
public RedisClient eval(String script, List keys, List args, Handler> handler) {
keys = (keys != null) ? keys : Collections.emptyList();
args = (args != null) ? args : Collections.emptyList();
sendJsonArray(EVAL, toPayload(script, keys.size(), keys, args), handler);
return this;
}
@Override
public RedisClient evalsha(String sha1, List keys, List args, Handler> handler) {
keys = (keys != null) ? keys : Collections.emptyList();
args = (args != null) ? args : Collections.emptyList();
sendJsonArray(EVALSHA, toPayload(sha1, keys.size(), keys, args), handler);
return this;
}
@Override
public RedisClient evalScript(Script script, List keys, List args, Handler> handler) {
this.evalsha(script.getSha1(), keys, args, res -> {
if (res.failed() && res.cause().getMessage().startsWith("NOSCRIPT")) {
this.eval(script.getScript(), keys, args, handler);
} else {
handler.handle(res);
}
});
return this;
}
@Override
public RedisClient exists(String key, Handler> handler) {
sendLong(EXISTS, toPayload(key), handler);
return this;
}
@Override
public RedisClient existsMany(List keys, Handler> handler) {
sendLong(EXISTS, toPayload(keys), handler);
return this;
}
@Override
public RedisClient expire(String key, long seconds, Handler> handler) {
sendLong(EXPIRE, toPayload(key, seconds), handler);
return this;
}
@Override
public RedisClient expireat(String key, long seconds, Handler> handler) {
sendLong(EXPIREAT, toPayload(key, seconds), handler);
return this;
}
@Override
public RedisClient flushall(Handler> handler) {
sendString(FLUSHALL, null, handler);
return this;
}
@Override
public RedisClient flushdb(Handler> handler) {
sendString(FLUSHDB, null, handler);
return this;
}
@Override
public RedisClient get(String key, Handler> handler) {
sendString(GET, toPayload(key), handler);
return this;
}
@Override
public RedisClient getBinary(String key, Handler> handler) {
sendBuffer(GET, toPayload(key), handler);
return this;
}
@Override
public RedisClient getbit(String key, long offset, Handler> handler) {
sendLong(GETBIT, toPayload(key, offset), handler);
return this;
}
@Override
public RedisClient getrange(String key, long start, long end, Handler> handler) {
sendString(GETRANGE, toPayload(key, start, end), handler);
return this;
}
@Override
public RedisClient getset(String key, String value, Handler> handler) {
sendString(GETSET, toPayload(key, value), handler);
return this;
}
@Override
public RedisClient hdel(String key, String field, Handler> handler) {
sendLong(HDEL, toPayload(key, field), handler);
return this;
}
@Override
public RedisClient hdelMany(String key, List fields, Handler> handler) {
sendLong(HDEL, toPayload(key, fields), handler);
return this;
}
@Override
public RedisClient hexists(String key, String field, Handler> handler) {
sendLong(HEXISTS, toPayload(key, field), handler);
return this;
}
@Override
public RedisClient hget(String key, String field, Handler> handler) {
sendString(HGET, toPayload(key, field), handler);
return this;
}
@Override
public RedisClient hgetall(String key, Handler> handler) {
sendJsonObject(HGETALL, toPayload(key), handler);
return this;
}
@Override
public RedisClient hincrby(String key, String field, long increment, Handler> handler) {
sendLong(HINCRBY, toPayload(key, field, increment), handler);
return this;
}
@Override
public RedisClient hincrbyfloat(String key, String field, double increment, Handler> handler) {
sendString(HINCRBYFLOAT, toPayload(key, field, increment), handler);
return this;
}
@Override
public RedisClient hkeys(String key, Handler> handler) {
sendJsonArray(HKEYS, toPayload(key), handler);
return this;
}
@Override
public RedisClient hlen(String key, Handler> handler) {
sendLong(HLEN, toPayload(key), handler);
return this;
}
@Override
public RedisClient hmget(String key, List fields, Handler> handler) {
sendJsonArray(HMGET, toPayload(key, fields), handler);
return this;
}
@Override
public RedisClient hmset(String key, JsonObject values, Handler> handler) {
sendString(HMSET, toPayload(key, values), handler);
return this;
}
@Override
public RedisClient hset(String key, String field, String value, Handler> handler) {
sendLong(HSET, toPayload(key, field, value), handler);
return this;
}
@Override
public RedisClient hsetnx(String key, String field, String value, Handler> handler) {
sendLong(HSETNX, toPayload(key, field, value), handler);
return this;
}
@Override
public RedisClient hvals(String key, Handler> handler) {
sendJsonArray(HVALS, toPayload(key), handler);
return this;
}
@Override
public RedisClient incr(String key, Handler> handler) {
sendLong(INCR, toPayload(key), handler);
return this;
}
@Override
public RedisClient incrby(String key, long increment, Handler> handler) {
sendLong(INCRBY, toPayload(key, increment), handler);
return this;
}
@Override
public RedisClient incrbyfloat(String key, double increment, Handler> handler) {
sendString(INCRBYFLOAT, toPayload(key, increment), handler);
return this;
}
@Override
public RedisClient info(Handler> handler) {
sendString(INFO, Collections.emptyList(), info -> {
if (info.failed()) {
handler.handle(Future.failedFuture(info.cause()));
} else {
JsonObject result = new JsonObject();
JsonObject section = result;
for (String line : info.result().split("\r?\n")) {
if (line.length() > 0) {
if (line.charAt(0) == '#') {
section = new JsonObject();
result.put(line.substring(2).toLowerCase(), section);
} else {
int sep = line.indexOf(':');
section.put(line.substring(0, sep), line.substring(sep + 1));
}
}
}
handler.handle(Future.succeededFuture(result));
}
});
return this;
}
@Override
public RedisClient infoSection(String section, Handler> handler) {
sendString(INFO, toPayload(section), info -> {
if (info.failed()) {
handler.handle(Future.failedFuture(info.cause()));
} else {
JsonObject result = new JsonObject();
JsonObject sectionJson = result;
for (String line : info.result().split("\r?\n")) {
if (line.length() > 0) {
if (line.charAt(0) == '#') {
sectionJson = new JsonObject();
result.put(line.substring(2).toLowerCase(), sectionJson);
} else {
int sep = line.indexOf(':');
sectionJson.put(line.substring(0, sep), line.substring(sep + 1));
}
}
}
handler.handle(Future.succeededFuture(result));
}
});
return this;
}
@Override
public RedisClient keys(String pattern, Handler> handler) {
sendJsonArray(KEYS, toPayload(pattern), handler);
return this;
}
@Override
public RedisClient lastsave(Handler> handler) {
sendLong(LASTSAVE, null, handler);
return this;
}
@Override
public RedisClient lindex(String key, int index, Handler> handler) {
sendString(LINDEX, toPayload(key, index), handler);
return this;
}
@Override
public RedisClient linsert(String key, InsertOptions option, String pivot, String value, Handler> handler) {
sendLong(LINSERT, toPayload(key, option.name(), pivot, value), handler);
return this;
}
@Override
public RedisClient llen(String key, Handler> handler) {
sendLong(LLEN, toPayload(key), handler);
return this;
}
@Override
public RedisClient lpop(String key, Handler> handler) {
sendString(LPOP, toPayload(key), handler);
return this;
}
@Override
public RedisClient lpushMany(String key, List values, Handler> handler) {
sendLong(LPUSH, toPayload(key, values), handler);
return this;
}
@Override
public RedisClient lpush(String key, String value, Handler> handler) {
sendLong(LPUSH, toPayload(key, value), handler);
return this;
}
@Override
public RedisClient lpushx(String key, String value, Handler> handler) {
sendLong(LPUSHX, toPayload(key, value), handler);
return this;
}
@Override
public RedisClient lrange(String key, long from, long to, Handler> handler) {
sendJsonArray(LRANGE, toPayload(key, from, to), handler);
return this;
}
@Override
public RedisClient lrem(String key, long count, String value, Handler> handler) {
sendLong(LREM, toPayload(key, count, value), handler);
return this;
}
@Override
public RedisClient lset(String key, long index, String value, Handler> handler) {
sendString(LSET, toPayload(key, index, value), handler);
return this;
}
@Override
public RedisClient ltrim(String key, long from, long to, Handler> handler) {
sendString(LTRIM, toPayload(key, from, to), handler);
return this;
}
@Override
public RedisClient mget(String key, Handler> handler) {
sendJsonArray(MGET, toPayload(key), handler);
return this;
}
@Override
public RedisClient mgetMany(List keys, Handler> handler) {
sendJsonArray(MGET, toPayload(keys), handler);
return this;
}
@Override
public RedisClient migrate(String host, int port, String key, int destdb, long timeout, MigrateOptions options, Handler> handler) {
sendString(MIGRATE, toPayload(host, port, key, destdb, timeout, options != null ? options.toJsonArray() : null), handler);
return this;
}
@Override
public RedisClient monitor(Handler> handler) {
sendVoid(MONITOR, null, handler);
return this;
}
@Override
public RedisClient move(String key, int destdb, Handler> handler) {
sendLong(MOVE, toPayload(key, destdb), handler);
return this;
}
@Override
public RedisClient mset(JsonObject keyvals, Handler> handler) {
sendString(MSET, toPayload(keyvals), handler);
return this;
}
@Override
public RedisClient msetnx(JsonObject keyvals, Handler> handler) {
sendLong(MSETNX, toPayload(keyvals), handler);
return this;
}
@Override
public RedisClient object(String key, ObjectCmd cmd, Handler> handler) {
sendVoid(OBJECT, toPayload(cmd.name(), key), handler);
return this;
}
@Override
public RedisClient persist(String key, Handler> handler) {
sendLong(PERSIST, toPayload(key), handler);
return this;
}
@Override
public RedisClient pexpire(String key, long millis, Handler> handler) {
sendLong(PEXPIRE, toPayload(key, millis), handler);
return this;
}
@Override
public RedisClient pexpireat(String key, long millis, Handler> handler) {
sendLong(PEXPIREAT, toPayload(key, millis), handler);
return this;
}
@Override
public RedisClient pfadd(String key, String element, Handler> handler) {
sendLong(PFADD, toPayload(key, element), handler);
return this;
}
@Override
public RedisClient pfaddMany(String key, List elements, Handler> handler) {
sendLong(PFADD, toPayload(key, elements), handler);
return this;
}
@Override
public RedisClient pfcount(String key, Handler> handler) {
sendLong(PFCOUNT, toPayload(key), handler);
return this;
}
@Override
public RedisClient pfcountMany(List key, Handler> handler) {
sendLong(PFCOUNT, toPayload(key), handler);
return this;
}
@Override
public RedisClient pfmerge(String destkey, List keys, Handler> handler) {
sendString(PFMERGE, toPayload(destkey, keys), handler);
return this;
}
@Override
public RedisClient ping(Handler> handler) {
sendString(PING, null, handler);
return this;
}
@Override
public RedisClient psetex(String key, long millis, String value, Handler> handler) {
sendVoid(PSETEX, toPayload(key, millis, value), handler);
return this;
}
@Override
public RedisClient psubscribe(String pattern, Handler> handler) {
sendJsonArray(PSUBSCRIBE, toPayload(pattern), handler);
return this;
}
@Override
public RedisClient psubscribeMany(List patterns, Handler> handler) {
sendJsonArray(PSUBSCRIBE, toPayload(patterns), handler);
return this;
}
@Override
public RedisClient pubsubChannels(String pattern, Handler> handler) {
sendJsonArray(PUBSUB, toPayload("CHANNELS", pattern == null || "".equals(pattern) ? null : pattern), handler);
return this;
}
public RedisClient pubsubNumsub(List channels, Handler> handler) {
sendJsonArray(PUBSUB, toPayload("NUMSUB", channels), handler);
return this;
}
public RedisClient pubsubNumpat(Handler> handler) {
sendLong(PUBSUB, toPayload("NUMPAT"), handler);
return this;
}
@Override
public RedisClient pttl(String key, Handler> handler) {
sendLong(PTTL, toPayload(key), handler);
return this;
}
@Override
public RedisClient publish(String channel, String message, Handler> handler) {
sendLong(PUBLISH, toPayload(channel, message), handler);
return this;
}
@Override
public RedisClient punsubscribe(List patterns, Handler> handler) {
sendVoid(PUNSUBSCRIBE, toPayload(patterns), handler);
return this;
}
@Override
public RedisClient randomkey(Handler> handler) {
sendString(RANDOMKEY, null, handler);
return this;
}
@Override
public RedisClient rename(String key, String newkey, Handler> handler) {
sendString(RENAME, toPayload(key, newkey), handler);
return this;
}
@Override
public RedisClient renamenx(String key, String newkey, Handler> handler) {
sendLong(RENAMENX, toPayload(key, newkey), handler);
return this;
}
@Override
public RedisClient restore(String key, long millis, String serialized, Handler> handler) {
sendString(RESTORE, toPayload(key, millis, RedisEncoding.decode(serialized)), handler);
return this;
}
@Override
public RedisClient role(Handler> handler) {
sendJsonArray(ROLE, null, handler);
return this;
}
@Override
public RedisClient rpop(String key, Handler> handler) {
sendString(RPOP, toPayload(key), handler);
return this;
}
@Override
public RedisClient rpoplpush(String key, String destkey, Handler> handler) {
sendString(RPOPLPUSH, toPayload(key, destkey), handler);
return this;
}
@Override
public RedisClient rpushMany(String key, List values, Handler> handler) {
sendLong(RPUSH, toPayload(key, values), handler);
return this;
}
@Override
public RedisClient rpush(String key, String value, Handler> handler) {
sendLong(RPUSH, toPayload(key, value), handler);
return this;
}
@Override
public RedisClient rpushx(String key, String value, Handler> handler) {
sendLong(RPUSHX, toPayload(key, value), handler);
return this;
}
@Override
public RedisClient sadd(String key, String member, Handler> handler) {
sendLong(SADD, toPayload(key, member), handler);
return this;
}
@Override
public RedisClient saddMany(String key, List members, Handler> handler) {
sendLong(SADD, toPayload(key, members), handler);
return this;
}
@Override
public RedisClient save(Handler> handler) {
sendString(SAVE, null, handler);
return this;
}
@Override
public RedisClient scard(String key, Handler> handler) {
sendLong(SCARD, toPayload(key), handler);
return this;
}
@Override
public RedisClient scriptExists(String script, Handler> handler) {
sendJsonArray(SCRIPT, toPayload("EXISTS", script), handler);
return this;
}
@Override
public RedisClient scriptExistsMany(List scripts, Handler> handler) {
sendJsonArray(SCRIPT, toPayload("EXISTS", scripts), handler);
return this;
}
@Override
public RedisClient scriptFlush(Handler> handler) {
sendString(SCRIPT, toPayload("FLUSH"), handler);
return this;
}
@Override
public RedisClient scriptKill(Handler> handler) {
sendString(SCRIPT, toPayload("KILL"), handler);
return this;
}
@Override
public RedisClient scriptLoad(String script, Handler> handler) {
sendString(SCRIPT, toPayload("LOAD", script), handler);
return this;
}
@Override
public RedisClient sdiff(String key, List cmpkeys, Handler> handler) {
sendJsonArray(SDIFF, toPayload(key, cmpkeys), handler);
return this;
}
@Override
public RedisClient sdiffstore(String destkey, String key, List cmpkeys, Handler> handler) {
sendLong(SDIFFSTORE, toPayload(destkey, key, cmpkeys), handler);
return this;
}
@Override
public RedisClient select(int dbindex, Handler> handler) {
sendString(SELECT, toPayload(dbindex), handler);
return this;
}
@Override
public RedisClient set(String key, String value, Handler> handler) {
sendVoid(SET, toPayload(key, value), handler);
return this;
}
@Override
public RedisClient setWithOptions(String key, String value, SetOptions options, Handler> handler) {
sendString(SET, toPayload(key, value, options != null ? options.toJsonArray() : null), handler);
return this;
}
@Override
public RedisClient setBinary(String key, Buffer value, Handler> handler) {
sendVoid(SET, toPayload(key, value), handler);
return this;
}
@Override
public RedisClient setBinaryWithOptions(String key, Buffer value, SetOptions options, Handler> handler) {
sendVoid(SET, toPayload(key, value, options != null ? options.toJsonArray() : null), handler);
return this;
}
@Override
public RedisClient setbit(String key, long offset, int bit, Handler> handler) {
sendLong(SETBIT, toPayload(key, offset, bit), handler);
return this;
}
@Override
public RedisClient setex(String key, long seconds, String value, Handler> handler) {
sendString(SETEX, toPayload(key, seconds, value), handler);
return this;
}
@Override
public RedisClient setnx(String key, String value, Handler> handler) {
sendLong(SETNX, toPayload(key, value), handler);
return this;
}
@Override
public RedisClient setrange(String key, int offset, String value, Handler> handler) {
sendLong(SETRANGE, toPayload(key, offset, value), handler);
return this;
}
@Override
public RedisClient sinter(List keys, Handler> handler) {
sendJsonArray(SINTER, toPayload(keys), handler);
return this;
}
@Override
public RedisClient sinterstore(String destkey, List keys, Handler> handler) {
sendLong(SINTERSTORE, toPayload(destkey, keys), handler);
return this;
}
@Override
public RedisClient sismember(String key, String member, Handler> handler) {
sendLong(SISMEMBER, toPayload(key, member), handler);
return this;
}
@Override
public RedisClient slaveof(String host, int port, Handler> handler) {
sendString(SLAVEOF, toPayload(host, port), handler);
return this;
}
@Override
public RedisClient slaveofNoone(Handler> handler) {
sendString(SLAVEOF, toPayload("NO", "ONE"), handler);
return this;
}
@Override
public RedisClient slowlogGet(int limit, Handler> handler) {
sendJsonArray(SLOWLOG, toPayload("GET", limit < 0 ? null : limit), handler);
return this;
}
@Override
public RedisClient slowlogLen(Handler> handler) {
sendLong(SLOWLOG, toPayload("LEN"), handler);
return this;
}
@Override
public RedisClient slowlogReset(Handler> handler) {
sendVoid(SLOWLOG, toPayload("RESET"), handler);
return this;
}
@Override
public RedisClient smembers(String key, Handler> handler) {
sendJsonArray(SMEMBERS, toPayload(key), handler);
return this;
}
@Override
public RedisClient smove(String key, String destkey, String member, Handler> handler) {
sendLong(SMOVE, toPayload(key, destkey, member), handler);
return this;
}
@Override
public RedisClient sort(String key, SortOptions options, Handler> handler) {
sendJsonArray(SORT, toPayload(key, options != null ? options.toJsonArray() : null), handler);
return this;
}
@Override
public RedisClient spop(String key, Handler> handler) {
sendString(SPOP, toPayload(key), handler);
return this;
}
@Override
public RedisClient spopMany(String key, int count, Handler> handler) {
sendJsonArray(SPOP, toPayload(key, count), handler);
return this;
}
@Override
public RedisClient srandmember(String key, Handler> handler) {
sendString(SRANDMEMBER, toPayload(key), handler);
return this;
}
@Override
public RedisClient srandmemberCount(String key, int count, Handler> handler) {
sendJsonArray(SRANDMEMBER, toPayload(key, count), handler);
return this;
}
@Override
public RedisClient srem(String key, String member, Handler> handler) {
sendLong(SREM, toPayload(key, member), handler);
return this;
}
@Override
public RedisClient sremMany(String key, List members, Handler> handler) {
sendLong(SREM, toPayload(key, members), handler);
return this;
}
@Override
public RedisClient strlen(String key, Handler> handler) {
sendLong(STRLEN, toPayload(key), handler);
return this;
}
@Override
public RedisClient subscribe(String channel, Handler> handler) {
sendJsonArray(SUBSCRIBE, toPayload(channel), handler);
return this;
}
@Override
public RedisClient subscribeMany(List channels, Handler> handler) {
sendJsonArray(SUBSCRIBE, toPayload(channels), handler);
return this;
}
@Override
public RedisClient sunion(List keys, Handler> handler) {
sendJsonArray(SUNION, toPayload(keys), handler);
return this;
}
@Override
public RedisClient sunionstore(String destkey, List keys, Handler> handler) {
sendLong(SUNIONSTORE, toPayload(destkey, keys), handler);
return this;
}
@Override
public RedisClient sync(Handler> handler) {
sendVoid(SYNC, null, handler);
return this;
}
@Override
public RedisClient time(Handler> handler) {
sendJsonArray(TIME, null, handler);
return this;
}
@Override
public RedisTransaction transaction() {
return new RedisTransactionImpl();
}
@Override
public RedisClient ttl(String key, Handler> handler) {
sendLong(TTL, toPayload(key), handler);
return this;
}
@Override
public RedisClient type(String key, Handler> handler) {
sendString(TYPE, toPayload(key), handler);
return this;
}
@Override
public RedisClient unsubscribe(List channels, Handler> handler) {
sendVoid(UNSUBSCRIBE, toPayload(channels), handler);
return this;
}
@Override
public RedisClient wait(long numSlaves, long timeout, Handler> handler) {
sendString(WAIT, toPayload(numSlaves, timeout), handler);
return this;
}
@Override
public RedisClient zadd(String key, double score, String member, Handler> handler) {
sendLong(ZADD, toPayload(key, score, member), handler);
return this;
}
@Override
public RedisClient zaddMany(String key, Map members, Handler> handler) {
// flip from to when wrapping
Stream flipped = members.entrySet().stream().map(e -> new Object[]{e.getValue(), e.getKey()});
sendLong(ZADD, toPayload(key, flipped), handler);
return this;
}
@Override
public RedisClient zcard(String key, Handler> handler) {
sendLong(ZCARD, toPayload(key), handler);
return this;
}
@Override
public RedisClient zcount(String key, double min, double max, Handler> handler) {
String minVal = (min == Double.NEGATIVE_INFINITY) ? "-inf" : String.valueOf(min);
String maxVal = (max == Double.POSITIVE_INFINITY) ? "+inf" : String.valueOf(max);
sendLong(ZCOUNT, toPayload(key, minVal, maxVal), handler);
return this;
}
@Override
public RedisClient zincrby(String key, double increment, String member, Handler> handler) {
sendString(ZINCRBY, toPayload(key, increment, member), handler);
return this;
}
@Override
public RedisClient zinterstore(String destkey, List sets, AggregateOptions options, Handler> handler) {
sendLong(ZINTERSTORE, toPayload(destkey, sets.size(), sets, options != null ? options.name() : null), handler);
return this;
}
@Override
public RedisClient zinterstoreWeighed(String destkey, Map sets, AggregateOptions options, Handler> handler) {
sendLong(ZINTERSTORE, toPayload(destkey, sets.size(), sets.keySet(), "WEIGHTS", sets.values(),
options != null ? options.toJsonArray() : null), handler);
return this;
}
@Override
public RedisClient zlexcount(String key, String min, String max, Handler