package redis.clients.jedis.tests; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisShardInfo; import redis.clients.jedis.ShardedJedis; import redis.clients.jedis.ShardedJedisPipeline; import redis.clients.jedis.ShardedJedisPool; import redis.clients.jedis.exceptions.JedisConnectionException; public class ShardedJedisPoolTest extends Assert { private static HostAndPort redis1 = HostAndPortUtil.getRedisServers().get(0); private static HostAndPort redis2 = HostAndPortUtil.getRedisServers().get(1); private List<JedisShardInfo> shards; @Before public void startUp() { shards = new ArrayList<JedisShardInfo>(); shards.add(new JedisShardInfo(redis1.getHost(), redis1.getPort())); shards.add(new JedisShardInfo(redis2.getHost(), redis2.getPort())); shards.get(0).setPassword("foobared"); shards.get(1).setPassword("foobared"); Jedis j = new Jedis(shards.get(0)); j.connect(); j.flushAll(); j.disconnect(); j = new Jedis(shards.get(1)); j.connect(); j.flushAll(); j.disconnect(); } @Test public void checkConnections() { ShardedJedisPool pool = new ShardedJedisPool(new GenericObjectPoolConfig(), shards); ShardedJedis jedis = pool.getResource(); jedis.set("foo", "bar"); assertEquals("bar", jedis.get("foo")); jedis.close(); pool.destroy(); } @Test public void checkCloseableConnections() throws Exception { ShardedJedisPool pool = new ShardedJedisPool(new GenericObjectPoolConfig(), shards); ShardedJedis jedis = pool.getResource(); jedis.set("foo", "bar"); assertEquals("bar", jedis.get("foo")); jedis.close(); pool.close(); assertTrue(pool.isClosed()); } @Test public void checkConnectionWithDefaultPort() { ShardedJedisPool pool = new ShardedJedisPool(new GenericObjectPoolConfig(), shards); ShardedJedis jedis = pool.getResource(); jedis.set("foo", "bar"); assertEquals("bar", jedis.get("foo")); jedis.close(); pool.destroy(); } @Test public void checkJedisIsReusedWhenReturned() { ShardedJedisPool pool = new ShardedJedisPool(new GenericObjectPoolConfig(), shards); ShardedJedis jedis = pool.getResource(); jedis.set("foo", "0"); jedis.close(); jedis = pool.getResource(); jedis.incr("foo"); jedis.close(); pool.destroy(); } @Test public void checkPoolRepairedWhenJedisIsBroken() { ShardedJedisPool pool = new ShardedJedisPool(new GenericObjectPoolConfig(), shards); ShardedJedis jedis = pool.getResource(); jedis.disconnect(); jedis.close(); jedis = pool.getResource(); jedis.incr("foo"); jedis.close(); pool.destroy(); } @Test(expected = JedisConnectionException.class) public void checkPoolOverflow() { GenericObjectPoolConfig config = new GenericObjectPoolConfig(); config.setMaxTotal(1); config.setBlockWhenExhausted(false); ShardedJedisPool pool = new ShardedJedisPool(config, shards); ShardedJedis jedis = pool.getResource(); jedis.set("foo", "0"); ShardedJedis newJedis = pool.getResource(); newJedis.incr("foo"); } @Test public void shouldNotShareInstances() { GenericObjectPoolConfig config = new GenericObjectPoolConfig(); config.setMaxTotal(2); ShardedJedisPool pool = new ShardedJedisPool(config, shards); ShardedJedis j1 = pool.getResource(); ShardedJedis j2 = pool.getResource(); assertNotSame(j1.getShard("foo"), j2.getShard("foo")); } @Test public void checkFailedJedisServer() { ShardedJedisPool pool = new ShardedJedisPool(new GenericObjectPoolConfig(), shards); ShardedJedis jedis = pool.getResource(); jedis.incr("foo"); jedis.close(); pool.destroy(); } @Test public void shouldReturnActiveShardsWhenOneGoesOffline() { GenericObjectPoolConfig redisConfig = new GenericObjectPoolConfig(); redisConfig.setTestOnBorrow(false); ShardedJedisPool pool = new ShardedJedisPool(redisConfig, shards); ShardedJedis jedis = pool.getResource(); // fill the shards for (int i = 0; i < 1000; i++) { jedis.set("a-test-" + i, "0"); } jedis.close(); // check quantity for each shard Jedis j = new Jedis(shards.get(0)); j.connect(); Long c1 = j.dbSize(); j.disconnect(); j = new Jedis(shards.get(1)); j.connect(); Long c2 = j.dbSize(); j.disconnect(); // shutdown shard 2 and check thay the pool returns an instance with c1 // items on one shard // alter shard 1 and recreate pool pool.destroy(); shards.set(1, new JedisShardInfo("localhost", 1234)); pool = new ShardedJedisPool(redisConfig, shards); jedis = pool.getResource(); Long actual = Long.valueOf(0); Long fails = Long.valueOf(0); for (int i = 0; i < 1000; i++) { try { jedis.get("a-test-" + i); actual++; } catch (RuntimeException e) { fails++; } } jedis.close(); pool.destroy(); assertEquals(actual, c1); assertEquals(fails, c2); } @Test public void startWithUrlString() { Jedis j = new Jedis("localhost", 6380); j.auth("foobared"); j.set("foo", "bar"); j = new Jedis("localhost", 6379); j.auth("foobared"); j.set("foo", "bar"); List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(); shards.add(new JedisShardInfo("redis://:foobared@localhost:6380")); shards.add(new JedisShardInfo("redis://:foobared@localhost:6379")); GenericObjectPoolConfig redisConfig = new GenericObjectPoolConfig(); ShardedJedisPool pool = new ShardedJedisPool(redisConfig, shards); Jedis[] jedises = pool.getResource().getAllShards().toArray(new Jedis[2]); Jedis jedis = jedises[0]; assertEquals("PONG", jedis.ping()); assertEquals("bar", jedis.get("foo")); jedis = jedises[1]; assertEquals("PONG", jedis.ping()); assertEquals("bar", jedis.get("foo")); } @Test public void startWithUrl() throws URISyntaxException { Jedis j = new Jedis("localhost", 6380); j.auth("foobared"); j.set("foo", "bar"); j = new Jedis("localhost", 6379); j.auth("foobared"); j.set("foo", "bar"); List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(); shards.add(new JedisShardInfo(new URI("redis://:foobared@localhost:6380"))); shards.add(new JedisShardInfo(new URI("redis://:foobared@localhost:6379"))); GenericObjectPoolConfig redisConfig = new GenericObjectPoolConfig(); ShardedJedisPool pool = new ShardedJedisPool(redisConfig, shards); Jedis[] jedises = pool.getResource().getAllShards().toArray(new Jedis[2]); Jedis jedis = jedises[0]; assertEquals("PONG", jedis.ping()); assertEquals("bar", jedis.get("foo")); jedis = jedises[1]; assertEquals("PONG", jedis.ping()); assertEquals("bar", jedis.get("foo")); } @Test public void returnResourceShouldResetState() throws URISyntaxException { GenericObjectPoolConfig config = new GenericObjectPoolConfig(); config.setMaxTotal(1); config.setBlockWhenExhausted(false); List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(); shards.add(new JedisShardInfo(new URI("redis://:foobared@localhost:6380"))); shards.add(new JedisShardInfo(new URI("redis://:foobared@localhost:6379"))); ShardedJedisPool pool = new ShardedJedisPool(config, shards); ShardedJedis jedis = pool.getResource(); jedis.set("pipelined", String.valueOf(0)); jedis.set("pipelined2", String.valueOf(0)); ShardedJedisPipeline pipeline = jedis.pipelined(); pipeline.incr("pipelined"); pipeline.incr("pipelined2"); jedis.resetState(); pipeline = jedis.pipelined(); pipeline.incr("pipelined"); pipeline.incr("pipelined2"); List<Object> results = pipeline.syncAndReturnAll(); assertEquals(2, results.size()); jedis.close(); pool.destroy(); } @Test public void checkResourceIsCloseable() throws URISyntaxException { GenericObjectPoolConfig config = new GenericObjectPoolConfig(); config.setMaxTotal(1); config.setBlockWhenExhausted(false); List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(); shards.add(new JedisShardInfo(new URI("redis://:foobared@localhost:6380"))); shards.add(new JedisShardInfo(new URI("redis://:foobared@localhost:6379"))); ShardedJedisPool pool = new ShardedJedisPool(config, shards); ShardedJedis jedis = pool.getResource(); try { jedis.set("hello", "jedis"); } finally { jedis.close(); } ShardedJedis jedis2 = pool.getResource(); try { assertEquals(jedis, jedis2); } finally { jedis2.close(); } } }