From 0bc27ac3a298b34d72aabe1afa985fd816a71fa0 Mon Sep 17 00:00:00 2001 From: Marcos Nils Date: Fri, 20 Dec 2013 15:28:32 -0300 Subject: [PATCH] Refactor redis cluster connection handler and add JedisAskDataException handling --- .../redis/clients/jedis/JedisCluster.java | 28 ++++++++-------- .../jedis/JedisClusterConnectionHandler.java | 29 ++-------------- .../jedis/JedisRandomConnectionHandler.java | 33 +++++++++++++++++++ .../java/redis/clients/jedis/Protocol.java | 7 +++- .../clients/jedis/tests/JedisClusterTest.java | 15 ++++----- .../clients/jedis/tests/utils/RedisSlot.java | 4 +++ 6 files changed, 66 insertions(+), 50 deletions(-) create mode 100644 src/main/java/redis/clients/jedis/JedisRandomConnectionHandler.java diff --git a/src/main/java/redis/clients/jedis/JedisCluster.java b/src/main/java/redis/clients/jedis/JedisCluster.java index a3b6f22..3c82d8c 100644 --- a/src/main/java/redis/clients/jedis/JedisCluster.java +++ b/src/main/java/redis/clients/jedis/JedisCluster.java @@ -15,7 +15,7 @@ public class JedisCluster implements JedisCommands, BasicCommands { private JedisClusterConnectionHandler connectionHandler; public JedisCluster(Set nodes, int timeout) { - connectionHandler = new JedisClusterConnectionHandler(nodes); + connectionHandler = new JedisRandomConnectionHandler(nodes); } @@ -31,7 +31,7 @@ public class JedisCluster implements JedisCommands, BasicCommands { return new JedisClusterCommand(connectionHandler) { @Override public String execute() { - return connectionHandler.getRandomConnection().set(key, value); + return connectionHandler.getConnection().set(key, value); } }.run(); } @@ -41,7 +41,7 @@ public class JedisCluster implements JedisCommands, BasicCommands { return new JedisClusterCommand(connectionHandler) { @Override public String execute() { - return connectionHandler.getRandomConnection().get(key); + return connectionHandler.getConnection().get(key); } }.run(); } @@ -51,7 +51,7 @@ public class JedisCluster implements JedisCommands, BasicCommands { return new JedisClusterCommand(connectionHandler) { @Override public Boolean execute() { - return connectionHandler.getRandomConnection().exists(key); + return connectionHandler.getConnection().exists(key); } }.run(); } @@ -61,7 +61,7 @@ public class JedisCluster implements JedisCommands, BasicCommands { return new JedisClusterCommand(connectionHandler) { @Override public Long execute() { - return connectionHandler.getRandomConnection().persist(key); + return connectionHandler.getConnection().persist(key); } }.run(); } @@ -71,7 +71,7 @@ public class JedisCluster implements JedisCommands, BasicCommands { return new JedisClusterCommand(connectionHandler) { @Override public String execute() { - return connectionHandler.getRandomConnection().type(key); + return connectionHandler.getConnection().type(key); } }.run(); } @@ -81,7 +81,7 @@ public class JedisCluster implements JedisCommands, BasicCommands { return new JedisClusterCommand(connectionHandler) { @Override public Long execute() { - return connectionHandler.getRandomConnection().expire(key, seconds); + return connectionHandler.getConnection().expire(key, seconds); } }.run(); } @@ -91,7 +91,7 @@ public class JedisCluster implements JedisCommands, BasicCommands { return new JedisClusterCommand(connectionHandler) { @Override public Long execute() { - return connectionHandler.getRandomConnection().expireAt(key, unixTime); + return connectionHandler.getConnection().expireAt(key, unixTime); } }.run(); } @@ -101,7 +101,7 @@ public class JedisCluster implements JedisCommands, BasicCommands { return new JedisClusterCommand(connectionHandler) { @Override public Long execute() { - return connectionHandler.getRandomConnection().ttl(key); + return connectionHandler.getConnection().ttl(key); } }.run(); } @@ -111,7 +111,7 @@ public class JedisCluster implements JedisCommands, BasicCommands { return new JedisClusterCommand(connectionHandler) { @Override public Boolean execute() { - return connectionHandler.getRandomConnection().setbit(key, offset, value); + return connectionHandler.getConnection().setbit(key, offset, value); } }.run(); } @@ -121,7 +121,7 @@ public class JedisCluster implements JedisCommands, BasicCommands { return new JedisClusterCommand(connectionHandler) { @Override public Boolean execute() { - return connectionHandler.getRandomConnection().setbit(key, offset, value); + return connectionHandler.getConnection().setbit(key, offset, value); } }.run(); } @@ -131,7 +131,7 @@ public class JedisCluster implements JedisCommands, BasicCommands { return new JedisClusterCommand(connectionHandler) { @Override public Boolean execute() { - return connectionHandler.getRandomConnection().getbit(key, offset); + return connectionHandler.getConnection().getbit(key, offset); } }.run(); } @@ -141,7 +141,7 @@ public class JedisCluster implements JedisCommands, BasicCommands { return new JedisClusterCommand(connectionHandler) { @Override public Long execute() { - return connectionHandler.getRandomConnection().setrange(key, offset, value); + return connectionHandler.getConnection().setrange(key, offset, value); } }.run(); } @@ -151,7 +151,7 @@ public class JedisCluster implements JedisCommands, BasicCommands { return new JedisClusterCommand(connectionHandler) { @Override public String execute() { - return connectionHandler.getRandomConnection().getrange(key, startOffset, endOffset); + return connectionHandler.getConnection().getrange(key, startOffset, endOffset); } }.run(); } diff --git a/src/main/java/redis/clients/jedis/JedisClusterConnectionHandler.java b/src/main/java/redis/clients/jedis/JedisClusterConnectionHandler.java index d942723..d5aaf51 100644 --- a/src/main/java/redis/clients/jedis/JedisClusterConnectionHandler.java +++ b/src/main/java/redis/clients/jedis/JedisClusterConnectionHandler.java @@ -1,33 +1,8 @@ package redis.clients.jedis; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import redis.clients.util.Pool; - -public class JedisClusterConnectionHandler { - - private Map nodes = new HashMap(); +public interface JedisClusterConnectionHandler { - public JedisClusterConnectionHandler(Set nodes) { - initializeSlotsCache(nodes); - } - - private void initializeSlotsCache(Set nodes) { - for (HostAndPort hostAndPort : nodes) { - JedisPool jp = new JedisPool(hostAndPort.getHost(), - hostAndPort.getPort()); - this.nodes.put(hostAndPort.getHost() + hostAndPort.getPort(), jp); - } - - } - - @SuppressWarnings("unchecked") - public Jedis getRandomConnection() { - Object[] nodeArray = nodes.values().toArray(); - return ((Pool) nodeArray[new Random().nextInt(nodeArray.length)]).getResource(); - } + Jedis getConnection(); } diff --git a/src/main/java/redis/clients/jedis/JedisRandomConnectionHandler.java b/src/main/java/redis/clients/jedis/JedisRandomConnectionHandler.java new file mode 100644 index 0000000..f3da675 --- /dev/null +++ b/src/main/java/redis/clients/jedis/JedisRandomConnectionHandler.java @@ -0,0 +1,33 @@ +package redis.clients.jedis; + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import java.util.Set; + +import redis.clients.util.Pool; + +public class JedisRandomConnectionHandler implements JedisClusterConnectionHandler { + + private Map nodes = new HashMap(); + + public JedisRandomConnectionHandler(Set nodes) { + initializeSlotsCache(nodes); + } + + private void initializeSlotsCache(Set nodes) { + for (HostAndPort hostAndPort : nodes) { + JedisPool jp = new JedisPool(hostAndPort.getHost(), + hostAndPort.getPort()); + this.nodes.put(hostAndPort.getHost() + hostAndPort.getPort(), jp); + } + + } + + @SuppressWarnings("unchecked") + public Jedis getConnection() { + Object[] nodeArray = nodes.values().toArray(); + return ((Pool) nodeArray[new Random().nextInt(nodeArray.length)]).getResource(); + } + +} diff --git a/src/main/java/redis/clients/jedis/Protocol.java b/src/main/java/redis/clients/jedis/Protocol.java index 123edc4..7eecd25 100644 --- a/src/main/java/redis/clients/jedis/Protocol.java +++ b/src/main/java/redis/clients/jedis/Protocol.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import redis.clients.jedis.exceptions.JedisAskDataException; import redis.clients.jedis.exceptions.JedisConnectionException; import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.exceptions.JedisMovedDataException; @@ -13,6 +14,7 @@ import redis.clients.util.SafeEncoder; public final class Protocol { + private static final String ASK_RESPONSE = "ASK"; private static final String MOVED_RESPONSE = "MOVED"; public static final int DEFAULT_PORT = 6379; public static final int DEFAULT_SENTINEL_PORT = 26379; @@ -75,9 +77,12 @@ public final class Protocol { private static void processError(final RedisInputStream is) { String message = is.readLine(); - //TODO: Read only first 5 bytes? + //TODO: I'm not sure if this is the best way to do this. + //Maybe Read only first 5 bytes instead? if (message.contains(MOVED_RESPONSE)) { throw new JedisMovedDataException(message); + } else if (message.contains(ASK_RESPONSE)) { + throw new JedisAskDataException(message); } throw new JedisDataException(message); } diff --git a/src/test/java/redis/clients/jedis/tests/JedisClusterTest.java b/src/test/java/redis/clients/jedis/tests/JedisClusterTest.java index 204b4f8..0f7c06c 100644 --- a/src/test/java/redis/clients/jedis/tests/JedisClusterTest.java +++ b/src/test/java/redis/clients/jedis/tests/JedisClusterTest.java @@ -77,14 +77,13 @@ public class JedisClusterTest extends Assert { node2.get("foo"); } -// @Test(expected=JedisAskDataException.class) -// public void ask() { -// node1.set("foo", "bar"); -// int keySlot = RedisSlot.getSlot("foo"); -// String node2Id = getNodeId(node2.clusterNodes()); -// node1.clusterSetSlotMigrating(keySlot, node2Id); -// node1.get("foo"); -// } + @Test(expected=JedisAskDataException.class) + public void ask() { + int keySlot = RedisSlot.getSlot("test"); + String node2Id = getNodeId(node2.clusterNodes()); + node1.clusterSetSlotMigrating(keySlot, node2Id); + node1.get("test"); + } private String getNodeId(String infoOutput) { for (String infoLine : infoOutput.split("\n")) { diff --git a/src/test/java/redis/clients/jedis/tests/utils/RedisSlot.java b/src/test/java/redis/clients/jedis/tests/utils/RedisSlot.java index 1dd76c3..61a98dd 100644 --- a/src/test/java/redis/clients/jedis/tests/utils/RedisSlot.java +++ b/src/test/java/redis/clients/jedis/tests/utils/RedisSlot.java @@ -22,4 +22,8 @@ public class RedisSlot { return crc &= 0xffff % 16384; } + public static void main(String[] args) { + System.out.println(getSlot("test")); + } + } \ No newline at end of file