diff --git a/pom.xml b/pom.xml
index 2486f880c..0e9542456 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
1.9.2
1.4.8
2.2
- 3.4.2.Final
+ 4.2.2.Final
2.9.0
0.7
06052013
diff --git a/src/main/java/org/springframework/data/redis/connection/ClusterCommandExecutor.java b/src/main/java/org/springframework/data/redis/connection/ClusterCommandExecutor.java
index 610d103d5..d1448ab00 100644
--- a/src/main/java/org/springframework/data/redis/connection/ClusterCommandExecutor.java
+++ b/src/main/java/org/springframework/data/redis/connection/ClusterCommandExecutor.java
@@ -372,6 +372,10 @@ public class ClusterCommandExecutor implements DisposableBean {
if (executor instanceof DisposableBean) {
((DisposableBean) executor).destroy();
}
+
+ if (resourceProvider instanceof DisposableBean) {
+ ((DisposableBean) resourceProvider).destroy();
+ }
}
/**
diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/AuthenticatingRedisClient.java b/src/main/java/org/springframework/data/redis/connection/lettuce/AuthenticatingRedisClient.java
index e37a5151d..1853d6da4 100644
--- a/src/main/java/org/springframework/data/redis/connection/lettuce/AuthenticatingRedisClient.java
+++ b/src/main/java/org/springframework/data/redis/connection/lettuce/AuthenticatingRedisClient.java
@@ -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 RedisConnection connect(RedisCodec codec) {
- RedisConnection conn = super.connect(codec);
- conn.auth(password);
- return conn;
+ public StatefulRedisConnection connect(RedisCodec codec) {
+ return super.connect(codec);
}
@Override
- public RedisAsyncConnection connectAsync(RedisCodec codec) {
- RedisAsyncConnection conn = super.connectAsync(codec);
- conn.auth(password);
- return conn;
+ public RedisAsyncCommands connectAsync(RedisCodec codec) {
+ return super.connectAsync(codec);
}
@Override
- public RedisPubSubConnection connectPubSub(RedisCodec codec) {
- RedisPubSubConnection conn = super.connectPubSub(codec);
- conn.auth(password);
- return conn;
+ public StatefulRedisPubSubConnection connectPubSub(RedisCodec codec) {
+ return super.connectPubSub(codec);
}
}
diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/BytesRedisCodec.java b/src/main/java/org/springframework/data/redis/connection/lettuce/BytesRedisCodec.java
deleted file mode 100644
index 67b7d967e..000000000
--- a/src/main/java/org/springframework/data/redis/connection/lettuce/BytesRedisCodec.java
+++ /dev/null
@@ -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 {
-
- @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;
- }
-}
diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettucePool.java b/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettucePool.java
index be52945a9..eb2ef0085 100644
--- a/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettucePool.java
+++ b/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettucePool.java
@@ -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 internalPool;
+ private GenericObjectPool> 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(new LettuceFactory(client, dbIndex), poolConfig);
+ this.internalPool = new GenericObjectPool>(new LettuceFactory(client, dbIndex),
+ poolConfig);
}
/**
@@ -135,7 +137,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean {
}
@SuppressWarnings("unchecked")
- public RedisAsyncConnection getResource() {
+ public StatefulConnection getResource() {
try {
return internalPool.borrowObject();
} catch (Exception e) {
@@ -143,7 +145,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean {
}
}
- public void returnBrokenResource(final RedisAsyncConnection resource) {
+ public void returnBrokenResource(final StatefulConnection resource) {
try {
internalPool.invalidateObject(resource);
} catch (Exception e) {
@@ -151,7 +153,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean {
}
}
- public void returnResource(final RedisAsyncConnection resource) {
+ public void returnResource(final StatefulConnection 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 {
+ private static class LettuceFactory extends BasePooledObjectFactory> {
private final RedisClient client;
@@ -315,11 +317,14 @@ public class DefaultLettucePool implements LettucePool, InitializingBean {
}
@Override
- public void activateObject(PooledObject pooledObject) throws Exception {
- pooledObject.getObject().select(dbIndex);
+ public void activateObject(PooledObject> pooledObject) throws Exception {
+
+ if (pooledObject.getObject() instanceof StatefulRedisConnection) {
+ ((StatefulRedisConnection) pooledObject.getObject()).sync().select(dbIndex);
+ }
}
- public void destroyObject(final PooledObject obj) throws Exception {
+ public void destroyObject(final PooledObject> 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 obj) {
+ public boolean validateObject(final PooledObject> 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 create() throws Exception {
+ return client.connect(LettuceConnection.CODEC);
}
@Override
- public PooledObject wrap(RedisAsyncConnection obj) {
- return new DefaultPooledObject(obj);
+ public PooledObject> wrap(StatefulConnection obj) {
+ return new DefaultPooledObject>(obj);
}
-
}
}
diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnection.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnection.java
index c84461524..107aed9ce 100644
--- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnection.java
+++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnection.java
@@ -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 CODEC = new BytesRedisCodec();
+ static final RedisCodec CODEC = ByteArrayCodec.INSTANCE;
private final RedisClusterClient clusterClient;
private ClusterCommandExecutor clusterCommandExecutor;
@@ -141,7 +141,7 @@ public class LettuceClusterConnection extends LettuceConnection
.executeCommandOnAllNodes(new LettuceClusterCommandCallback>() {
@Override
- public List doInCluster(RedisClusterConnection connection) {
+ public List doInCluster(RedisClusterCommands connection) {
return connection.keys(pattern);
}
}).resultsAsList();
@@ -164,7 +164,7 @@ public class LettuceClusterConnection extends LettuceConnection
clusterCommandExecutor.executeCommandOnAllNodes(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
return client.flushall();
}
});
@@ -180,7 +180,7 @@ public class LettuceClusterConnection extends LettuceConnection
clusterCommandExecutor.executeCommandOnAllNodes(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
return client.flushdb();
}
});
@@ -197,7 +197,7 @@ public class LettuceClusterConnection extends LettuceConnection
.executeCommandOnAllNodes(new LettuceClusterCommandCallback() {
@Override
- public Long doInCluster(RedisClusterConnection client) {
+ public Long doInCluster(RedisClusterCommands client) {
return client.dbsize();
}
@@ -227,7 +227,7 @@ public class LettuceClusterConnection extends LettuceConnection
.executeCommandOnAllNodes(new LettuceClusterCommandCallback() {
@Override
- public Properties doInCluster(RedisClusterConnection client) {
+ public Properties doInCluster(RedisClusterCommands client) {
return LettuceConverters.toProperties(client.info());
}
}).getResults();
@@ -249,7 +249,7 @@ public class LettuceClusterConnection extends LettuceConnection
.executeCommandOnAllNodes(new LettuceClusterCommandCallback() {
@Override
- public Properties doInCluster(RedisClusterConnection client) {
+ public Properties doInCluster(RedisClusterCommands client) {
return LettuceConverters.toProperties(client.info(section));
}
}).getResults();
@@ -274,7 +274,7 @@ public class LettuceClusterConnection extends LettuceConnection
.toProperties(clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands 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>() {
@Override
- public Set doInCluster(RedisClusterConnection client) {
+ public Set doInCluster(RedisClusterCommands client) {
return LettuceConverters.toSetOfRedisClusterNodes(client.clusterSlaves(nodeToUse.getId()));
}
}, master).getValue();
@@ -371,7 +363,7 @@ public class LettuceClusterConnection extends LettuceConnection
return clusterCommandExecutor.executeCommandOnArbitraryNode(new LettuceClusterCommandCallback() {
@Override
- public ClusterInfo doInCluster(RedisClusterConnection client) {
+ public ClusterInfo doInCluster(RedisClusterCommands client) {
return new ClusterInfo(LettuceConverters.toProperties(client.clusterInfo()));
}
}).getValue();
@@ -387,7 +379,7 @@ public class LettuceClusterConnection extends LettuceConnection
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
return client.clusterAddSlots(slots);
}
}, node);
@@ -416,7 +408,7 @@ public class LettuceClusterConnection extends LettuceConnection
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
return client.clusterDelSlots(slots);
}
}, node);
@@ -448,7 +440,7 @@ public class LettuceClusterConnection extends LettuceConnection
this.clusterCommandExecutor.executeCommandAsyncOnNodes(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
return client.clusterForget(nodeToRemove.getId());
}
@@ -469,7 +461,7 @@ public class LettuceClusterConnection extends LettuceConnection
this.clusterCommandExecutor.executeCommandOnAllNodes(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
return client.clusterMeet(node.getHost(), node.getPort());
}
});
@@ -491,7 +483,7 @@ public class LettuceClusterConnection extends LettuceConnection
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
switch (mode) {
case MIGRATING:
return client.clusterSetSlotMigrating(slot, nodeId);
@@ -547,7 +539,7 @@ public class LettuceClusterConnection extends LettuceConnection
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
return client.clusterReplicate(masterNode.getId());
}
}, slave);
@@ -563,8 +555,8 @@ public class LettuceClusterConnection extends LettuceConnection
.executeCommandOnAllNodes(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection connection) {
- return doPing(connection);
+ public String doInCluster(RedisClusterCommands connection) {
+ return connection.ping();
}
}).resultsAsList();
@@ -587,29 +579,12 @@ public class LettuceClusterConnection extends LettuceConnection
return clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
- return doPing(client);
+ public String doInCluster(RedisClusterCommands client) {
+ return client.ping();
}
}, node).getValue();
}
- protected String doPing(RedisClusterConnection 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() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
return client.bgrewriteaof();
}
}, node);
@@ -636,7 +611,7 @@ public class LettuceClusterConnection extends LettuceConnection
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
return client.bgsave();
}
}, node);
@@ -652,7 +627,7 @@ public class LettuceClusterConnection extends LettuceConnection
return clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() {
@Override
- public Long doInCluster(RedisClusterConnection client) {
+ public Long doInCluster(RedisClusterCommands client) {
return client.lastsave().getTime();
}
}, node).getValue();
@@ -668,7 +643,7 @@ public class LettuceClusterConnection extends LettuceConnection
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
return client.save();
}
}, node);
@@ -685,7 +660,7 @@ public class LettuceClusterConnection extends LettuceConnection
return clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() {
@Override
- public Long doInCluster(RedisClusterConnection client) {
+ public Long doInCluster(RedisClusterCommands client) {
return client.dbsize();
}
}, node).getValue();
@@ -701,7 +676,7 @@ public class LettuceClusterConnection extends LettuceConnection
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
return client.flushdb();
}
}, node);
@@ -717,7 +692,7 @@ public class LettuceClusterConnection extends LettuceConnection
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
return client.flushall();
}
}, node);
@@ -735,7 +710,7 @@ public class LettuceClusterConnection extends LettuceConnection
.toProperties(clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
return client.info();
}
}, node).getValue());
@@ -752,7 +727,7 @@ public class LettuceClusterConnection extends LettuceConnection
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback>() {
@Override
- public List doInCluster(RedisClusterConnection client) {
+ public List doInCluster(RedisClusterCommands client) {
return client.keys(pattern);
}
}, node).getValue());
@@ -768,7 +743,7 @@ public class LettuceClusterConnection extends LettuceConnection
return clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() {
@Override
- public byte[] doInCluster(RedisClusterConnection client) {
+ public byte[] doInCluster(RedisClusterCommands client) {
return client.randomkey();
}
}, node).getValue();
@@ -855,7 +830,7 @@ public class LettuceClusterConnection extends LettuceConnection
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() {
@Override
- public Void doInCluster(RedisClusterConnection client) {
+ public Void doInCluster(RedisClusterCommands client) {
client.shutdown(true);
return null;
}
@@ -899,17 +874,10 @@ public class LettuceClusterConnection extends LettuceConnection
@Override
public List 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() {
-
- @Override
- public byte[] doInCluster(RedisClusterConnection 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 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 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>() {
@Override
- public KeyValue doInCluster(RedisClusterConnection client, byte[] key) {
+ public KeyValue doInCluster(RedisClusterCommands client, byte[] key) {
return client.blpop(timeout, key);
}
}, Arrays.asList(keys)).resultsAsList();
@@ -995,7 +957,7 @@ public class LettuceClusterConnection extends LettuceConnection
.executeMuliKeyCommand(new LettuceMultiKeyClusterCommandCallback>() {
@Override
- public KeyValue doInCluster(RedisClusterConnection client, byte[] key) {
+ public KeyValue doInCluster(RedisClusterCommands 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>() {
@Override
- public Set doInCluster(RedisClusterConnection client, byte[] key) {
+ public Set doInCluster(RedisClusterCommands client, byte[] key) {
return client.smembers(key);
}
}, Arrays.asList(keys)).resultsAsList();
@@ -1140,7 +1114,7 @@ public class LettuceClusterConnection extends LettuceConnection
.executeMuliKeyCommand(new LettuceMultiKeyClusterCommandCallback>() {
@Override
- public Set doInCluster(RedisClusterConnection client, byte[] key) {
+ public Set doInCluster(RedisClusterCommands client, byte[] key) {
return client.smembers(key);
}
}, Arrays.asList(keys)).resultsAsList();
@@ -1196,7 +1170,7 @@ public class LettuceClusterConnection extends LettuceConnection
.executeMuliKeyCommand(new LettuceMultiKeyClusterCommandCallback>() {
@Override
- public Set doInCluster(RedisClusterConnection client, byte[] key) {
+ public Set doInCluster(RedisClusterCommands 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 doGetAsyncDedicatedConnection() {
- return (RedisAsyncConnection) clusterClient.connectClusterAsync(CODEC);
+ protected StatefulConnection doGetAsyncDedicatedConnection() {
+ return clusterClient.connect(CODEC);
}
// --> cluster node stuff
@@ -1332,7 +1306,7 @@ public class LettuceClusterConnection extends LettuceConnection
.executeCommandOnAllNodes(new LettuceClusterCommandCallback>() {
@Override
- public List doInCluster(RedisClusterConnection client) {
+ public List doInCluster(RedisClusterCommands client) {
return client.configGet(pattern);
}
}).getResults();
@@ -1360,7 +1334,7 @@ public class LettuceClusterConnection extends LettuceConnection
return clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback>() {
@Override
- public List doInCluster(RedisClusterConnection client) {
+ public List doInCluster(RedisClusterCommands client) {
return client.configGet(pattern);
}
}, node).getValue();
@@ -1376,7 +1350,7 @@ public class LettuceClusterConnection extends LettuceConnection
clusterCommandExecutor.executeCommandOnAllNodes(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
return client.configSet(param, value);
}
});
@@ -1392,7 +1366,7 @@ public class LettuceClusterConnection extends LettuceConnection
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
return client.configSet(param, value);
}
}, node);
@@ -1409,7 +1383,7 @@ public class LettuceClusterConnection extends LettuceConnection
clusterCommandExecutor.executeCommandOnAllNodes(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
return client.configResetstat();
}
});
@@ -1425,7 +1399,7 @@ public class LettuceClusterConnection extends LettuceConnection
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
return client.configResetstat();
}
}, node);
@@ -1442,7 +1416,7 @@ public class LettuceClusterConnection extends LettuceConnection
clusterCommandExecutor.executeCommandOnArbitraryNode(new LettuceClusterCommandCallback>() {
@Override
- public List doInCluster(RedisClusterConnection client) {
+ public List doInCluster(RedisClusterCommands client) {
return client.time();
}
}).getValue());
@@ -1459,7 +1433,7 @@ public class LettuceClusterConnection extends LettuceConnection
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback>() {
@Override
- public List doInCluster(RedisClusterConnection client) {
+ public List doInCluster(RedisClusterCommands client) {
return client.time();
}
}, node).getValue());
@@ -1485,7 +1459,7 @@ public class LettuceClusterConnection extends LettuceConnection
List map = clusterCommandExecutor.executeCommandOnAllNodes(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
return client.clientList();
}
}).resultsAsList();
@@ -1508,7 +1482,7 @@ public class LettuceClusterConnection extends LettuceConnection
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() {
@Override
- public String doInCluster(RedisClusterConnection client) {
+ public String doInCluster(RedisClusterCommands client) {
return client.clientList();
}
}, node).getValue());
@@ -1525,7 +1499,7 @@ public class LettuceClusterConnection extends LettuceConnection
.executeCommandAsyncOnNodes(new LettuceClusterCommandCallback>() {
@Override
- public Set doInCluster(RedisClusterConnection client) {
+ public Set doInCluster(RedisClusterCommands 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
- extends ClusterCommandCallback, T> {}
+ extends ClusterCommandCallback, T> {}
/**
* Lettuce specific implementation of {@link MultiKeyClusterCommandCallback}.
@@ -1557,7 +1531,7 @@ public class LettuceClusterConnection extends LettuceConnection
* @since 1.7
*/
protected interface LettuceMultiKeyClusterCommandCallback
- extends MultiKeyClusterCommandCallback, T> {
+ extends MultiKeyClusterCommandCallback, 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 connection;
public LettuceClusterNodeResourceProvider(RedisClusterClient client) {
@@ -1578,14 +1553,20 @@ public class LettuceClusterConnection extends LettuceConnection
@Override
@SuppressWarnings("unchecked")
- public RedisClusterConnection getResourceForSpecificNode(RedisClusterNode node) {
+ public RedisClusterCommands 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 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 connection = (RedisClusterConnection) resource;
- connection.close();
+ @Override
+ public void destroy() throws Exception {
+ if (connection != null) {
+ connection.close();
+ }
}
-
}
/**
diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java
index bc7f13ac9..453a50844 100644
--- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java
+++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java
@@ -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 Lettuce Redis
@@ -132,9 +135,8 @@ import com.lambdaworks.redis.pubsub.RedisPubSubConnection;
*/
public class LettuceConnection extends AbstractRedisConnection {
- static final RedisCodec CODEC = new BytesRedisCodec();
+ static final RedisCodec 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 asyncSharedConn;
- private final com.lambdaworks.redis.RedisConnection sharedConn;
- private com.lambdaworks.redis.RedisAsyncConnection asyncDedicatedConn;
- private com.lambdaworks.redis.RedisConnection dedicatedConn;
+ private final StatefulConnection asyncSharedConn;
+ private StatefulConnection 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> {
+ private class LettuceResult extends FutureResult> {
public LettuceResult(Future resultHolder, Converter 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 sharedConnection, long timeout,
- RedisClient client) {
+ public LettuceConnection(StatefulRedisConnection 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 sharedConnection, long timeout,
- RedisClient client, LettucePool pool) {
+ public LettuceConnection(StatefulRedisConnection 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 sharedConnection, long timeout,
+ public LettuceConnection(StatefulRedisConnection 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 connectionImpl = (RedisAsyncConnectionImpl) getAsyncConnection();
+ RedisClusterAsyncCommands 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 getNativeConnection() {
- return (subscription != null ? subscription.pubsub : getAsyncConnection());
+ public RedisClusterAsyncCommands getNativeConnection() {
+ return (subscription != null ? subscription.pubsub.async() : getAsyncConnection());
}
public boolean isQueueing() {
@@ -467,47 +461,56 @@ public class LettuceConnection extends AbstractRedisConnection {
public List