Add first test to thorw MovedDataException when receiving MOVED from a cluster node

This commit is contained in:
Marcos Nils
2013-12-07 17:55:17 -03:00
parent 46966fb89f
commit a8987ed865
7 changed files with 775 additions and 13 deletions

View File

@@ -1697,7 +1697,7 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
protected void checkIsInMulti() {
if (client.isInMulti()) {
throw new JedisDataException(
throw new JedisDataException(
"Cannot use Jedis when in Multi. Please use JedisTransaction instead.");
}
}

View File

@@ -1,5 +1,739 @@
package redis.clients.jedis;
public class JedisCluster {
public static final int HASH_SLOTS = 16384;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import redis.clients.jedis.BinaryClient.LIST_POSITION;
import redis.clients.util.Pool;
public class JedisCluster implements JedisCommands, BasicCommands {
public static final short HASHSLOTS = 16384;
private static final int DEFAULT_TIMEOUT = 1;
private Map<String, JedisPool> nodes = new HashMap<String, JedisPool>();
public JedisCluster(Set<HostAndPort> nodes, int timeout) {
initializeSlotsCache(nodes);
}
private void initializeSlotsCache(Set<HostAndPort> nodes) {
for (HostAndPort hostAndPort : nodes) {
JedisPool jp = new JedisPool(hostAndPort.getHost(), hostAndPort.getPort());
this.nodes.put(hostAndPort.getHost()+hostAndPort.getPort(), jp);
}
}
public JedisCluster(Set<HostAndPort> nodes) {
this(nodes, DEFAULT_TIMEOUT);
}
@Override
public String set(String key, String value) {
return getRandomConnection().set(key, value);
}
@Override
public String get(String key) {
return getRandomConnection().get(key);
}
@Override
public Boolean exists(String key) {
return getRandomConnection().exists(key);
}
@Override
public Long persist(String key) {
return getRandomConnection().persist(key);
}
@Override
public String type(String key) {
return getRandomConnection().type(key);
}
@Override
public Long expire(String key, int seconds) {
return getRandomConnection().expire(key, seconds);
}
@Override
public Long expireAt(String key, long unixTime) {
return getRandomConnection().expireAt(key, unixTime);
}
@Override
public Long ttl(String key) {
return getRandomConnection().ttl(key);
}
@Override
public Boolean setbit(String key, long offset, boolean value) {
return getRandomConnection().setbit(key, offset, value);
}
@Override
public Boolean setbit(String key, long offset, String value) {
return getRandomConnection().setbit(key, offset, value);
}
@Override
public Boolean getbit(String key, long offset) {
return getRandomConnection().getbit(key, offset);
}
@Override
public Long setrange(String key, long offset, String value) {
return getRandomConnection().setrange(key, offset, value);
}
@Override
public String getrange(String key, long startOffset, long endOffset) {
return getRandomConnection().getrange(key, startOffset, endOffset);
}
@Override
public String getSet(String key, String value) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long setnx(String key, String value) {
// TODO Auto-generated method stub
return null;
}
@Override
public String setex(String key, int seconds, String value) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long decrBy(String key, long integer) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long decr(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long incrBy(String key, long integer) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long incr(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long append(String key, String value) {
// TODO Auto-generated method stub
return null;
}
@Override
public String substr(String key, int start, int end) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long hset(String key, String field, String value) {
// TODO Auto-generated method stub
return null;
}
@Override
public String hget(String key, String field) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long hsetnx(String key, String field, String value) {
// TODO Auto-generated method stub
return null;
}
@Override
public String hmset(String key, Map<String, String> hash) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<String> hmget(String key, String... fields) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long hincrBy(String key, String field, long value) {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean hexists(String key, String field) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long hdel(String key, String... field) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long hlen(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<String> hkeys(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<String> hvals(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public Map<String, String> hgetAll(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long rpush(String key, String... string) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long lpush(String key, String... string) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long llen(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<String> lrange(String key, long start, long end) {
// TODO Auto-generated method stub
return null;
}
@Override
public String ltrim(String key, long start, long end) {
// TODO Auto-generated method stub
return null;
}
@Override
public String lindex(String key, long index) {
// TODO Auto-generated method stub
return null;
}
@Override
public String lset(String key, long index, String value) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long lrem(String key, long count, String value) {
// TODO Auto-generated method stub
return null;
}
@Override
public String lpop(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public String rpop(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long sadd(String key, String... member) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<String> smembers(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long srem(String key, String... member) {
// TODO Auto-generated method stub
return null;
}
@Override
public String spop(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long scard(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean sismember(String key, String member) {
// TODO Auto-generated method stub
return null;
}
@Override
public String srandmember(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long strlen(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long zadd(String key, double score, String member) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long zadd(String key, Map<Double, String> scoreMembers) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<String> zrange(String key, long start, long end) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long zrem(String key, String... member) {
// TODO Auto-generated method stub
return null;
}
@Override
public Double zincrby(String key, double score, String member) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long zrank(String key, String member) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long zrevrank(String key, String member) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<String> zrevrange(String key, long start, long end) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<Tuple> zrangeWithScores(String key, long start, long end) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<Tuple> zrevrangeWithScores(String key, long start, long end) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long zcard(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public Double zscore(String key, String member) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<String> sort(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<String> sort(String key, SortingParams sortingParameters) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long zcount(String key, double min, double max) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long zcount(String key, String min, String max) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<String> zrangeByScore(String key, double min, double max) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<String> zrangeByScore(String key, String min, String max) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<String> zrevrangeByScore(String key, double max, double min) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<String> zrangeByScore(String key, double min, double max,
int offset, int count) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<String> zrevrangeByScore(String key, String max, String min) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<String> zrangeByScore(String key, String min, String max,
int offset, int count) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<String> zrevrangeByScore(String key, double max, double min,
int offset, int count) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<Tuple> zrangeByScoreWithScores(String key, double min, double max) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<Tuple> zrevrangeByScoreWithScores(String key, double max,
double min) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<Tuple> zrangeByScoreWithScores(String key, double min,
double max, int offset, int count) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<String> zrevrangeByScore(String key, String max, String min,
int offset, int count) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<Tuple> zrangeByScoreWithScores(String key, String min, String max) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<Tuple> zrevrangeByScoreWithScores(String key, String max,
String min) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<Tuple> zrangeByScoreWithScores(String key, String min,
String max, int offset, int count) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<Tuple> zrevrangeByScoreWithScores(String key, double max,
double min, int offset, int count) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<Tuple> zrevrangeByScoreWithScores(String key, String max,
String min, int offset, int count) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long zremrangeByRank(String key, long start, long end) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long zremrangeByScore(String key, double start, double end) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long zremrangeByScore(String key, String start, String end) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long linsert(String key, LIST_POSITION where, String pivot,
String value) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long lpushx(String key, String... string) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long rpushx(String key, String... string) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<String> blpop(String arg) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<String> brpop(String arg) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long del(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public String echo(String string) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long move(String key, int dbIndex) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long bitcount(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public Long bitcount(String key, long start, long end) {
// TODO Auto-generated method stub
return null;
}
@Override
public String ping() {
// TODO Auto-generated method stub
return null;
}
@Override
public String quit() {
// TODO Auto-generated method stub
return null;
}
@Override
public String flushDB() {
// TODO Auto-generated method stub
return null;
}
@Override
public Long dbSize() {
// TODO Auto-generated method stub
return null;
}
@Override
public String select(int index) {
// TODO Auto-generated method stub
return null;
}
@Override
public String flushAll() {
// TODO Auto-generated method stub
return null;
}
@Override
public String auth(String password) {
// TODO Auto-generated method stub
return null;
}
@Override
public String save() {
// TODO Auto-generated method stub
return null;
}
@Override
public String bgsave() {
// TODO Auto-generated method stub
return null;
}
@Override
public String bgrewriteaof() {
// TODO Auto-generated method stub
return null;
}
@Override
public Long lastsave() {
// TODO Auto-generated method stub
return null;
}
@Override
public String shutdown() {
// TODO Auto-generated method stub
return null;
}
@Override
public String info() {
// TODO Auto-generated method stub
return null;
}
@Override
public String info(String section) {
// TODO Auto-generated method stub
return null;
}
@Override
public String slaveof(String host, int port) {
// TODO Auto-generated method stub
return null;
}
@Override
public String slaveofNoOne() {
// TODO Auto-generated method stub
return null;
}
@Override
public Long getDB() {
// TODO Auto-generated method stub
return null;
}
@Override
public String debug(DebugParams params) {
// TODO Auto-generated method stub
return null;
}
@Override
public String configResetStat() {
// TODO Auto-generated method stub
return null;
}
@SuppressWarnings("unchecked")
private Jedis getRandomConnection() {
Object[] nodeArray = nodes.values().toArray();
return ((Pool<Jedis>) nodeArray[new Random().nextInt(nodeArray.length)]).getResource();
}
}

View File

@@ -18,7 +18,7 @@ public class JedisPool extends Pool<Jedis> {
this(new GenericObjectPoolConfig(), host, port,
Protocol.DEFAULT_TIMEOUT, null, Protocol.DEFAULT_DATABASE, null);
}
public JedisPool(final String host) {
URI uri = URI.create(host);
if (uri.getScheme() != null && uri.getScheme().equals("redis")) {

View File

@@ -6,13 +6,15 @@ import java.util.List;
import redis.clients.jedis.exceptions.JedisConnectionException;
import redis.clients.jedis.exceptions.JedisDataException;
import redis.clients.jedis.exceptions.JedisMovedDataException;
import redis.clients.util.RedisInputStream;
import redis.clients.util.RedisOutputStream;
import redis.clients.util.SafeEncoder;
public final class Protocol {
public static final int DEFAULT_PORT = 6379;
private static final String MOVED_RESPONSE = "MOVED";
public static final int DEFAULT_PORT = 6379;
public static final int DEFAULT_SENTINEL_PORT = 26379;
public static final int DEFAULT_TIMEOUT = 2000;
public static final int DEFAULT_DATABASE = 0;
@@ -72,8 +74,12 @@ public final class Protocol {
}
private static void processError(final RedisInputStream is) {
String message = is.readLine();
throw new JedisDataException(message);
String message = is.readLine();
//TODO: Read only first 5 bytes?
if (message.contains(MOVED_RESPONSE)) {
throw new JedisMovedDataException(message);
}
throw new JedisDataException(message);
}
private static Object process(final RedisInputStream is) {

View File

@@ -0,0 +1,17 @@
package redis.clients.jedis.exceptions;
public class JedisMovedDataException extends JedisDataException {
private static final long serialVersionUID = 3878126572474819403L;
public JedisMovedDataException(String message) {
super(message);
}
public JedisMovedDataException(Throwable cause) {
super(cause);
}
public JedisMovedDataException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,5 +1,7 @@
package redis.clients.jedis.tests;
import java.util.HashSet;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@@ -9,6 +11,7 @@ import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.exceptions.JedisMovedDataException;
public class JedisClusterTest extends Assert {
private Jedis node1;
@@ -42,7 +45,7 @@ public class JedisClusterTest extends Assert {
// add all slots to node1
Pipeline pipelined = node1.pipelined();
for (int i = 0; i < JedisCluster.HASH_SLOTS; i++) {
for (int i = 0; i < JedisCluster.HASHSLOTS; i++) {
pipelined.clusterAddSlots(i);
}
pipelined.sync();
@@ -52,15 +55,17 @@ public class JedisClusterTest extends Assert {
public void tearDown() {
// clear all slots of node1
Pipeline pipelined = node1.pipelined();
for (int i = 0; i < JedisCluster.HASH_SLOTS; i++) {
for (int i = 0; i < JedisCluster.HASHSLOTS; i++) {
pipelined.clusterDelSlots(i);
}
pipelined.sync();
}
@Test
public void moved() {
//TODO: needs to implement
@Test(expected=JedisMovedDataException.class)
public void throwMovedExceptionTest() {
JedisCluster jc = new JedisCluster(new HashSet<HostAndPort>(HostAndPortUtil.getClusterServers()));
jc.set("foo", "bar");
jc.get("foo");
}
@Test