Make it better to use URI from Jedis / JedisPool

* no need to provide password / DB index when user uses URI
* can provide timeout when user users URI
This commit is contained in:
Jungtaek Lim
2014-06-15 21:50:38 +09:00
parent e05eaa2b07
commit 1d29b759fe
6 changed files with 134 additions and 56 deletions

View File

@@ -17,6 +17,7 @@ import redis.clients.jedis.BinaryClient.LIST_POSITION;
import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.exceptions.JedisDataException;
import redis.clients.jedis.exceptions.JedisException; import redis.clients.jedis.exceptions.JedisException;
import redis.clients.util.JedisByteHashMap; import redis.clients.util.JedisByteHashMap;
import redis.clients.util.JedisURIHelper;
import redis.clients.util.SafeEncoder; import redis.clients.util.SafeEncoder;
public class BinaryJedis implements BasicCommands, BinaryJedisCommands, public class BinaryJedis implements BasicCommands, BinaryJedisCommands,
@@ -27,11 +28,7 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands,
public BinaryJedis(final String host) { public BinaryJedis(final String host) {
URI uri = URI.create(host); URI uri = URI.create(host);
if (uri.getScheme() != null && uri.getScheme().equals("redis")) { if (uri.getScheme() != null && uri.getScheme().equals("redis")) {
client = new Client(uri.getHost(), uri.getPort()); initializeClientFromURI(uri);
client.auth(uri.getUserInfo().split(":", 2)[1]);
client.getStatusCodeReply();
client.select(Integer.parseInt(uri.getPath().split("/", 2)[1]));
client.getStatusCodeReply();
} else { } else {
client = new Client(host); client = new Client(host);
} }
@@ -53,12 +50,29 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands,
} }
public BinaryJedis(URI uri) { public BinaryJedis(URI uri) {
initializeClientFromURI(uri);
}
public BinaryJedis(final URI uri, final int timeout) {
initializeClientFromURI(uri);
client.setTimeout(timeout);
}
private void initializeClientFromURI(URI uri) {
client = new Client(uri.getHost(), uri.getPort()); client = new Client(uri.getHost(), uri.getPort());
client.auth(uri.getUserInfo().split(":", 2)[1]);
String password = JedisURIHelper.getPassword(uri);
if (password != null) {
client.auth(password);
client.getStatusCodeReply(); client.getStatusCodeReply();
client.select(Integer.parseInt(uri.getPath().split("/", 2)[1])); }
Integer dbIndex = JedisURIHelper.getDBIndex(uri);
if (dbIndex != null) {
client.select(dbIndex);
client.getStatusCodeReply(); client.getStatusCodeReply();
} }
}
public String ping() { public String ping() {
checkIsInMulti(); checkIsInMulti();

View File

@@ -35,6 +35,10 @@ public class Jedis extends BinaryJedis implements JedisCommands,
super(uri); super(uri);
} }
public Jedis(final URI uri, final int timeout) {
super(uri, timeout);
}
/** /**
* Set the string value as value of the key. The string can't be longer than * Set the string value as value of the key. The string can't be longer than
* 1073741824 bytes (1 GB). * 1073741824 bytes (1 GB).
@@ -547,7 +551,8 @@ public class Jedis extends BinaryJedis implements JedisCommands,
/** /**
* INCRBYFLOAT * INCRBYFLOAT
* <p> * <p>
* INCRBYFLOAT commands are limited to double precision floating point values. * INCRBYFLOAT commands are limited to double precision floating point
* values.
* <p> * <p>
* Note: this is actually a string operation, that is, in Redis there are * Note: this is actually a string operation, that is, in Redis there are
* not "double" types. Simply the string stored at the key is parsed as a * not "double" types. Simply the string stored at the key is parsed as a
@@ -763,24 +768,25 @@ public class Jedis extends BinaryJedis implements JedisCommands,
/** /**
* Increment the number stored at field in the hash at key by a double * Increment the number stored at field in the hash at key by a double
* precision floating point value. If key does not exist, * precision floating point value. If key does not exist, a new key holding
* a new key holding a hash is created. If field does not * a hash is created. If field does not exist or holds a string, the value
* exist or holds a string, the value is set to 0 before applying the * is set to 0 before applying the operation. Since the value argument is
* operation. Since the value argument is signed you can use this command to * signed you can use this command to perform both increments and
* perform both increments and decrements. * decrements.
* <p> * <p>
* The range of values supported by HINCRBYFLOAT is limited to * The range of values supported by HINCRBYFLOAT is limited to double
* double precision floating point values. * precision floating point values.
* <p> * <p>
* <b>Time complexity:</b> O(1) * <b>Time complexity:</b> O(1)
* *
* @param key * @param key
* @param field * @param field
* @param value * @param value
* @return Double precision floating point reply The new value at field after the increment * @return Double precision floating point reply The new value at field
* operation. * after the increment operation.
*/ */
public Double hincrByFloat(final String key, final String field, final double value) { public Double hincrByFloat(final String key, final String field,
final double value) {
checkIsInMulti(); checkIsInMulti();
client.hincrByFloat(key, field, value); client.hincrByFloat(key, field, value);
final String dval = client.getBulkReply(); final String dval = client.getBulkReply();
@@ -2712,7 +2718,8 @@ public class Jedis extends BinaryJedis implements JedisCommands,
return bitpos(key, value, new BitPosParams()); return bitpos(key, value, new BitPosParams());
} }
public Long bitpos(final String key, final boolean value, final BitPosParams params) { public Long bitpos(final String key, final boolean value,
final BitPosParams params) {
client.bitpos(key, value, params); client.bitpos(key, value, params);
return client.getIntegerReply(); return client.getIntegerReply();
} }
@@ -3140,7 +3147,6 @@ public class Jedis extends BinaryJedis implements JedisCommands,
return client.getIntegerReply(); return client.getIntegerReply();
} }
public String psetex(final String key, final int milliseconds, public String psetex(final String key, final int milliseconds,
final String value) { final String value) {
checkIsInMulti(); checkIsInMulti();

View File

@@ -5,6 +5,7 @@ import java.net.URI;
import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.util.JedisURIHelper;
import redis.clients.util.Pool; import redis.clients.util.Pool;
public class JedisPool extends Pool<Jedis> { public class JedisPool extends Pool<Jedis> {
@@ -24,8 +25,12 @@ public class JedisPool extends Pool<Jedis> {
if (uri.getScheme() != null && uri.getScheme().equals("redis")) { if (uri.getScheme() != null && uri.getScheme().equals("redis")) {
String h = uri.getHost(); String h = uri.getHost();
int port = uri.getPort(); int port = uri.getPort();
String password = uri.getUserInfo().split(":", 2)[1]; String password = JedisURIHelper.getPassword(uri);
int database = Integer.parseInt(uri.getPath().split("/", 2)[1]); int database = 0;
Integer dbIndex = JedisURIHelper.getDBIndex(uri);
if (dbIndex != null) {
database = dbIndex.intValue();
}
this.internalPool = new GenericObjectPool<Jedis>( this.internalPool = new GenericObjectPool<Jedis>(
new JedisFactory(h, port, Protocol.DEFAULT_TIMEOUT, new JedisFactory(h, port, Protocol.DEFAULT_TIMEOUT,
password, database, null), password, database, null),
@@ -39,13 +44,11 @@ public class JedisPool extends Pool<Jedis> {
} }
public JedisPool(final URI uri) { public JedisPool(final URI uri) {
String h = uri.getHost(); this(new GenericObjectPoolConfig(), uri, Protocol.DEFAULT_TIMEOUT);
int port = uri.getPort(); }
String password = uri.getUserInfo().split(":", 2)[1];
int database = Integer.parseInt(uri.getPath().split("/", 2)[1]); public JedisPool(final URI uri, final int timeout) {
this.internalPool = new GenericObjectPool<Jedis>(new JedisFactory(h, this(new GenericObjectPoolConfig(), uri, timeout);
port, Protocol.DEFAULT_TIMEOUT, password, database, null),
new GenericObjectPoolConfig());
} }
public JedisPool(final GenericObjectPoolConfig poolConfig, public JedisPool(final GenericObjectPoolConfig poolConfig,
@@ -79,6 +82,18 @@ public class JedisPool extends Pool<Jedis> {
database, clientName)); database, clientName));
} }
public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri) {
this(poolConfig, uri, Protocol.DEFAULT_TIMEOUT);
}
public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri,
final int timeout) {
super(poolConfig, new JedisFactory(uri.getHost(), uri.getPort(),
timeout, JedisURIHelper.getPassword(uri),
JedisURIHelper.getDBIndex(uri) != null ? JedisURIHelper
.getDBIndex(uri) : 0, null));
}
@Override @Override
public Jedis getResource() { public Jedis getResource() {
Jedis jedis = super.getResource(); Jedis jedis = super.getResource();

View File

@@ -0,0 +1,21 @@
package redis.clients.util;
import java.net.URI;
public class JedisURIHelper {
public static String getPassword(URI uri) {
String userInfo = uri.getUserInfo();
if (userInfo != null) {
return userInfo.split(":", 2)[1];
}
return null;
}
public static Integer getDBIndex(URI uri) {
String[] pathSplit = uri.getPath().split("/", 2);
if (pathSplit.length > 1) {
return Integer.parseInt(pathSplit[1]);
}
return null;
}
}

View File

@@ -144,6 +144,12 @@ public class JedisPoolTest extends Assert {
assertEquals("bar", jedis.get("foo")); assertEquals("bar", jedis.get("foo"));
} }
@Test
public void allowUrlWithNoDBAndNoPassword() throws URISyntaxException {
new JedisPool("redis://localhost:6380");
new JedisPool(new URI("redis://localhost:6380"));
}
@Test @Test
public void selectDatabaseOnActivation() { public void selectDatabaseOnActivation() {
JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(),

View File

@@ -57,6 +57,14 @@ public class JedisTest extends JedisCommandTestBase {
jedis.hmget("foobar", "foo"); jedis.hmget("foobar", "foo");
} }
@Test(expected = JedisConnectionException.class)
public void timeoutConnectionWithURI() throws Exception {
jedis = new Jedis(new URI("redis://:foobared@localhost:6380/2"), 15000);
jedis.configSet("timeout", "1");
Thread.sleep(2000);
jedis.hmget("foobar", "foo");
}
@Test(expected = JedisDataException.class) @Test(expected = JedisDataException.class)
public void failWhenSendingNullValues() { public void failWhenSendingNullValues() {
jedis.set("foo", null); jedis.set("foo", null);
@@ -93,6 +101,14 @@ public class JedisTest extends JedisCommandTestBase {
assertEquals("bar", jedis.get("foo")); assertEquals("bar", jedis.get("foo"));
} }
@Test
public void allowUrlWithNoDBAndNoPassword() {
Jedis jedis = new Jedis("redis://localhost:6380");
assertEquals(jedis.getClient().getHost(), "localhost");
assertEquals(jedis.getClient().getPort(), 6380);
assertEquals(jedis.getDB(), (Long) 0L);
}
@Test @Test
public void checkCloseable() { public void checkCloseable() {
jedis.close(); jedis.close();