DATAREDIS-528 - Upgrade to Lettuce 4.2.2.
We now support Lettuce 4.2.2.Final. Using Lettuce requires Java 8. Original pull request: #222.
This commit is contained in:
committed by
Mark Paluch
parent
863e5b8d68
commit
4be4ed0b28
@@ -372,6 +372,10 @@ public class ClusterCommandExecutor implements DisposableBean {
|
||||
if (executor instanceof DisposableBean) {
|
||||
((DisposableBean) executor).destroy();
|
||||
}
|
||||
|
||||
if (resourceProvider instanceof DisposableBean) {
|
||||
((DisposableBean) resourceProvider).destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,54 +15,44 @@
|
||||
*/
|
||||
package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import com.lambdaworks.redis.RedisAsyncConnection;
|
||||
import com.lambdaworks.redis.RedisClient;
|
||||
import com.lambdaworks.redis.RedisConnection;
|
||||
import com.lambdaworks.redis.RedisURI;
|
||||
import com.lambdaworks.redis.api.StatefulRedisConnection;
|
||||
import com.lambdaworks.redis.api.async.RedisAsyncCommands;
|
||||
import com.lambdaworks.redis.codec.RedisCodec;
|
||||
import com.lambdaworks.redis.pubsub.RedisPubSubConnection;
|
||||
import com.lambdaworks.redis.pubsub.StatefulRedisPubSubConnection;
|
||||
|
||||
/**
|
||||
* Extension of {@link RedisClient} that calls auth on all new connections using the supplied credentials
|
||||
*
|
||||
* @author Jennifer Hickey
|
||||
* @author Mar Paluch
|
||||
* @author Mark Paluch
|
||||
* @author Christoph Strobl
|
||||
* @deprecated since 1.6 - Please use {@link RedisURI#setPassword(String)}
|
||||
*/
|
||||
@Deprecated
|
||||
public class AuthenticatingRedisClient extends RedisClient {
|
||||
|
||||
private String password;
|
||||
|
||||
public AuthenticatingRedisClient(String host, int port, String password) {
|
||||
super(host, port);
|
||||
this.password = password;
|
||||
super(null, RedisURI.builder().withHost(host).withPort(port).withPassword(password).build());
|
||||
}
|
||||
|
||||
public AuthenticatingRedisClient(String host, String password) {
|
||||
super(host);
|
||||
this.password = password;
|
||||
super(null, RedisURI.builder().withHost(host).withPassword(password).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K, V> RedisConnection<K, V> connect(RedisCodec<K, V> codec) {
|
||||
RedisConnection<K, V> conn = super.connect(codec);
|
||||
conn.auth(password);
|
||||
return conn;
|
||||
public <K, V> StatefulRedisConnection<K, V> connect(RedisCodec<K, V> codec) {
|
||||
return super.connect(codec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K, V> RedisAsyncConnection<K, V> connectAsync(RedisCodec<K, V> codec) {
|
||||
RedisAsyncConnection<K, V> conn = super.connectAsync(codec);
|
||||
conn.auth(password);
|
||||
return conn;
|
||||
public <K, V> RedisAsyncCommands<K, V> connectAsync(RedisCodec<K, V> codec) {
|
||||
return super.connectAsync(codec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K, V> RedisPubSubConnection<K, V> connectPubSub(RedisCodec<K, V> codec) {
|
||||
RedisPubSubConnection<K, V> conn = super.connectPubSub(codec);
|
||||
conn.auth(password);
|
||||
return conn;
|
||||
public <K, V> StatefulRedisPubSubConnection<K, V> connectPubSub(RedisCodec<K, V> codec) {
|
||||
return super.connectPubSub(codec);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.lambdaworks.redis.codec.RedisCodec;
|
||||
|
||||
/**
|
||||
* Basic codec that returns the raw data as byte[].
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
class BytesRedisCodec extends RedisCodec<byte[], byte[]> {
|
||||
|
||||
@Override
|
||||
public byte[] decodeKey(ByteBuffer bytes) {
|
||||
return getBytes(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] decodeValue(ByteBuffer bytes) {
|
||||
return getBytes(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encodeKey(byte[] key) {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encodeValue(byte[] value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
private static byte[] getBytes(ByteBuffer buffer) {
|
||||
byte[] b = new byte[buffer.remaining()];
|
||||
buffer.get(b);
|
||||
return b;
|
||||
}
|
||||
}
|
||||
@@ -28,9 +28,10 @@ import org.springframework.data.redis.connection.RedisSentinelConfiguration;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.lambdaworks.redis.RedisAsyncConnection;
|
||||
import com.lambdaworks.redis.RedisClient;
|
||||
import com.lambdaworks.redis.RedisURI;
|
||||
import com.lambdaworks.redis.api.StatefulConnection;
|
||||
import com.lambdaworks.redis.api.StatefulRedisConnection;
|
||||
import com.lambdaworks.redis.resource.ClientResources;
|
||||
|
||||
/**
|
||||
@@ -43,7 +44,7 @@ import com.lambdaworks.redis.resource.ClientResources;
|
||||
public class DefaultLettucePool implements LettucePool, InitializingBean {
|
||||
|
||||
@SuppressWarnings("rawtypes") //
|
||||
private GenericObjectPool<RedisAsyncConnection> internalPool;
|
||||
private GenericObjectPool<StatefulConnection<byte[], byte[]>> internalPool;
|
||||
private RedisClient client;
|
||||
private int dbIndex = 0;
|
||||
private GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
|
||||
@@ -112,7 +113,8 @@ public class DefaultLettucePool implements LettucePool, InitializingBean {
|
||||
}
|
||||
|
||||
client.setDefaultTimeout(timeout, TimeUnit.MILLISECONDS);
|
||||
this.internalPool = new GenericObjectPool<RedisAsyncConnection>(new LettuceFactory(client, dbIndex), poolConfig);
|
||||
this.internalPool = new GenericObjectPool<StatefulConnection<byte[], byte[]>>(new LettuceFactory(client, dbIndex),
|
||||
poolConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,7 +137,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public RedisAsyncConnection<byte[], byte[]> getResource() {
|
||||
public StatefulConnection<byte[], byte[]> getResource() {
|
||||
try {
|
||||
return internalPool.borrowObject();
|
||||
} catch (Exception e) {
|
||||
@@ -143,7 +145,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean {
|
||||
}
|
||||
}
|
||||
|
||||
public void returnBrokenResource(final RedisAsyncConnection<byte[], byte[]> resource) {
|
||||
public void returnBrokenResource(final StatefulConnection<byte[], byte[]> resource) {
|
||||
try {
|
||||
internalPool.invalidateObject(resource);
|
||||
} catch (Exception e) {
|
||||
@@ -151,7 +153,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean {
|
||||
}
|
||||
}
|
||||
|
||||
public void returnResource(final RedisAsyncConnection<byte[], byte[]> resource) {
|
||||
public void returnResource(final StatefulConnection<byte[], byte[]> resource) {
|
||||
try {
|
||||
internalPool.returnObject(resource);
|
||||
} catch (Exception e) {
|
||||
@@ -302,7 +304,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean {
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static class LettuceFactory extends BasePooledObjectFactory<RedisAsyncConnection> {
|
||||
private static class LettuceFactory extends BasePooledObjectFactory<StatefulConnection<byte[], byte[]>> {
|
||||
|
||||
private final RedisClient client;
|
||||
|
||||
@@ -315,11 +317,14 @@ public class DefaultLettucePool implements LettucePool, InitializingBean {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activateObject(PooledObject<RedisAsyncConnection> pooledObject) throws Exception {
|
||||
pooledObject.getObject().select(dbIndex);
|
||||
public void activateObject(PooledObject<StatefulConnection<byte[], byte[]>> pooledObject) throws Exception {
|
||||
|
||||
if (pooledObject.getObject() instanceof StatefulRedisConnection) {
|
||||
((StatefulRedisConnection) pooledObject.getObject()).sync().select(dbIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public void destroyObject(final PooledObject<RedisAsyncConnection> obj) throws Exception {
|
||||
public void destroyObject(final PooledObject<StatefulConnection<byte[], byte[]>> obj) throws Exception {
|
||||
try {
|
||||
obj.getObject().close();
|
||||
} catch (Exception e) {
|
||||
@@ -327,9 +332,11 @@ public class DefaultLettucePool implements LettucePool, InitializingBean {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean validateObject(final PooledObject<RedisAsyncConnection> obj) {
|
||||
public boolean validateObject(final PooledObject<StatefulConnection<byte[], byte[]>> obj) {
|
||||
try {
|
||||
obj.getObject().ping();
|
||||
if (obj.getObject() instanceof StatefulRedisConnection) {
|
||||
((StatefulRedisConnection) obj.getObject()).sync().ping();
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
@@ -337,14 +344,13 @@ public class DefaultLettucePool implements LettucePool, InitializingBean {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RedisAsyncConnection create() throws Exception {
|
||||
return client.connectAsync(LettuceConnection.CODEC);
|
||||
public StatefulConnection<byte[], byte[]> create() throws Exception {
|
||||
return client.connect(LettuceConnection.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PooledObject<RedisAsyncConnection> wrap(RedisAsyncConnection obj) {
|
||||
return new DefaultPooledObject<RedisAsyncConnection>(obj);
|
||||
public PooledObject<StatefulConnection<byte[], byte[]>> wrap(StatefulConnection<byte[], byte[]> obj) {
|
||||
return new DefaultPooledObject<StatefulConnection<byte[], byte[]>>(obj);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.redis.ExceptionTranslationStrategy;
|
||||
import org.springframework.data.redis.PassThroughExceptionTranslationStrategy;
|
||||
@@ -57,14 +57,14 @@ import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import com.lambdaworks.redis.KeyValue;
|
||||
import com.lambdaworks.redis.RedisAsyncConnection;
|
||||
import com.lambdaworks.redis.RedisAsyncConnectionImpl;
|
||||
import com.lambdaworks.redis.RedisClusterConnection;
|
||||
import com.lambdaworks.redis.RedisConnection;
|
||||
import com.lambdaworks.redis.RedisException;
|
||||
import com.lambdaworks.redis.api.StatefulConnection;
|
||||
import com.lambdaworks.redis.cluster.RedisClusterClient;
|
||||
import com.lambdaworks.redis.cluster.SlotHash;
|
||||
import com.lambdaworks.redis.cluster.api.StatefulRedisClusterConnection;
|
||||
import com.lambdaworks.redis.cluster.api.sync.RedisClusterCommands;
|
||||
import com.lambdaworks.redis.cluster.models.partitions.Partitions;
|
||||
import com.lambdaworks.redis.codec.ByteArrayCodec;
|
||||
import com.lambdaworks.redis.codec.RedisCodec;
|
||||
|
||||
/**
|
||||
@@ -77,7 +77,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
|
||||
static final ExceptionTranslationStrategy exceptionConverter = new PassThroughExceptionTranslationStrategy(
|
||||
new LettuceExceptionConverter());
|
||||
static final RedisCodec<byte[], byte[]> CODEC = new BytesRedisCodec();
|
||||
static final RedisCodec<byte[], byte[]> CODEC = ByteArrayCodec.INSTANCE;
|
||||
|
||||
private final RedisClusterClient clusterClient;
|
||||
private ClusterCommandExecutor clusterCommandExecutor;
|
||||
@@ -141,7 +141,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
.executeCommandOnAllNodes(new LettuceClusterCommandCallback<List<byte[]>>() {
|
||||
|
||||
@Override
|
||||
public List<byte[]> doInCluster(RedisClusterConnection<byte[], byte[]> connection) {
|
||||
public List<byte[]> doInCluster(RedisClusterCommands<byte[], byte[]> connection) {
|
||||
return connection.keys(pattern);
|
||||
}
|
||||
}).resultsAsList();
|
||||
@@ -164,7 +164,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnAllNodes(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.flushall();
|
||||
}
|
||||
});
|
||||
@@ -180,7 +180,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnAllNodes(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.flushdb();
|
||||
}
|
||||
});
|
||||
@@ -197,7 +197,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
.executeCommandOnAllNodes(new LettuceClusterCommandCallback<Long>() {
|
||||
|
||||
@Override
|
||||
public Long doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public Long doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.dbsize();
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
.executeCommandOnAllNodes(new LettuceClusterCommandCallback<Properties>() {
|
||||
|
||||
@Override
|
||||
public Properties doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public Properties doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return LettuceConverters.toProperties(client.info());
|
||||
}
|
||||
}).getResults();
|
||||
@@ -249,7 +249,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
.executeCommandOnAllNodes(new LettuceClusterCommandCallback<Properties>() {
|
||||
|
||||
@Override
|
||||
public Properties doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public Properties doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return LettuceConverters.toProperties(client.info(section));
|
||||
}
|
||||
}).getResults();
|
||||
@@ -274,7 +274,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
.toProperties(clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.info(section);
|
||||
}
|
||||
}, node).getValue());
|
||||
@@ -298,16 +298,8 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
|
||||
Assert.noNullElements(keys, "Keys must not be null or contain null key!");
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
return super.del(keys);
|
||||
}
|
||||
|
||||
long total = 0;
|
||||
for (byte[] key : keys) {
|
||||
Long delted = super.del(key);
|
||||
total += (delted != null ? delted.longValue() : 0);
|
||||
}
|
||||
return Long.valueOf(total);
|
||||
// Routing for mget is handled by lettuce itself.
|
||||
return super.del(keys);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -325,7 +317,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
.executeCommandOnSingleNode(new LettuceClusterCommandCallback<Set<RedisClusterNode>>() {
|
||||
|
||||
@Override
|
||||
public Set<RedisClusterNode> doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public Set<RedisClusterNode> doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return LettuceConverters.toSetOfRedisClusterNodes(client.clusterSlaves(nodeToUse.getId()));
|
||||
}
|
||||
}, master).getValue();
|
||||
@@ -371,7 +363,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
return clusterCommandExecutor.executeCommandOnArbitraryNode(new LettuceClusterCommandCallback<ClusterInfo>() {
|
||||
|
||||
@Override
|
||||
public ClusterInfo doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public ClusterInfo doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return new ClusterInfo(LettuceConverters.toProperties(client.clusterInfo()));
|
||||
}
|
||||
}).getValue();
|
||||
@@ -387,7 +379,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.clusterAddSlots(slots);
|
||||
}
|
||||
}, node);
|
||||
@@ -416,7 +408,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.clusterDelSlots(slots);
|
||||
}
|
||||
}, node);
|
||||
@@ -448,7 +440,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
this.clusterCommandExecutor.executeCommandAsyncOnNodes(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.clusterForget(nodeToRemove.getId());
|
||||
}
|
||||
|
||||
@@ -469,7 +461,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
this.clusterCommandExecutor.executeCommandOnAllNodes(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.clusterMeet(node.getHost(), node.getPort());
|
||||
}
|
||||
});
|
||||
@@ -491,7 +483,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
switch (mode) {
|
||||
case MIGRATING:
|
||||
return client.clusterSetSlotMigrating(slot, nodeId);
|
||||
@@ -547,7 +539,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.clusterReplicate(masterNode.getId());
|
||||
}
|
||||
}, slave);
|
||||
@@ -563,8 +555,8 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
.executeCommandOnAllNodes(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> connection) {
|
||||
return doPing(connection);
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> connection) {
|
||||
return connection.ping();
|
||||
}
|
||||
}).resultsAsList();
|
||||
|
||||
@@ -587,29 +579,12 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
return clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
return doPing(client);
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.ping();
|
||||
}
|
||||
}, node).getValue();
|
||||
}
|
||||
|
||||
protected String doPing(RedisClusterConnection<byte[], byte[]> client) {
|
||||
|
||||
if (client instanceof RedisConnection) {
|
||||
return ((RedisConnection) client).ping();
|
||||
}
|
||||
|
||||
if (client instanceof RedisAsyncConnectionImpl) {
|
||||
try {
|
||||
return (String) ((RedisAsyncConnectionImpl) client).ping().get();
|
||||
} catch (Exception e) {
|
||||
throw exceptionConverter.translate(e);
|
||||
}
|
||||
}
|
||||
|
||||
throw new DataAccessResourceFailureException("Cannot execute ping using " + client);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisClusterConnection#bgReWriteAof(org.springframework.data.redis.connection.RedisClusterNode)
|
||||
@@ -620,7 +595,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.bgrewriteaof();
|
||||
}
|
||||
}, node);
|
||||
@@ -636,7 +611,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.bgsave();
|
||||
}
|
||||
}, node);
|
||||
@@ -652,7 +627,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
return clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<Long>() {
|
||||
|
||||
@Override
|
||||
public Long doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public Long doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.lastsave().getTime();
|
||||
}
|
||||
}, node).getValue();
|
||||
@@ -668,7 +643,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.save();
|
||||
}
|
||||
}, node);
|
||||
@@ -685,7 +660,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
return clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<Long>() {
|
||||
|
||||
@Override
|
||||
public Long doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public Long doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.dbsize();
|
||||
}
|
||||
}, node).getValue();
|
||||
@@ -701,7 +676,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.flushdb();
|
||||
}
|
||||
}, node);
|
||||
@@ -717,7 +692,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.flushall();
|
||||
}
|
||||
}, node);
|
||||
@@ -735,7 +710,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
.toProperties(clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.info();
|
||||
}
|
||||
}, node).getValue());
|
||||
@@ -752,7 +727,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<List<byte[]>>() {
|
||||
|
||||
@Override
|
||||
public List<byte[]> doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public List<byte[]> doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.keys(pattern);
|
||||
}
|
||||
}, node).getValue());
|
||||
@@ -768,7 +743,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
return clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<byte[]>() {
|
||||
|
||||
@Override
|
||||
public byte[] doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public byte[] doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.randomkey();
|
||||
}
|
||||
}, node).getValue();
|
||||
@@ -855,7 +830,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<Void>() {
|
||||
|
||||
@Override
|
||||
public Void doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public Void doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
client.shutdown(true);
|
||||
return null;
|
||||
}
|
||||
@@ -899,17 +874,10 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
@Override
|
||||
public List<byte[]> mGet(byte[]... keys) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
return super.mGet(keys);
|
||||
}
|
||||
Assert.notNull(keys, "Keys must not be null!");
|
||||
|
||||
return this.clusterCommandExecutor.executeMuliKeyCommand(new LettuceMultiKeyClusterCommandCallback<byte[]>() {
|
||||
|
||||
@Override
|
||||
public byte[] doInCluster(RedisClusterConnection<byte[], byte[]> client, byte[] key) {
|
||||
return client.get(key);
|
||||
}
|
||||
}, Arrays.asList(keys)).resultsAsListSortBy(keys);
|
||||
// Routing for mget is handled by lettuce itself.
|
||||
return super.mGet(keys);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -919,16 +887,10 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
@Override
|
||||
public void mSet(Map<byte[], byte[]> tuples) {
|
||||
|
||||
Assert.notNull(tuples, "Tuple must not be null!");
|
||||
Assert.notNull(tuples, "Tuples must not be null!");
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(tuples.keySet().toArray(new byte[tuples.keySet().size()][]))) {
|
||||
super.mSet(tuples);
|
||||
return;
|
||||
}
|
||||
|
||||
for (Map.Entry<byte[], byte[]> entry : tuples.entrySet()) {
|
||||
set(entry.getKey(), entry.getValue());
|
||||
}
|
||||
// Routing for msetnx is handled by lettuce itself.
|
||||
super.mSet(tuples);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -966,7 +928,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
.executeMuliKeyCommand(new LettuceMultiKeyClusterCommandCallback<KeyValue<byte[], byte[]>>() {
|
||||
|
||||
@Override
|
||||
public KeyValue<byte[], byte[]> doInCluster(RedisClusterConnection<byte[], byte[]> client, byte[] key) {
|
||||
public KeyValue<byte[], byte[]> doInCluster(RedisClusterCommands<byte[], byte[]> client, byte[] key) {
|
||||
return client.blpop(timeout, key);
|
||||
}
|
||||
}, Arrays.asList(keys)).resultsAsList();
|
||||
@@ -995,7 +957,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
.executeMuliKeyCommand(new LettuceMultiKeyClusterCommandCallback<KeyValue<byte[], byte[]>>() {
|
||||
|
||||
@Override
|
||||
public KeyValue<byte[], byte[]> doInCluster(RedisClusterConnection<byte[], byte[]> client, byte[] key) {
|
||||
public KeyValue<byte[], byte[]> doInCluster(RedisClusterCommands<byte[], byte[]> client, byte[] key) {
|
||||
return client.brpop(timeout, key);
|
||||
}
|
||||
}, Arrays.asList(keys)).resultsAsList();
|
||||
@@ -1045,6 +1007,18 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisConnectionCommands#select(int)
|
||||
*/
|
||||
@Override
|
||||
public void select(int dbIndex) {
|
||||
|
||||
if (dbIndex != 0) {
|
||||
throw new InvalidDataAccessApiUsageException("Cannot SELECT non zero index in cluster mode.");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#sMove(byte[], byte[], byte[])
|
||||
@@ -1079,7 +1053,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
.executeMuliKeyCommand(new LettuceMultiKeyClusterCommandCallback<Set<byte[]>>() {
|
||||
|
||||
@Override
|
||||
public Set<byte[]> doInCluster(RedisClusterConnection<byte[], byte[]> client, byte[] key) {
|
||||
public Set<byte[]> doInCluster(RedisClusterCommands<byte[], byte[]> client, byte[] key) {
|
||||
return client.smembers(key);
|
||||
}
|
||||
}, Arrays.asList(keys)).resultsAsList();
|
||||
@@ -1140,7 +1114,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
.executeMuliKeyCommand(new LettuceMultiKeyClusterCommandCallback<Set<byte[]>>() {
|
||||
|
||||
@Override
|
||||
public Set<byte[]> doInCluster(RedisClusterConnection<byte[], byte[]> client, byte[] key) {
|
||||
public Set<byte[]> doInCluster(RedisClusterCommands<byte[], byte[]> client, byte[] key) {
|
||||
return client.smembers(key);
|
||||
}
|
||||
}, Arrays.asList(keys)).resultsAsList();
|
||||
@@ -1196,7 +1170,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
.executeMuliKeyCommand(new LettuceMultiKeyClusterCommandCallback<Set<byte[]>>() {
|
||||
|
||||
@Override
|
||||
public Set<byte[]> doInCluster(RedisClusterConnection<byte[], byte[]> client, byte[] key) {
|
||||
public Set<byte[]> doInCluster(RedisClusterCommands<byte[], byte[]> client, byte[] key) {
|
||||
return client.smembers(key);
|
||||
}
|
||||
}, Arrays.asList(others)).resultsAsList();
|
||||
@@ -1238,8 +1212,8 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#getAsyncDedicatedConnection()
|
||||
*/
|
||||
@Override
|
||||
protected RedisAsyncConnection<byte[], byte[]> doGetAsyncDedicatedConnection() {
|
||||
return (RedisAsyncConnection<byte[], byte[]>) clusterClient.connectClusterAsync(CODEC);
|
||||
protected StatefulConnection<byte[], byte[]> doGetAsyncDedicatedConnection() {
|
||||
return clusterClient.connect(CODEC);
|
||||
}
|
||||
|
||||
// --> cluster node stuff
|
||||
@@ -1332,7 +1306,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
.executeCommandOnAllNodes(new LettuceClusterCommandCallback<List<String>>() {
|
||||
|
||||
@Override
|
||||
public List<String> doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public List<String> doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.configGet(pattern);
|
||||
}
|
||||
}).getResults();
|
||||
@@ -1360,7 +1334,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
return clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<List<String>>() {
|
||||
|
||||
@Override
|
||||
public List<String> doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public List<String> doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.configGet(pattern);
|
||||
}
|
||||
}, node).getValue();
|
||||
@@ -1376,7 +1350,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnAllNodes(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.configSet(param, value);
|
||||
}
|
||||
});
|
||||
@@ -1392,7 +1366,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.configSet(param, value);
|
||||
}
|
||||
}, node);
|
||||
@@ -1409,7 +1383,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnAllNodes(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.configResetstat();
|
||||
}
|
||||
});
|
||||
@@ -1425,7 +1399,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.configResetstat();
|
||||
}
|
||||
}, node);
|
||||
@@ -1442,7 +1416,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnArbitraryNode(new LettuceClusterCommandCallback<List<byte[]>>() {
|
||||
|
||||
@Override
|
||||
public List<byte[]> doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public List<byte[]> doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.time();
|
||||
}
|
||||
}).getValue());
|
||||
@@ -1459,7 +1433,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<List<byte[]>>() {
|
||||
|
||||
@Override
|
||||
public List<byte[]> doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public List<byte[]> doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.time();
|
||||
}
|
||||
}, node).getValue());
|
||||
@@ -1485,7 +1459,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
List<String> map = clusterCommandExecutor.executeCommandOnAllNodes(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.clientList();
|
||||
}
|
||||
}).resultsAsList();
|
||||
@@ -1508,7 +1482,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public String doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.clientList();
|
||||
}
|
||||
}, node).getValue());
|
||||
@@ -1525,7 +1499,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
.executeCommandAsyncOnNodes(new LettuceClusterCommandCallback<Collection<RedisClusterNode>>() {
|
||||
|
||||
@Override
|
||||
public Set<RedisClusterNode> doInCluster(RedisClusterConnection<byte[], byte[]> client) {
|
||||
public Set<RedisClusterNode> doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return Converters.toSetOfRedisClusterNodes(client.clusterSlaves(client.clusterMyId()));
|
||||
}
|
||||
}, topologyProvider.getTopology().getActiveMasterNodes()).getResults();
|
||||
@@ -1547,7 +1521,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
* @since 1.7
|
||||
*/
|
||||
protected interface LettuceClusterCommandCallback<T>
|
||||
extends ClusterCommandCallback<RedisClusterConnection<byte[], byte[]>, T> {}
|
||||
extends ClusterCommandCallback<RedisClusterCommands<byte[], byte[]>, T> {}
|
||||
|
||||
/**
|
||||
* Lettuce specific implementation of {@link MultiKeyClusterCommandCallback}.
|
||||
@@ -1557,7 +1531,7 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
* @since 1.7
|
||||
*/
|
||||
protected interface LettuceMultiKeyClusterCommandCallback<T>
|
||||
extends MultiKeyClusterCommandCallback<RedisClusterConnection<byte[], byte[]>, T> {
|
||||
extends MultiKeyClusterCommandCallback<RedisClusterCommands<byte[], byte[]>, T> {
|
||||
|
||||
}
|
||||
|
||||
@@ -1567,9 +1541,10 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
* @author Christoph Strobl
|
||||
* @since 1.7
|
||||
*/
|
||||
static class LettuceClusterNodeResourceProvider implements ClusterNodeResourceProvider {
|
||||
static class LettuceClusterNodeResourceProvider implements ClusterNodeResourceProvider, DisposableBean {
|
||||
|
||||
private final RedisClusterClient client;
|
||||
private volatile StatefulRedisClusterConnection<byte[], byte[]> connection;
|
||||
|
||||
public LettuceClusterNodeResourceProvider(RedisClusterClient client) {
|
||||
|
||||
@@ -1578,14 +1553,20 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public RedisClusterConnection<byte[], byte[]> getResourceForSpecificNode(RedisClusterNode node) {
|
||||
public RedisClusterCommands<byte[], byte[]> getResourceForSpecificNode(RedisClusterNode node) {
|
||||
|
||||
Assert.notNull(node, "Node must not be null!");
|
||||
|
||||
if (connection == null) {
|
||||
synchronized (this) {
|
||||
if (connection == null) {
|
||||
this.connection = client.connect(CODEC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
RedisClusterConnection<byte[], byte[]> connection = client.connectCluster(CODEC).getConnection(node.getHost(),
|
||||
node.getPort());
|
||||
return connection;
|
||||
return connection.getConnection(node.getHost(), node.getPort()).sync();
|
||||
} catch (RedisException e) {
|
||||
|
||||
// unwrap cause when cluster node not known in cluster
|
||||
@@ -1598,12 +1579,14 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void returnResourceForSpecificNode(RedisClusterNode node, Object resource) {
|
||||
public void returnResourceForSpecificNode(RedisClusterNode node, Object resource) {}
|
||||
|
||||
RedisClusterConnection<byte[], byte[]> connection = (RedisClusterConnection<byte[], byte[]>) resource;
|
||||
connection.close();
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.data.redis.connection.lettuce;
|
||||
import static com.lambdaworks.redis.protocol.CommandType.*;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -32,7 +31,6 @@ import java.util.Properties;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -74,7 +72,6 @@ import org.springframework.data.redis.core.types.RedisClientInfo;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import com.lambdaworks.redis.AbstractRedisClient;
|
||||
import com.lambdaworks.redis.GeoArgs;
|
||||
@@ -83,14 +80,9 @@ import com.lambdaworks.redis.GeoWithin;
|
||||
import com.lambdaworks.redis.KeyScanCursor;
|
||||
import com.lambdaworks.redis.LettuceFutures;
|
||||
import com.lambdaworks.redis.MapScanCursor;
|
||||
import com.lambdaworks.redis.RedisAsyncConnection;
|
||||
import com.lambdaworks.redis.RedisAsyncConnectionImpl;
|
||||
import com.lambdaworks.redis.RedisChannelHandler;
|
||||
import com.lambdaworks.redis.RedisClient;
|
||||
import com.lambdaworks.redis.RedisClusterConnection;
|
||||
import com.lambdaworks.redis.RedisConnection;
|
||||
import com.lambdaworks.redis.RedisException;
|
||||
import com.lambdaworks.redis.RedisSentinelAsyncConnection;
|
||||
import com.lambdaworks.redis.RedisFuture;
|
||||
import com.lambdaworks.redis.RedisURI;
|
||||
import com.lambdaworks.redis.ScanArgs;
|
||||
import com.lambdaworks.redis.ScoredValue;
|
||||
@@ -98,9 +90,20 @@ import com.lambdaworks.redis.ScoredValueScanCursor;
|
||||
import com.lambdaworks.redis.SortArgs;
|
||||
import com.lambdaworks.redis.ValueScanCursor;
|
||||
import com.lambdaworks.redis.ZStoreArgs;
|
||||
import com.lambdaworks.redis.api.StatefulConnection;
|
||||
import com.lambdaworks.redis.api.StatefulRedisConnection;
|
||||
import com.lambdaworks.redis.api.async.RedisAsyncCommands;
|
||||
import com.lambdaworks.redis.api.async.RedisHLLAsyncCommands;
|
||||
import com.lambdaworks.redis.api.sync.RedisCommands;
|
||||
import com.lambdaworks.redis.api.sync.RedisHLLCommands;
|
||||
import com.lambdaworks.redis.cluster.api.StatefulRedisClusterConnection;
|
||||
import com.lambdaworks.redis.cluster.api.async.RedisClusterAsyncCommands;
|
||||
import com.lambdaworks.redis.cluster.api.sync.RedisClusterCommands;
|
||||
import com.lambdaworks.redis.codec.ByteArrayCodec;
|
||||
import com.lambdaworks.redis.codec.RedisCodec;
|
||||
import com.lambdaworks.redis.output.BooleanOutput;
|
||||
import com.lambdaworks.redis.output.ByteArrayOutput;
|
||||
import com.lambdaworks.redis.output.CommandOutput;
|
||||
import com.lambdaworks.redis.output.DateOutput;
|
||||
import com.lambdaworks.redis.output.DoubleOutput;
|
||||
import com.lambdaworks.redis.output.IntegerOutput;
|
||||
@@ -114,9 +117,9 @@ import com.lambdaworks.redis.output.ValueOutput;
|
||||
import com.lambdaworks.redis.output.ValueSetOutput;
|
||||
import com.lambdaworks.redis.protocol.Command;
|
||||
import com.lambdaworks.redis.protocol.CommandArgs;
|
||||
import com.lambdaworks.redis.protocol.CommandOutput;
|
||||
import com.lambdaworks.redis.protocol.CommandType;
|
||||
import com.lambdaworks.redis.pubsub.RedisPubSubConnection;
|
||||
import com.lambdaworks.redis.pubsub.StatefulRedisPubSubConnection;
|
||||
import com.lambdaworks.redis.sentinel.api.StatefulRedisSentinelConnection;
|
||||
|
||||
/**
|
||||
* {@code RedisConnection} implementation on top of <a href="https://github.com/mp911de/lettuce">Lettuce</a> Redis
|
||||
@@ -132,9 +135,8 @@ import com.lambdaworks.redis.pubsub.RedisPubSubConnection;
|
||||
*/
|
||||
public class LettuceConnection extends AbstractRedisConnection {
|
||||
|
||||
static final RedisCodec<byte[], byte[]> CODEC = new BytesRedisCodec();
|
||||
static final RedisCodec<byte[], byte[]> CODEC = ByteArrayCodec.INSTANCE;
|
||||
|
||||
private static final Method SYNC_HANDLER;
|
||||
private static final ExceptionTranslationStrategy EXCEPTION_TRANSLATION = new FallbackExceptionTranslationStrategy(
|
||||
LettuceConverters.exceptionConverter());
|
||||
private static final TypeHints typeHints = new TypeHints();
|
||||
@@ -142,16 +144,8 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
private final int defaultDbIndex;
|
||||
private int dbIndex;
|
||||
|
||||
static {
|
||||
SYNC_HANDLER = ReflectionUtils.findMethod(AbstractRedisClient.class, "syncHandler", RedisChannelHandler.class,
|
||||
Class[].class);
|
||||
ReflectionUtils.makeAccessible(SYNC_HANDLER);
|
||||
}
|
||||
|
||||
private final com.lambdaworks.redis.RedisAsyncConnection<byte[], byte[]> asyncSharedConn;
|
||||
private final com.lambdaworks.redis.RedisConnection<byte[], byte[]> sharedConn;
|
||||
private com.lambdaworks.redis.RedisAsyncConnection<byte[], byte[]> asyncDedicatedConn;
|
||||
private com.lambdaworks.redis.RedisConnection<byte[], byte[]> dedicatedConn;
|
||||
private final StatefulConnection<byte[], byte[]> asyncSharedConn;
|
||||
private StatefulConnection<byte[], byte[]> asyncDedicatedConn;
|
||||
|
||||
private final long timeout;
|
||||
|
||||
@@ -169,13 +163,13 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
private boolean convertPipelineAndTxResults = true;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private class LettuceResult extends FutureResult<Command<?, ?, ?>> {
|
||||
private class LettuceResult extends FutureResult<com.lambdaworks.redis.protocol.RedisCommand<?, ?, ?>> {
|
||||
public <T> LettuceResult(Future<T> resultHolder, Converter<T, ?> converter) {
|
||||
super((Command) resultHolder, converter);
|
||||
super((com.lambdaworks.redis.protocol.RedisCommand) resultHolder, converter);
|
||||
}
|
||||
|
||||
public LettuceResult(Future resultHolder) {
|
||||
super((Command) resultHolder);
|
||||
super((com.lambdaworks.redis.protocol.RedisCommand) resultHolder);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -183,10 +177,10 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
public Object get() {
|
||||
try {
|
||||
if (convertPipelineAndTxResults && converter != null) {
|
||||
return converter.convert(resultHolder.get());
|
||||
return converter.convert(resultHolder.getOutput().get());
|
||||
}
|
||||
return resultHolder.get();
|
||||
} catch (ExecutionException e) {
|
||||
return resultHolder.getOutput().get();
|
||||
} catch (Exception e) {
|
||||
throw EXCEPTION_TRANSLATION.translate(e);
|
||||
}
|
||||
}
|
||||
@@ -292,8 +286,7 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
* @param timeout The connection timeout (in milliseconds)
|
||||
* @param client The {@link RedisClient} to use when making pub/sub, blocking, and tx connections
|
||||
*/
|
||||
public LettuceConnection(com.lambdaworks.redis.RedisAsyncConnection<byte[], byte[]> sharedConnection, long timeout,
|
||||
RedisClient client) {
|
||||
public LettuceConnection(StatefulRedisConnection<byte[], byte[]> sharedConnection, long timeout, RedisClient client) {
|
||||
this(sharedConnection, timeout, client, null);
|
||||
}
|
||||
|
||||
@@ -306,8 +299,8 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
* @param client The {@link RedisClient} to use when making pub/sub connections
|
||||
* @param pool The connection pool to use for blocking and tx operations
|
||||
*/
|
||||
public LettuceConnection(com.lambdaworks.redis.RedisAsyncConnection<byte[], byte[]> sharedConnection, long timeout,
|
||||
RedisClient client, LettucePool pool) {
|
||||
public LettuceConnection(StatefulRedisConnection<byte[], byte[]> sharedConnection, long timeout, RedisClient client,
|
||||
LettucePool pool) {
|
||||
|
||||
this(sharedConnection, timeout, client, pool, 0);
|
||||
}
|
||||
@@ -321,13 +314,12 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
* @param defaultDbIndex The db index to use along with {@link RedisClient} when establishing a dedicated connection.
|
||||
* @since 1.7
|
||||
*/
|
||||
public LettuceConnection(com.lambdaworks.redis.RedisAsyncConnection<byte[], byte[]> sharedConnection, long timeout,
|
||||
public LettuceConnection(StatefulRedisConnection<byte[], byte[]> sharedConnection, long timeout,
|
||||
AbstractRedisClient client, LettucePool pool, int defaultDbIndex) {
|
||||
|
||||
this.asyncSharedConn = sharedConnection;
|
||||
this.timeout = timeout;
|
||||
this.client = client;
|
||||
this.sharedConn = sharedConnection != null ? syncConnection(asyncSharedConn) : null;
|
||||
this.pool = pool;
|
||||
this.defaultDbIndex = defaultDbIndex;
|
||||
this.dbIndex = this.defaultDbIndex;
|
||||
@@ -344,11 +336,13 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private Object await(com.lambdaworks.redis.protocol.RedisCommand cmd) {
|
||||
if (isMulti && cmd instanceof Command && ((Command) cmd).isMulti()) {
|
||||
private Object await(RedisFuture<?> cmd) {
|
||||
|
||||
if (isMulti) {
|
||||
return null;
|
||||
}
|
||||
return LettuceFutures.await(cmd, timeout, TimeUnit.MILLISECONDS);
|
||||
|
||||
return LettuceFutures.awaitOrCancel(cmd, timeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -380,21 +374,21 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
cmdArg.addKeys(args);
|
||||
}
|
||||
|
||||
RedisAsyncConnectionImpl<byte[], byte[]> connectionImpl = (RedisAsyncConnectionImpl<byte[], byte[]>) getAsyncConnection();
|
||||
RedisClusterAsyncCommands<byte[], byte[]> connectionImpl = getAsyncConnection();
|
||||
|
||||
CommandOutput expectedOutput = commandOutputTypeHint != null ? commandOutputTypeHint
|
||||
: typeHints.getTypeHint(commandType);
|
||||
Command cmd = new Command(commandType, expectedOutput, cmdArg);
|
||||
if (isPipelined()) {
|
||||
|
||||
pipeline(new LettuceResult(connectionImpl.dispatch(cmd)));
|
||||
pipeline(new LettuceResult(connectionImpl.dispatch(cmd.getType(), cmd.getOutput(), cmd.getArgs())));
|
||||
return null;
|
||||
} else if (isQueueing()) {
|
||||
|
||||
transaction(new LettuceTxResult(connectionImpl.dispatch(cmd)));
|
||||
transaction(new LettuceTxResult(connectionImpl.dispatch(cmd.getType(), cmd.getOutput(), cmd.getArgs())));
|
||||
return null;
|
||||
} else {
|
||||
return await(connectionImpl.dispatch(cmd));
|
||||
return await(connectionImpl.dispatch(cmd.getType(), cmd.getOutput(), cmd.getArgs()));
|
||||
}
|
||||
} catch (RedisException ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
@@ -445,8 +439,8 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
return isClosed && !isSubscribed();
|
||||
}
|
||||
|
||||
public RedisAsyncConnection<byte[], byte[]> getNativeConnection() {
|
||||
return (subscription != null ? subscription.pubsub : getAsyncConnection());
|
||||
public RedisClusterAsyncCommands<byte[], byte[]> getNativeConnection() {
|
||||
return (subscription != null ? subscription.pubsub.async() : getAsyncConnection());
|
||||
}
|
||||
|
||||
public boolean isQueueing() {
|
||||
@@ -467,47 +461,56 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
public List<Object> closePipeline() {
|
||||
if (isPipelined) {
|
||||
isPipelined = false;
|
||||
List<Command<?, ?, ?>> futures = new ArrayList<Command<?, ?, ?>>();
|
||||
List<com.lambdaworks.redis.protocol.RedisCommand<?, ?, ?>> futures = new ArrayList<com.lambdaworks.redis.protocol.RedisCommand<?, ?, ?>>();
|
||||
for (LettuceResult result : ppline) {
|
||||
futures.add(result.getResultHolder());
|
||||
}
|
||||
boolean done = LettuceFutures.awaitAll(timeout, TimeUnit.MILLISECONDS,
|
||||
futures.toArray(new Command[futures.size()]));
|
||||
List<Object> results = new ArrayList<Object>(futures.size());
|
||||
|
||||
Exception problem = null;
|
||||
// boolean done = LettuceFutures.awaitAll(timeout, TimeUnit.MILLISECONDS,
|
||||
// futures.toArray(new Command[futures.size()]));
|
||||
|
||||
if (done) {
|
||||
for (LettuceResult result : ppline) {
|
||||
if (result.getResultHolder().getOutput().hasError()) {
|
||||
Exception err = new InvalidDataAccessApiUsageException(result.getResultHolder().getOutput().getError());
|
||||
// remember only the first error
|
||||
if (problem == null) {
|
||||
problem = err;
|
||||
}
|
||||
results.add(err);
|
||||
} else if (!convertPipelineAndTxResults || !(result.isStatus())) {
|
||||
try {
|
||||
results.add(result.get());
|
||||
} catch (DataAccessException e) {
|
||||
try {
|
||||
boolean done = LettuceFutures.awaitAll(timeout, TimeUnit.MILLISECONDS,
|
||||
futures.toArray(new RedisFuture[futures.size()]));
|
||||
|
||||
List<Object> results = new ArrayList<Object>(futures.size());
|
||||
|
||||
Exception problem = null;
|
||||
|
||||
if (done) {
|
||||
for (LettuceResult result : ppline) {
|
||||
if (result.getResultHolder().getOutput().hasError()) {
|
||||
Exception err = new InvalidDataAccessApiUsageException(result.getResultHolder().getOutput().getError());
|
||||
// remember only the first error
|
||||
if (problem == null) {
|
||||
problem = e;
|
||||
problem = err;
|
||||
}
|
||||
results.add(err);
|
||||
} else if (!convertPipelineAndTxResults || !(result.isStatus())) {
|
||||
try {
|
||||
results.add(result.get());
|
||||
} catch (DataAccessException e) {
|
||||
if (problem == null) {
|
||||
problem = e;
|
||||
}
|
||||
results.add(e);
|
||||
}
|
||||
results.add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ppline.clear();
|
||||
ppline.clear();
|
||||
|
||||
if (problem != null) {
|
||||
throw new RedisPipelineException(problem, results);
|
||||
}
|
||||
if (done) {
|
||||
return results;
|
||||
}
|
||||
if (problem != null) {
|
||||
throw new RedisPipelineException(problem, results);
|
||||
}
|
||||
if (done) {
|
||||
return results;
|
||||
}
|
||||
|
||||
throw new RedisPipelineException(new QueryTimeoutException("Redis command timed out"));
|
||||
throw new RedisPipelineException(new QueryTimeoutException("Redis command timed out"));
|
||||
} catch (Exception e) {
|
||||
throw new RedisPipelineException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
@@ -839,10 +842,10 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
isMulti = false;
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(new LettuceStatusResult(getAsyncDedicatedConnection().discard()));
|
||||
pipeline(new LettuceStatusResult(((RedisAsyncCommands) getAsyncDedicatedConnection()).discard()));
|
||||
return;
|
||||
}
|
||||
getDedicatedConnection().discard();
|
||||
((RedisCommands) getDedicatedConnection()).discard();
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
} finally {
|
||||
@@ -855,11 +858,12 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
isMulti = false;
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(new LettuceResult(getAsyncDedicatedConnection().exec(), new LettuceTransactionResultConverter(
|
||||
new LinkedList<FutureResult<?>>(txResults), LettuceConverters.exceptionConverter())));
|
||||
pipeline(new LettuceResult(((RedisAsyncCommands) getAsyncDedicatedConnection()).exec(),
|
||||
new LettuceTransactionResultConverter(new LinkedList<FutureResult<?>>(txResults),
|
||||
LettuceConverters.exceptionConverter())));
|
||||
return null;
|
||||
}
|
||||
List<Object> results = getDedicatedConnection().exec();
|
||||
List<Object> results = ((RedisCommands) getDedicatedConnection()).exec();
|
||||
return convertPipelineAndTxResults
|
||||
? new LettuceTransactionResultConverter(txResults, LettuceConverters.exceptionConverter()).convert(results)
|
||||
: results;
|
||||
@@ -873,14 +877,16 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
public Boolean exists(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(new LettuceResult(getAsyncConnection().exists(key)));
|
||||
pipeline(new LettuceResult(getAsyncConnection().exists(new byte[][] { key }),
|
||||
LettuceConverters.longToBooleanConverter()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(new LettuceTxResult(getConnection().exists(key)));
|
||||
transaction(new LettuceResult(getAsyncConnection().exists(new byte[][] { key }),
|
||||
LettuceConverters.longToBooleanConverter()));
|
||||
return null;
|
||||
}
|
||||
return getConnection().exists(key);
|
||||
return LettuceConverters.longToBooleanConverter().convert(getConnection().exists(new byte[][] { key }));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
@@ -1055,10 +1061,10 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
isMulti = true;
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
getAsyncDedicatedConnection().multi();
|
||||
((RedisAsyncCommands) getAsyncDedicatedConnection()).multi();
|
||||
return;
|
||||
}
|
||||
getDedicatedConnection().multi();
|
||||
((RedisCommands) getDedicatedConnection()).multi();
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
@@ -1157,10 +1163,10 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
|
||||
this.dbIndex = dbIndex;
|
||||
if (isQueueing()) {
|
||||
transaction(new LettuceTxStatusResult(getConnection().select(dbIndex)));
|
||||
transaction(new LettuceTxStatusResult(((RedisCommands) getAsyncConnection()).select(dbIndex)));
|
||||
return;
|
||||
}
|
||||
getConnection().select(dbIndex);
|
||||
((RedisCommands) getConnection()).select(dbIndex);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
@@ -1235,14 +1241,14 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
public void unwatch() {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(new LettuceStatusResult(getAsyncDedicatedConnection().unwatch()));
|
||||
pipeline(new LettuceStatusResult(((RedisAsyncCommands) getAsyncDedicatedConnection()).unwatch()));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(new LettuceTxStatusResult(getDedicatedConnection().unwatch()));
|
||||
transaction(new LettuceTxStatusResult(((RedisAsyncCommands) getDedicatedConnection()).unwatch()));
|
||||
return;
|
||||
}
|
||||
getDedicatedConnection().unwatch();
|
||||
((RedisCommands) getDedicatedConnection()).unwatch();
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
@@ -1254,10 +1260,14 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
}
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(new LettuceStatusResult(getAsyncDedicatedConnection().watch(keys)));
|
||||
pipeline(new LettuceStatusResult(((RedisAsyncCommands) getAsyncDedicatedConnection()).watch(keys)));
|
||||
return;
|
||||
}
|
||||
getDedicatedConnection().watch(keys);
|
||||
if (isQueueing()) {
|
||||
transaction(new LettuceTxStatusResult(((RedisAsyncCommands) getDedicatedConnection()).watch()));
|
||||
return;
|
||||
}
|
||||
((RedisCommands) getDedicatedConnection()).watch(keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
@@ -2135,13 +2145,13 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
public List<byte[]> sRandMember(byte[] key, long count) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(
|
||||
new LettuceResult(getAsyncConnection().srandmember(key, count), LettuceConverters.bytesSetToBytesList()));
|
||||
pipeline(new LettuceResult((RedisFuture) getAsyncConnection().srandmember(key, count),
|
||||
LettuceConverters.bytesCollectionToBytesList()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(
|
||||
new LettuceTxResult(getConnection().srandmember(key, count), LettuceConverters.bytesSetToBytesList()));
|
||||
transaction(new LettuceTxResult(getConnection().srandmember(key, count),
|
||||
LettuceConverters.bytesCollectionToBytesList()));
|
||||
return null;
|
||||
}
|
||||
return LettuceConverters.toBytesList(getConnection().srandmember(key, count));
|
||||
@@ -3336,7 +3346,19 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
Assert.notNull(members, "Members must not be null!");
|
||||
Assert.noNullElements(members, "Members must not contain null!");
|
||||
|
||||
throw new UnsupportedOperationException("Lettuce does currently not supprt GEOHASH.");
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(new LettuceResult(getAsyncConnection().geohash(key, members)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(new LettuceTxResult(getConnection().geohash(key, members)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().geohash(key, members);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3702,16 +3724,6 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
com.lambdaworks.redis.ScanCursor scanCursor = getScanCursor(cursorId);
|
||||
ScanArgs scanArgs = getScanArgs(options);
|
||||
|
||||
if (isPipelined()) {
|
||||
pipeline(new LettuceResult(getAsyncConnection().scan(scanCursor, scanArgs)));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isQueueing()) {
|
||||
transaction(new LettuceTxResult(getAsyncConnection().scan(scanCursor, scanArgs)));
|
||||
return null;
|
||||
}
|
||||
|
||||
KeyScanCursor<byte[]> keyScanCursor = getConnection().scan(scanCursor, scanArgs);
|
||||
String nextCursorId = keyScanCursor.getCursor();
|
||||
|
||||
@@ -3889,10 +3901,11 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
}
|
||||
}
|
||||
|
||||
private RedisPubSubConnection<byte[], byte[]> switchToPubSub() {
|
||||
private StatefulRedisPubSubConnection<byte[], byte[]> switchToPubSub() {
|
||||
close();
|
||||
// open a pubsub one
|
||||
return ((RedisClient) client).connectPubSub(CODEC);
|
||||
// return ((RedisClient) client).connectPubSub(CODEC);
|
||||
}
|
||||
|
||||
private void pipeline(LettuceResult result) {
|
||||
@@ -3907,63 +3920,91 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
txResults.add(result);
|
||||
}
|
||||
|
||||
private RedisAsyncConnection<byte[], byte[]> getAsyncConnection() {
|
||||
private RedisClusterAsyncCommands<byte[], byte[]> getAsyncConnection() {
|
||||
if (isQueueing()) {
|
||||
return getAsyncDedicatedConnection();
|
||||
}
|
||||
if (asyncSharedConn != null) {
|
||||
return asyncSharedConn;
|
||||
|
||||
if (asyncSharedConn instanceof StatefulRedisConnection) {
|
||||
return ((StatefulRedisConnection<byte[], byte[]>) asyncSharedConn).async();
|
||||
}
|
||||
}
|
||||
return getAsyncDedicatedConnection();
|
||||
}
|
||||
|
||||
protected com.lambdaworks.redis.RedisConnection<byte[], byte[]> getConnection() {
|
||||
protected RedisClusterCommands<byte[], byte[]> getConnection() {
|
||||
|
||||
if (isQueueing()) {
|
||||
return getDedicatedConnection();
|
||||
}
|
||||
if (sharedConn != null) {
|
||||
return sharedConn;
|
||||
if (asyncSharedConn != null) {
|
||||
|
||||
if (asyncSharedConn instanceof StatefulRedisConnection) {
|
||||
return ((StatefulRedisConnection<byte[], byte[]>) asyncSharedConn).sync();
|
||||
}
|
||||
if (asyncSharedConn instanceof StatefulRedisClusterConnection) {
|
||||
return ((StatefulRedisClusterConnection<byte[], byte[]>) asyncSharedConn).sync();
|
||||
}
|
||||
}
|
||||
return getDedicatedConnection();
|
||||
}
|
||||
|
||||
protected RedisAsyncConnection<byte[], byte[]> getAsyncDedicatedConnection() {
|
||||
protected RedisClusterAsyncCommands<byte[], byte[]> getAsyncDedicatedConnection() {
|
||||
if (asyncDedicatedConn == null) {
|
||||
|
||||
asyncDedicatedConn = doGetAsyncDedicatedConnection();
|
||||
|
||||
if (this.pool == null) {
|
||||
this.asyncDedicatedConn.select(dbIndex);
|
||||
}
|
||||
|
||||
if (asyncDedicatedConn instanceof StatefulRedisConnection) {
|
||||
((StatefulRedisConnection<byte[], byte[]>) asyncDedicatedConn).sync().select(dbIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
return asyncDedicatedConn;
|
||||
|
||||
if (asyncDedicatedConn instanceof StatefulRedisConnection) {
|
||||
return ((StatefulRedisConnection<byte[], byte[]>) asyncDedicatedConn).async();
|
||||
}
|
||||
if (asyncDedicatedConn instanceof StatefulRedisClusterConnection) {
|
||||
return ((StatefulRedisClusterConnection<byte[], byte[]>) asyncDedicatedConn).async();
|
||||
}
|
||||
|
||||
throw new IllegalStateException(String.format("%s is not a supported connection type.", asyncDedicatedConn.getClass().getName()));
|
||||
}
|
||||
|
||||
protected RedisAsyncConnection<byte[], byte[]> doGetAsyncDedicatedConnection() {
|
||||
protected StatefulConnection<byte[], byte[]> doGetAsyncDedicatedConnection() {
|
||||
|
||||
if (this.pool != null) {
|
||||
return pool.getResource();
|
||||
} else {
|
||||
return ((RedisClient) client).connectAsync(CODEC);
|
||||
return ((RedisClient) client).connect(CODEC);
|
||||
}
|
||||
}
|
||||
|
||||
private com.lambdaworks.redis.RedisConnection<byte[], byte[]> getDedicatedConnection() {
|
||||
if (dedicatedConn == null) {
|
||||
this.dedicatedConn = syncConnection(getAsyncDedicatedConnection());
|
||||
}
|
||||
return dedicatedConn;
|
||||
}
|
||||
private RedisClusterCommands<byte[], byte[]> getDedicatedConnection() {
|
||||
|
||||
if (asyncDedicatedConn == null) {
|
||||
|
||||
asyncDedicatedConn = doGetAsyncDedicatedConnection();
|
||||
|
||||
if (this.pool == null) {
|
||||
|
||||
if (asyncDedicatedConn instanceof StatefulRedisConnection) {
|
||||
((StatefulRedisConnection<byte[], byte[]>) asyncDedicatedConn).sync().select(dbIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private com.lambdaworks.redis.RedisConnection<byte[], byte[]> syncConnection(
|
||||
RedisAsyncConnection<byte[], byte[]> asyncConnection) {
|
||||
try {
|
||||
return (com.lambdaworks.redis.RedisConnection<byte[], byte[]>) SYNC_HANDLER.invoke(null, asyncConnection,
|
||||
new Class[] { com.lambdaworks.redis.RedisConnection.class, RedisClusterConnection.class });
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
|
||||
if (asyncDedicatedConn instanceof StatefulRedisConnection) {
|
||||
return ((StatefulRedisConnection<byte[], byte[]>) asyncDedicatedConn).sync();
|
||||
}
|
||||
if (asyncDedicatedConn instanceof StatefulRedisClusterConnection) {
|
||||
return ((StatefulRedisClusterConnection<byte[], byte[]>) asyncDedicatedConn).sync();
|
||||
}
|
||||
|
||||
throw new IllegalStateException(String.format("%s is not a supported connection type.", asyncDedicatedConn.getClass().getName()));
|
||||
}
|
||||
|
||||
private Future<Long> asyncBitOp(BitOperation op, byte[] destination, byte[]... keys) {
|
||||
@@ -4025,7 +4066,12 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
return null;
|
||||
}
|
||||
|
||||
ScanArgs scanArgs = ScanArgs.Builder.matches(options.getPattern());
|
||||
ScanArgs scanArgs = new ScanArgs();
|
||||
|
||||
if (options.getPattern() != null) {
|
||||
scanArgs.match(options.getPattern());
|
||||
}
|
||||
|
||||
if (options.getCount() != null) {
|
||||
scanArgs.limit(options.getCount());
|
||||
}
|
||||
@@ -4082,10 +4128,10 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
return false;
|
||||
}
|
||||
|
||||
RedisConnection<String, String> connection = null;
|
||||
StatefulRedisConnection<String, String> connection = null;
|
||||
try {
|
||||
connection = ((RedisClient) client).connect(getRedisURI(node));
|
||||
return connection.ping().equalsIgnoreCase("pong");
|
||||
return connection.sync().ping().equalsIgnoreCase("pong");
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
} finally {
|
||||
@@ -4105,8 +4151,8 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
*/
|
||||
@Override
|
||||
protected RedisSentinelConnection getSentinelConnection(RedisNode sentinel) {
|
||||
RedisSentinelAsyncConnection<String, String> connection = ((RedisClient) client)
|
||||
.connectSentinelAsync(getRedisURI(sentinel));
|
||||
StatefulRedisSentinelConnection<String, String> connection = ((RedisClient) client)
|
||||
.connectSentinel(getRedisURI(sentinel));
|
||||
return new LettuceSentinelConnection(connection);
|
||||
}
|
||||
|
||||
@@ -4363,30 +4409,19 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
if (values.length == 1) {
|
||||
pipeline(new LettuceResult(getAsyncConnection().pfadd(key, values[0])));
|
||||
} else {
|
||||
pipeline(
|
||||
new LettuceResult(getAsyncConnection().pfadd(key, values[0], LettuceConverters.subarray(values, 1))));
|
||||
}
|
||||
RedisHLLAsyncCommands<byte[], byte[]> asyncConnection = getAsyncConnection();
|
||||
pipeline(new LettuceResult(asyncConnection.pfadd(key, values)));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isQueueing()) {
|
||||
if (values.length == 1) {
|
||||
transaction(new LettuceTxResult(getConnection().pfadd(key, values[0])));
|
||||
} else {
|
||||
transaction(
|
||||
new LettuceTxResult(getConnection().pfadd(key, values[0], LettuceConverters.subarray(values, 1))));
|
||||
}
|
||||
|
||||
RedisHLLAsyncCommands<byte[], byte[]> asyncConnection = getAsyncConnection();
|
||||
transaction(new LettuceResult(asyncConnection.pfadd(key, values)));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (values.length == 1) {
|
||||
return getConnection().pfadd(key, values[0]);
|
||||
}
|
||||
|
||||
return getConnection().pfadd(key, values[0], LettuceConverters.subarray(values, 1));
|
||||
RedisHLLCommands<byte[], byte[]> connection = getConnection();
|
||||
return connection.pfadd(key, values);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
@@ -4403,28 +4438,19 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
Assert.noNullElements(keys, "Keys for PFCOUNT must not contain 'null'.");
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
if (keys.length == 1) {
|
||||
pipeline(new LettuceResult(getAsyncConnection().pfcount(keys[0])));
|
||||
} else {
|
||||
pipeline(new LettuceResult(getAsyncConnection().pfcount(keys[0], LettuceConverters.subarray(keys, 1))));
|
||||
}
|
||||
RedisHLLAsyncCommands<byte[], byte[]> asyncConnection = getAsyncConnection();
|
||||
pipeline(new LettuceResult(asyncConnection.pfcount(keys)));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isQueueing()) {
|
||||
if (keys.length == 1) {
|
||||
transaction(new LettuceTxResult(getConnection().pfcount(keys[0])));
|
||||
} else {
|
||||
transaction(new LettuceTxResult(getConnection().pfcount(keys[0], LettuceConverters.subarray(keys, 1))));
|
||||
}
|
||||
|
||||
RedisHLLAsyncCommands<byte[], byte[]> asyncConnection = getAsyncConnection();
|
||||
transaction(new LettuceResult(asyncConnection.pfcount(keys)));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (keys.length == 1) {
|
||||
return getConnection().pfcount(keys[0]);
|
||||
}
|
||||
|
||||
return getConnection().pfcount(keys[0], LettuceConverters.subarray(keys, 1));
|
||||
RedisHLLCommands<byte[], byte[]> connection = getConnection();
|
||||
return connection.pfcount(keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
@@ -4442,27 +4468,19 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
if (sourceKeys.length == 1) {
|
||||
pipeline(new LettuceResult(getAsyncConnection().pfmerge(destinationKey, sourceKeys[0])));
|
||||
} else {
|
||||
pipeline(new LettuceResult(
|
||||
getAsyncConnection().pfmerge(destinationKey, sourceKeys[0], LettuceConverters.subarray(sourceKeys, 1))));
|
||||
}
|
||||
}
|
||||
if (isQueueing()) {
|
||||
if (sourceKeys.length == 1) {
|
||||
transaction(new LettuceTxResult(getConnection().pfmerge(destinationKey, sourceKeys[0])));
|
||||
} else {
|
||||
transaction(new LettuceTxResult(
|
||||
getConnection().pfmerge(destinationKey, sourceKeys[0], LettuceConverters.subarray(sourceKeys, 1))));
|
||||
}
|
||||
RedisHLLAsyncCommands<byte[], byte[]> asyncConnection = getAsyncConnection();
|
||||
pipeline(new LettuceResult(asyncConnection.pfmerge(destinationKey, sourceKeys)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (sourceKeys.length == 1) {
|
||||
getConnection().pfmerge(destinationKey, sourceKeys[0]);
|
||||
} else {
|
||||
getConnection().pfmerge(destinationKey, sourceKeys[0], LettuceConverters.subarray(sourceKeys, 1));
|
||||
if (isQueueing()) {
|
||||
RedisHLLAsyncCommands<byte[], byte[]> asyncConnection = getAsyncConnection();
|
||||
transaction(new LettuceResult(asyncConnection.pfmerge(destinationKey, sourceKeys)));
|
||||
return;
|
||||
}
|
||||
|
||||
RedisHLLCommands<byte[], byte[]> connection = getConnection();
|
||||
connection.pfmerge(destinationKey, sourceKeys);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
|
||||
@@ -44,12 +44,10 @@ import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.lambdaworks.redis.AbstractRedisClient;
|
||||
import com.lambdaworks.redis.LettuceFutures;
|
||||
import com.lambdaworks.redis.RedisAsyncConnection;
|
||||
import com.lambdaworks.redis.RedisClient;
|
||||
import com.lambdaworks.redis.RedisException;
|
||||
import com.lambdaworks.redis.RedisFuture;
|
||||
import com.lambdaworks.redis.RedisURI;
|
||||
import com.lambdaworks.redis.api.StatefulRedisConnection;
|
||||
import com.lambdaworks.redis.cluster.RedisClusterClient;
|
||||
import com.lambdaworks.redis.resource.ClientResources;
|
||||
|
||||
@@ -88,7 +86,7 @@ public class LettuceConnectionFactory implements InitializingBean, DisposableBea
|
||||
private long shutdownTimeout = TimeUnit.MILLISECONDS.convert(2, TimeUnit.SECONDS);
|
||||
private boolean validateConnection = false;
|
||||
private boolean shareNativeConnection = true;
|
||||
private RedisAsyncConnection<byte[], byte[]> connection;
|
||||
private StatefulRedisConnection<byte[], byte[]> connection;
|
||||
private LettucePool pool;
|
||||
private int dbIndex = 0;
|
||||
/** Synchronization monitor for the shared Connection */
|
||||
@@ -207,6 +205,7 @@ public class LettuceConnectionFactory implements InitializingBean, DisposableBea
|
||||
}
|
||||
|
||||
public void initConnection() {
|
||||
|
||||
synchronized (this.connectionMonitor) {
|
||||
if (this.connection != null) {
|
||||
resetConnection();
|
||||
@@ -237,11 +236,8 @@ public class LettuceConnectionFactory implements InitializingBean, DisposableBea
|
||||
|
||||
if (connection.isOpen()) {
|
||||
try {
|
||||
RedisFuture<String> ping = connection.ping();
|
||||
LettuceFutures.awaitAll(timeout, TimeUnit.MILLISECONDS, ping);
|
||||
if (PING_REPLY.equalsIgnoreCase(ping.get())) {
|
||||
valid = true;
|
||||
}
|
||||
connection.sync().ping();
|
||||
valid = true;
|
||||
} catch (Exception e) {
|
||||
log.debug("Validation failed", e);
|
||||
}
|
||||
@@ -511,7 +507,7 @@ public class LettuceConnectionFactory implements InitializingBean, DisposableBea
|
||||
this.convertPipelineAndTxResults = convertPipelineAndTxResults;
|
||||
}
|
||||
|
||||
protected RedisAsyncConnection<byte[], byte[]> getSharedConnection() {
|
||||
protected StatefulRedisConnection<byte[], byte[]> getSharedConnection() {
|
||||
if (shareNativeConnection) {
|
||||
synchronized (this.connectionMonitor) {
|
||||
if (this.connection == null) {
|
||||
@@ -527,18 +523,17 @@ public class LettuceConnectionFactory implements InitializingBean, DisposableBea
|
||||
}
|
||||
}
|
||||
|
||||
protected RedisAsyncConnection<byte[], byte[]> createLettuceConnector() {
|
||||
protected StatefulRedisConnection<byte[], byte[]> createLettuceConnector() {
|
||||
try {
|
||||
|
||||
RedisAsyncConnection connection = null;
|
||||
StatefulRedisConnection<byte[], byte[]> connection = null;
|
||||
if (client instanceof RedisClient) {
|
||||
connection = ((RedisClient) client).connectAsync(LettuceConnection.CODEC);
|
||||
connection = ((RedisClient) client).connect(LettuceConnection.CODEC);
|
||||
if (dbIndex > 0) {
|
||||
connection.select(dbIndex);
|
||||
connection.sync().select(dbIndex);
|
||||
}
|
||||
} else {
|
||||
connection = (RedisAsyncConnection<byte[], byte[]>) ((RedisClusterClient) client)
|
||||
.connectClusterAsync(LettuceConnection.CODEC);
|
||||
connection = null;
|
||||
}
|
||||
return connection;
|
||||
} catch (RedisException e) {
|
||||
@@ -630,6 +625,6 @@ public class LettuceConnectionFactory implements InitializingBean, DisposableBea
|
||||
if (!(client instanceof RedisClient)) {
|
||||
throw new InvalidDataAccessResourceUsageException("Unable to connect to sentinels using " + client.getClass());
|
||||
}
|
||||
return new LettuceSentinelConnection(((RedisClient) client).connectSentinelAsync());
|
||||
return new LettuceSentinelConnection(((RedisClient) client).connectSentinel());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.redis.connection.lettuce;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
@@ -73,11 +74,11 @@ import com.lambdaworks.redis.KeyValue;
|
||||
import com.lambdaworks.redis.RedisURI;
|
||||
import com.lambdaworks.redis.ScoredValue;
|
||||
import com.lambdaworks.redis.ScriptOutputType;
|
||||
import com.lambdaworks.redis.SetArgs;
|
||||
import com.lambdaworks.redis.SortArgs;
|
||||
import com.lambdaworks.redis.cluster.models.partitions.Partitions;
|
||||
import com.lambdaworks.redis.cluster.models.partitions.RedisClusterNode.NodeFlag;
|
||||
import com.lambdaworks.redis.protocol.LettuceCharsets;
|
||||
import com.lambdaworks.redis.protocol.SetArgs;
|
||||
|
||||
/**
|
||||
* Lettuce type converters
|
||||
@@ -95,6 +96,7 @@ abstract public class LettuceConverters extends Converters {
|
||||
private static final Converter<byte[], String> BYTES_TO_STRING;
|
||||
private static final Converter<String, byte[]> STRING_TO_BYTES;
|
||||
private static final Converter<Set<byte[]>, List<byte[]>> BYTES_SET_TO_BYTES_LIST;
|
||||
private static final Converter<Collection<byte[]>, List<byte[]>> BYTES_COLLECTION_TO_BYTES_LIST;
|
||||
private static final Converter<KeyValue<byte[], byte[]>, List<byte[]>> KEY_VALUE_TO_BYTES_LIST;
|
||||
private static final Converter<List<ScoredValue<byte[]>>, Set<Tuple>> SCORED_VALUES_TO_TUPLE_SET;
|
||||
private static final Converter<List<ScoredValue<byte[]>>, List<Tuple>> SCORED_VALUES_TO_TUPLE_LIST;
|
||||
@@ -151,6 +153,14 @@ abstract public class LettuceConverters extends Converters {
|
||||
return results != null ? new ArrayList<byte[]>(results) : null;
|
||||
}
|
||||
};
|
||||
BYTES_COLLECTION_TO_BYTES_LIST = new Converter<Collection<byte[]>, List<byte[]>>() {
|
||||
public List<byte[]> convert(Collection<byte[]> results) {
|
||||
if (results instanceof List) {
|
||||
return (List<byte[]>) results;
|
||||
}
|
||||
return results != null ? new ArrayList<byte[]>(results) : null;
|
||||
}
|
||||
};
|
||||
KEY_VALUE_TO_BYTES_LIST = new Converter<KeyValue<byte[], byte[]>, List<byte[]>>() {
|
||||
public List<byte[]> convert(KeyValue<byte[], byte[]> source) {
|
||||
if (source == null) {
|
||||
@@ -365,8 +375,12 @@ abstract public class LettuceConverters extends Converters {
|
||||
return KEY_VALUE_TO_BYTES_LIST;
|
||||
}
|
||||
|
||||
public static Converter<Set<byte[]>, List<byte[]>> bytesSetToBytesList() {
|
||||
return BYTES_SET_TO_BYTES_LIST;
|
||||
public static Converter<Collection<byte[]>, List<byte[]>> bytesSetToBytesList() {
|
||||
return BYTES_COLLECTION_TO_BYTES_LIST;
|
||||
}
|
||||
|
||||
public static Converter<Collection<byte[]>, List<byte[]>> bytesCollectionToBytesList() {
|
||||
return BYTES_COLLECTION_TO_BYTES_LIST;
|
||||
}
|
||||
|
||||
public static Converter<List<ScoredValue<byte[]>>, Set<Tuple>> scoredValuesToTupleSet() {
|
||||
@@ -405,8 +419,8 @@ abstract public class LettuceConverters extends Converters {
|
||||
return KEY_VALUE_TO_BYTES_LIST.convert(source);
|
||||
}
|
||||
|
||||
public static List<byte[]> toBytesList(Set<byte[]> source) {
|
||||
return BYTES_SET_TO_BYTES_LIST.convert(source);
|
||||
public static List<byte[]> toBytesList(Collection<byte[]> source) {
|
||||
return BYTES_COLLECTION_TO_BYTES_LIST.convert(source);
|
||||
}
|
||||
|
||||
public static Set<Tuple> toTupleSet(List<ScoredValue<byte[]>> source) {
|
||||
@@ -769,7 +783,7 @@ abstract public class LettuceConverters extends Converters {
|
||||
public GeoResults<GeoLocation<byte[]>> convert(Set<byte[]> source) {
|
||||
|
||||
if (CollectionUtils.isEmpty(source)) {
|
||||
return new GeoResults<GeoLocation<byte[]>>(Collections.<GeoResult<GeoLocation<byte[]>>> emptyList());
|
||||
return new GeoResults<GeoLocation<byte[]>>(Collections.<GeoResult<GeoLocation<byte[]>>>emptyList());
|
||||
}
|
||||
|
||||
List<GeoResult<GeoLocation<byte[]>>> results = new ArrayList<GeoResult<GeoLocation<byte[]>>>(source.size());
|
||||
|
||||
@@ -18,20 +18,20 @@ package org.springframework.data.redis.connection.lettuce;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import com.lambdaworks.redis.RedisCommandInterruptedException;
|
||||
import com.lambdaworks.redis.RedisCommandTimeoutException;
|
||||
import com.lambdaworks.redis.RedisConnectionException;
|
||||
import com.lambdaworks.redis.RedisException;
|
||||
import io.netty.channel.ChannelException;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.QueryTimeoutException;
|
||||
import org.springframework.data.redis.RedisConnectionFailureException;
|
||||
import org.springframework.data.redis.RedisSystemException;
|
||||
|
||||
import com.lambdaworks.redis.RedisCommandExecutionException;
|
||||
import com.lambdaworks.redis.RedisCommandInterruptedException;
|
||||
import com.lambdaworks.redis.RedisCommandTimeoutException;
|
||||
import com.lambdaworks.redis.RedisConnectionException;
|
||||
import com.lambdaworks.redis.RedisException;
|
||||
|
||||
import io.netty.channel.ChannelException;
|
||||
|
||||
/**
|
||||
* Converts Lettuce Exceptions to {@link DataAccessException}s
|
||||
*
|
||||
@@ -42,9 +42,9 @@ public class LettuceExceptionConverter implements Converter<Exception, DataAcces
|
||||
|
||||
public DataAccessException convert(Exception ex) {
|
||||
|
||||
if (ex instanceof ExecutionException) {
|
||||
if (ex instanceof ExecutionException || ex instanceof RedisCommandExecutionException) {
|
||||
|
||||
if(ex.getCause() != ex && ex.getCause() instanceof Exception) {
|
||||
if (ex.getCause() != ex && ex.getCause() instanceof Exception) {
|
||||
return convert((Exception) ex.getCause());
|
||||
}
|
||||
return new RedisSystemException("Error in execution", ex);
|
||||
|
||||
@@ -18,15 +18,15 @@ package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import org.springframework.data.redis.connection.Pool;
|
||||
|
||||
import com.lambdaworks.redis.RedisAsyncConnection;
|
||||
import com.lambdaworks.redis.RedisClient;
|
||||
import com.lambdaworks.redis.api.StatefulConnection;
|
||||
|
||||
/**
|
||||
* Pool of Lettuce {@link RedisAsyncConnection}s
|
||||
* Pool of Lettuce {@link StatefulConnection}s
|
||||
*
|
||||
* @author Jennifer Hickey
|
||||
*/
|
||||
public interface LettucePool extends Pool<RedisAsyncConnection<byte[], byte[]>> {
|
||||
public interface LettucePool extends Pool<StatefulConnection<byte[], byte[]>> {
|
||||
|
||||
/**
|
||||
* @return The {@link RedisClient} used to create pooled connections
|
||||
|
||||
@@ -27,9 +27,9 @@ import org.springframework.data.redis.connection.RedisServer;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.lambdaworks.redis.RedisClient;
|
||||
import com.lambdaworks.redis.RedisSentinelAsyncConnection;
|
||||
import com.lambdaworks.redis.RedisURI.Builder;
|
||||
import com.lambdaworks.redis.resource.ClientResources;
|
||||
import com.lambdaworks.redis.sentinel.api.StatefulRedisSentinelConnection;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
@@ -42,7 +42,7 @@ public class LettuceSentinelConnection implements RedisSentinelConnection {
|
||||
LettuceConverters.exceptionConverter());
|
||||
|
||||
private RedisClient redisClient;
|
||||
private RedisSentinelAsyncConnection<String, String> connection;
|
||||
private StatefulRedisSentinelConnection<String, String> connection;
|
||||
|
||||
/**
|
||||
* Creates a {@link LettuceSentinelConnection} with a dedicated client for a supplied {@link RedisNode}.
|
||||
@@ -101,7 +101,7 @@ public class LettuceSentinelConnection implements RedisSentinelConnection {
|
||||
*
|
||||
* @param connection native Lettuce connection, must not be {@literal null}
|
||||
*/
|
||||
protected LettuceSentinelConnection(RedisSentinelAsyncConnection<String, String> connection) {
|
||||
protected LettuceSentinelConnection(StatefulRedisSentinelConnection<String, String> connection) {
|
||||
|
||||
Assert.notNull(connection, "Cannot create LettuceSentinelConnection using 'null' as connection.");
|
||||
this.connection = connection;
|
||||
@@ -116,7 +116,7 @@ public class LettuceSentinelConnection implements RedisSentinelConnection {
|
||||
|
||||
Assert.notNull(master, "Redis node master must not be 'null' for failover.");
|
||||
Assert.hasText(master.getName(), "Redis master name must not be 'null' or empty for failover.");
|
||||
connection.failover(master.getName());
|
||||
connection.sync().failover(master.getName());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -126,7 +126,7 @@ public class LettuceSentinelConnection implements RedisSentinelConnection {
|
||||
@Override
|
||||
public List<RedisServer> masters() {
|
||||
try {
|
||||
return LettuceConverters.toListOfRedisServer(connection.masters().get());
|
||||
return LettuceConverters.toListOfRedisServer(connection.sync().masters());
|
||||
} catch (Exception e) {
|
||||
throw EXCEPTION_TRANSLATION.translate(e);
|
||||
}
|
||||
@@ -152,7 +152,7 @@ public class LettuceSentinelConnection implements RedisSentinelConnection {
|
||||
|
||||
Assert.hasText(masterName, "Name of redis master cannot be 'null' or empty when loading slaves.");
|
||||
try {
|
||||
return LettuceConverters.toListOfRedisServer(connection.slaves(masterName).get());
|
||||
return LettuceConverters.toListOfRedisServer(connection.sync().slaves(masterName));
|
||||
} catch (Exception e) {
|
||||
throw EXCEPTION_TRANSLATION.translate(e);
|
||||
}
|
||||
@@ -176,7 +176,7 @@ public class LettuceSentinelConnection implements RedisSentinelConnection {
|
||||
public void remove(String masterName) {
|
||||
|
||||
Assert.hasText(masterName, "Name of redis master cannot be 'null' or empty when trying to remove.");
|
||||
connection.remove(masterName);
|
||||
connection.sync().remove(masterName);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -191,7 +191,8 @@ public class LettuceSentinelConnection implements RedisSentinelConnection {
|
||||
Assert.hasText(server.getHost(), "Host must not be 'null' for server to monitor.");
|
||||
Assert.notNull(server.getPort(), "Port must not be 'null' for server to monitor.");
|
||||
Assert.notNull(server.getQuorum(), "Quorum must not be 'null' for server to monitor.");
|
||||
connection.monitor(server.getName(), server.getHost(), server.getPort().intValue(), server.getQuorum().intValue());
|
||||
connection.sync().monitor(server.getName(), server.getHost(), server.getPort().intValue(),
|
||||
server.getQuorum().intValue());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -214,13 +215,12 @@ public class LettuceSentinelConnection implements RedisSentinelConnection {
|
||||
}
|
||||
}
|
||||
|
||||
private RedisSentinelAsyncConnection<String, String> connectSentinel() {
|
||||
return redisClient.connectSentinelAsync();
|
||||
private StatefulRedisSentinelConnection<String, String> connectSentinel() {
|
||||
return redisClient.connectSentinel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpen() {
|
||||
return connection != null && connection.isOpen();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ package org.springframework.data.redis.connection.lettuce;
|
||||
import org.springframework.data.redis.connection.MessageListener;
|
||||
import org.springframework.data.redis.connection.util.AbstractSubscription;
|
||||
|
||||
import com.lambdaworks.redis.pubsub.RedisPubSubConnection;
|
||||
import com.lambdaworks.redis.pubsub.StatefulRedisPubSubConnection;
|
||||
|
||||
/**
|
||||
* Message subscription on top of Lettuce.
|
||||
@@ -28,10 +28,10 @@ import com.lambdaworks.redis.pubsub.RedisPubSubConnection;
|
||||
*/
|
||||
class LettuceSubscription extends AbstractSubscription {
|
||||
|
||||
final RedisPubSubConnection<byte[], byte[]> pubsub;
|
||||
final StatefulRedisPubSubConnection<byte[], byte[]> pubsub;
|
||||
private LettuceMessageListener listener;
|
||||
|
||||
LettuceSubscription(MessageListener listener, RedisPubSubConnection<byte[], byte[]> pubsubConnection) {
|
||||
LettuceSubscription(MessageListener listener, StatefulRedisPubSubConnection<byte[], byte[]> pubsubConnection) {
|
||||
super(listener);
|
||||
this.pubsub = pubsubConnection;
|
||||
this.listener = new LettuceMessageListener(listener);
|
||||
@@ -41,30 +41,30 @@ class LettuceSubscription extends AbstractSubscription {
|
||||
|
||||
protected void doClose() {
|
||||
if (!getChannels().isEmpty()) {
|
||||
pubsub.unsubscribe(new byte[0]);
|
||||
pubsub.sync().unsubscribe(new byte[0]);
|
||||
}
|
||||
if (!getPatterns().isEmpty()) {
|
||||
pubsub.punsubscribe(new byte[0]);
|
||||
pubsub.sync().punsubscribe(new byte[0]);
|
||||
}
|
||||
pubsub.removeListener(this.listener);
|
||||
pubsub.close();
|
||||
}
|
||||
|
||||
protected void doPsubscribe(byte[]... patterns) {
|
||||
pubsub.psubscribe(patterns);
|
||||
pubsub.sync().psubscribe(patterns);
|
||||
}
|
||||
|
||||
protected void doPUnsubscribe(boolean all, byte[]... patterns) {
|
||||
// lettuce doesn't automatically subscribe from all channels
|
||||
pubsub.punsubscribe(patterns);
|
||||
pubsub.sync().punsubscribe(patterns);
|
||||
}
|
||||
|
||||
protected void doSubscribe(byte[]... channels) {
|
||||
pubsub.subscribe(channels);
|
||||
pubsub.sync().subscribe(channels);
|
||||
}
|
||||
|
||||
protected void doUnsubscribe(boolean all, byte[]... channels) {
|
||||
// lettuce doesn't automatically subscribe from all patterns
|
||||
pubsub.unsubscribe(channels);
|
||||
pubsub.sync().unsubscribe(channels);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import com.lambdaworks.redis.protocol.LettuceCharsets;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.RedisSystemException;
|
||||
import org.springframework.data.redis.connection.DefaultTuple;
|
||||
import org.springframework.data.redis.connection.ReturnType;
|
||||
import org.springframework.data.redis.connection.RedisListCommands.Position;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Aggregate;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Tuple;
|
||||
import org.springframework.data.redis.connection.SortParameters;
|
||||
import org.springframework.data.redis.connection.SortParameters.Order;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.lambdaworks.redis.KeyValue;
|
||||
import com.lambdaworks.redis.RedisCommandInterruptedException;
|
||||
import com.lambdaworks.redis.RedisException;
|
||||
import com.lambdaworks.redis.ScoredValue;
|
||||
import com.lambdaworks.redis.ScriptOutputType;
|
||||
import com.lambdaworks.redis.SortArgs;
|
||||
import com.lambdaworks.redis.ZStoreArgs;
|
||||
import com.lambdaworks.redis.codec.RedisCodec;
|
||||
|
||||
/**
|
||||
* Helper class featuring methods for Lettuce connection handling, providing support for exception translation.
|
||||
* Deprecated in favor of {@link LettuceConverters}
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
@Deprecated
|
||||
abstract class LettuceUtils {
|
||||
|
||||
static final RedisCodec<byte[], byte[]> CODEC = new BytesRedisCodec();
|
||||
|
||||
static DataAccessException convertRedisAccessException(RuntimeException ex) {
|
||||
if (ex instanceof RedisCommandInterruptedException) {
|
||||
return new RedisSystemException("Redis command interrupted", ex);
|
||||
}
|
||||
if (ex instanceof RedisException) {
|
||||
return new RedisSystemException("Redis exception", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static Properties info(String reply) {
|
||||
if (reply == null) {
|
||||
return null;
|
||||
}
|
||||
Properties info = new Properties();
|
||||
StringReader stringReader = new StringReader(reply);
|
||||
try {
|
||||
info.load(stringReader);
|
||||
} catch (Exception ex) {
|
||||
throw new RedisSystemException("Cannot read Redis info", ex);
|
||||
} finally {
|
||||
stringReader.close();
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
static int asBit(boolean value) {
|
||||
return (value ? 1 : 0);
|
||||
}
|
||||
|
||||
static boolean convertPosition(Position where) {
|
||||
Assert.notNull("list positions are mandatory");
|
||||
return (Position.AFTER.equals(where) ? false : true);
|
||||
}
|
||||
|
||||
static Set<Tuple> convertTuple(List<ScoredValue<byte[]>> zrange) {
|
||||
if (zrange == null) {
|
||||
return null;
|
||||
}
|
||||
Set<Tuple> tuples = new LinkedHashSet<Tuple>(zrange.size());
|
||||
|
||||
for (int i = 0; i < zrange.size(); i++) {
|
||||
tuples.add(new DefaultTuple(zrange.get(i).value, Double.valueOf(zrange.get(i).score)));
|
||||
}
|
||||
return tuples;
|
||||
}
|
||||
|
||||
static SortArgs sort(SortParameters params) {
|
||||
SortArgs args = new SortArgs();
|
||||
|
||||
if (params == null) {
|
||||
return args;
|
||||
}
|
||||
|
||||
if (params.getByPattern() != null) {
|
||||
args.by(new String(params.getByPattern(), LettuceCharsets.ASCII));
|
||||
}
|
||||
|
||||
if (params.getLimit() != null) {
|
||||
args.limit(params.getLimit().getStart(), params.getLimit().getCount());
|
||||
}
|
||||
|
||||
if (params.getGetPattern() != null) {
|
||||
byte[][] pattern = params.getGetPattern();
|
||||
for (byte[] bs : pattern) {
|
||||
args.get(new String(bs, LettuceCharsets.ASCII));
|
||||
}
|
||||
}
|
||||
|
||||
if (params.getOrder() != null) {
|
||||
if (params.getOrder() == Order.ASC) {
|
||||
args.asc();
|
||||
} else {
|
||||
args.desc();
|
||||
}
|
||||
}
|
||||
|
||||
Boolean isAlpha = params.isAlphabetic();
|
||||
if (isAlpha != null && isAlpha) {
|
||||
args.alpha();
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
static ZStoreArgs zArgs(Aggregate aggregate, int[] weights) {
|
||||
ZStoreArgs args = new ZStoreArgs();
|
||||
|
||||
if (aggregate != null) {
|
||||
switch (aggregate) {
|
||||
case MIN:
|
||||
args.min();
|
||||
break;
|
||||
case MAX:
|
||||
args.max();
|
||||
break;
|
||||
default:
|
||||
args.sum();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
long[] lg = new long[weights.length];
|
||||
for (int i = 0; i < lg.length; i++) {
|
||||
lg[i] = (long) weights[i];
|
||||
}
|
||||
args.weights(lg);
|
||||
return args;
|
||||
}
|
||||
|
||||
static List<byte[]> toList(KeyValue<byte[], byte[]> blpop) {
|
||||
if (blpop == null) {
|
||||
return null;
|
||||
}
|
||||
List<byte[]> list = new ArrayList<byte[]>(2);
|
||||
list.add(blpop.key);
|
||||
list.add(blpop.value);
|
||||
return list;
|
||||
}
|
||||
|
||||
static ScriptOutputType toScriptOutputType(ReturnType returnType) {
|
||||
switch (returnType) {
|
||||
case BOOLEAN:
|
||||
return ScriptOutputType.BOOLEAN;
|
||||
case MULTI:
|
||||
return ScriptOutputType.MULTI;
|
||||
case VALUE:
|
||||
return ScriptOutputType.VALUE;
|
||||
case INTEGER:
|
||||
return ScriptOutputType.INTEGER;
|
||||
case STATUS:
|
||||
return ScriptOutputType.STATUS;
|
||||
default:
|
||||
throw new IllegalArgumentException("Return type " + returnType + " is not a supported script output type");
|
||||
}
|
||||
}
|
||||
|
||||
static byte[][] extractScriptKeys(int numKeys, byte[]... keysAndArgs) {
|
||||
if (numKeys > 0) {
|
||||
return Arrays.copyOfRange(keysAndArgs, 0, numKeys);
|
||||
}
|
||||
return new byte[0][0];
|
||||
}
|
||||
|
||||
static byte[][] extractScriptArgs(int numKeys, byte[]... keysAndArgs) {
|
||||
if (keysAndArgs.length > numKeys) {
|
||||
return Arrays.copyOfRange(keysAndArgs, numKeys, keysAndArgs.length);
|
||||
}
|
||||
return new byte[0][0];
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user