From 3073f778b4edab3205b922c22f29cfed490c494e Mon Sep 17 00:00:00 2001 From: Jungtaek Lim Date: Sat, 21 Dec 2013 01:33:46 +0900 Subject: [PATCH] JedisPool / JedisSentinelPool resets returning object's state (watched, multi) * BinaryClient / BinaryJedis : added feature to reset its state (watched, multi) * JedisPool / JedisSentinelPool : calls new feature (reset state) when Jedis object returns to pool * Unit Test included --- .../redis/clients/jedis/BinaryClient.java | 20 +++++++- .../java/redis/clients/jedis/BinaryJedis.java | 5 ++ .../java/redis/clients/jedis/JedisPool.java | 1 + .../clients/jedis/JedisSentinelPool.java | 1 + .../clients/jedis/tests/JedisPoolTest.java | 22 +++++++++ .../jedis/tests/JedisSentinelPoolTest.java | 22 +++++++++ .../commands/TransactionCommandsTest.java | 46 +++++++++++++++++++ 7 files changed, 116 insertions(+), 1 deletion(-) diff --git a/src/main/java/redis/clients/jedis/BinaryClient.java b/src/main/java/redis/clients/jedis/BinaryClient.java index dff1e76..abf0dc3 100644 --- a/src/main/java/redis/clients/jedis/BinaryClient.java +++ b/src/main/java/redis/clients/jedis/BinaryClient.java @@ -29,15 +29,21 @@ public class BinaryClient extends Connection { } private boolean isInMulti; - + private String password; private long db; + private boolean isInWatch; + public boolean isInMulti() { return isInMulti; } + public boolean isInWatch() { + return isInWatch; + } + public BinaryClient(final String host) { super(host); } @@ -447,19 +453,23 @@ public class BinaryClient extends Connection { public void discard() { sendCommand(DISCARD); isInMulti = false; + isInWatch = false; } public void exec() { sendCommand(EXEC); isInMulti = false; + isInWatch = false; } public void watch(final byte[]... keys) { sendCommand(WATCH, keys); + isInWatch = true; } public void unwatch() { sendCommand(UNWATCH); + isInWatch = false; } public void sort(final byte[] key) { @@ -912,6 +922,14 @@ public class BinaryClient extends Connection { db = 0; super.disconnect(); } + + public void resetState() { + if (isInMulti()) + discard(); + + if (isInWatch()) + unwatch(); + } private void sendEvalCommand(Command command, byte[] script, byte[] keyCount, byte[][] params) { diff --git a/src/main/java/redis/clients/jedis/BinaryJedis.java b/src/main/java/redis/clients/jedis/BinaryJedis.java index 92a99a2..6a318ce 100644 --- a/src/main/java/redis/clients/jedis/BinaryJedis.java +++ b/src/main/java/redis/clients/jedis/BinaryJedis.java @@ -1709,6 +1709,11 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey public void disconnect() { client.disconnect(); } + + public void resetState() { + client.resetState(); + client.getAll(); + } public String watch(final byte[]... keys) { client.watch(keys); diff --git a/src/main/java/redis/clients/jedis/JedisPool.java b/src/main/java/redis/clients/jedis/JedisPool.java index 58212ba..946863b 100644 --- a/src/main/java/redis/clients/jedis/JedisPool.java +++ b/src/main/java/redis/clients/jedis/JedisPool.java @@ -84,6 +84,7 @@ public class JedisPool extends Pool { } public void returnResource(final Jedis resource) { + resource.resetState(); returnResourceObject(resource); } } diff --git a/src/main/java/redis/clients/jedis/JedisSentinelPool.java b/src/main/java/redis/clients/jedis/JedisSentinelPool.java index e4c6e3b..9190225 100644 --- a/src/main/java/redis/clients/jedis/JedisSentinelPool.java +++ b/src/main/java/redis/clients/jedis/JedisSentinelPool.java @@ -79,6 +79,7 @@ public class JedisSentinelPool extends Pool { } public void returnResource(final Jedis resource) { + resource.resetState(); returnResourceObject(resource); } diff --git a/src/test/java/redis/clients/jedis/tests/JedisPoolTest.java b/src/test/java/redis/clients/jedis/tests/JedisPoolTest.java index 652de92..c62e3bd 100644 --- a/src/test/java/redis/clients/jedis/tests/JedisPoolTest.java +++ b/src/test/java/redis/clients/jedis/tests/JedisPoolTest.java @@ -11,6 +11,7 @@ import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; +import redis.clients.jedis.Transaction; import redis.clients.jedis.exceptions.JedisConnectionException; public class JedisPoolTest extends Assert { @@ -176,4 +177,25 @@ public class JedisPoolTest extends Assert { pool0.returnResource(jedis); pool0.destroy(); } + + @Test + public void returnResourceShouldResetState() { + GenericObjectPoolConfig config = new GenericObjectPoolConfig(); + config.setMaxTotal(1); + config.setBlockWhenExhausted(false); + JedisPool pool = new JedisPool(config, hnp.getHost(), hnp.getPort(), + 2000, "foobared"); + + Jedis jedis = pool.getResource(); + jedis.set("hello", "jedis"); + Transaction t = jedis.multi(); + t.set("hello", "world"); + pool.returnResource(jedis); + + Jedis jedis2 = pool.getResource(); + assertTrue(jedis == jedis2); + assertEquals("jedis", jedis2.get("hello")); + pool.returnResource(jedis2); + pool.destroy(); + } } diff --git a/src/test/java/redis/clients/jedis/tests/JedisSentinelPoolTest.java b/src/test/java/redis/clients/jedis/tests/JedisSentinelPoolTest.java index c3a72a0..c0752e2 100644 --- a/src/test/java/redis/clients/jedis/tests/JedisSentinelPoolTest.java +++ b/src/test/java/redis/clients/jedis/tests/JedisSentinelPoolTest.java @@ -11,8 +11,10 @@ import org.junit.Test; import redis.clients.jedis.DebugParams; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPubSub; import redis.clients.jedis.JedisSentinelPool; +import redis.clients.jedis.Transaction; public class JedisSentinelPoolTest extends JedisTestBase { private static final String MASTER_NAME = "mymaster"; @@ -149,4 +151,24 @@ public class JedisSentinelPoolTest extends JedisTestBase { } } + @Test + public void returnResourceShouldResetState() { + GenericObjectPoolConfig config = new GenericObjectPoolConfig(); + config.setMaxTotal(1); + config.setBlockWhenExhausted(false); + JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels, + config, 1000, "foobared", 2); + + Jedis jedis = pool.getResource(); + jedis.set("hello", "jedis"); + Transaction t = jedis.multi(); + t.set("hello", "world"); + pool.returnResource(jedis); + + Jedis jedis2 = pool.getResource(); + assertTrue(jedis == jedis2); + assertEquals("jedis", jedis2.get("hello")); + pool.returnResource(jedis2); + pool.destroy(); + } } diff --git a/src/test/java/redis/clients/jedis/tests/commands/TransactionCommandsTest.java b/src/test/java/redis/clients/jedis/tests/commands/TransactionCommandsTest.java index 565c1a4..fb52063 100644 --- a/src/test/java/redis/clients/jedis/tests/commands/TransactionCommandsTest.java +++ b/src/test/java/redis/clients/jedis/tests/commands/TransactionCommandsTest.java @@ -12,10 +12,12 @@ import org.junit.Test; import redis.clients.jedis.Jedis; import redis.clients.jedis.Protocol.Keyword; +import redis.clients.jedis.Pipeline; import redis.clients.jedis.Response; import redis.clients.jedis.Transaction; import redis.clients.jedis.TransactionBlock; import redis.clients.jedis.exceptions.JedisDataException; +import redis.clients.jedis.exceptions.JedisException; public class TransactionCommandsTest extends JedisCommandTestBase { final byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 }; @@ -294,4 +296,48 @@ public class TransactionCommandsTest extends JedisCommandTestBase { assertNull(results); } + + @Test + public void testResetStateWhenInMulti() { + jedis.auth("foobared"); + + Transaction t = jedis.multi(); + t.set("foooo", "barrr"); + + jedis.resetState(); + assertEquals(null, jedis.get("foooo")); + } + + @Test + public void testResetStateWhenInMultiWithinPipeline() { + jedis.auth("foobared"); + + Pipeline p = jedis.pipelined(); + p.multi(); + p.set("foooo", "barrr"); + + jedis.resetState(); + assertEquals(null, jedis.get("foooo")); + } + + @Test + public void testResetStateWhenInWatch() { + jedis.watch("mykey", "somekey"); + + // state reset : unwatch + jedis.resetState(); + + Transaction t = jedis.multi(); + + nj.connect(); + nj.auth("foobared"); + nj.set("mykey", "bar"); + nj.disconnect(); + + t.set("mykey", "foo"); + List resp = t.exec(); + assertNotNull(resp); + assertEquals(1, resp.size()); + assertEquals("foo", jedis.get("mykey")); + } } \ No newline at end of file