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"));
pool.returnResource(jedis);
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"));
pool.returnResource(jedis);
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"));
pool.returnResource(jedis);
pool.destroy();
}
@Test
public void checkJedisIsReusedWhenReturned() {
ShardedJedisPool pool = new ShardedJedisPool(
new GenericObjectPoolConfig(), shards);
ShardedJedis jedis = pool.getResource();
jedis.set("foo", "0");
pool.returnResource(jedis);
jedis = pool.getResource();
jedis.incr("foo");
pool.returnResource(jedis);
pool.destroy();
}
@Test
public void checkPoolRepairedWhenJedisIsBroken() {
ShardedJedisPool pool = new ShardedJedisPool(
new GenericObjectPoolConfig(), shards);
ShardedJedis jedis = pool.getResource();
jedis.disconnect();
pool.returnBrokenResource(jedis);
jedis = pool.getResource();
jedis.incr("foo");
pool.returnResource(jedis);
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");
pool.returnResource(jedis);
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");
}
pool.returnResource(jedis);
// 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++;
}
}
pool.returnResource(jedis);
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());
pool.returnResource(jedis);
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();
}
}
}