DATAREDIS-261 - Upgrade to commons-pool2.
'JRedisPool' and 'DefaultLettucePool' have been migrated to 'commons-pool2'. 'PoolConfig' has been deprecated, and will be removed in '1.4', as all required operations are available via 'GenericObjectPoolConfig'. Along the way a minor bug within 'LettuceConnection' has been resolved, which prevented 'RedisAsyncConnections' from being properly closed/returned to pool. Original Pull Request: #50
This commit is contained in:
committed by
Thomas Darimont
parent
d116d3825a
commit
408b52a449
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,64 +15,22 @@
|
||||
*/
|
||||
package org.springframework.data.redis.connection;
|
||||
|
||||
import org.apache.commons.pool.impl.GenericObjectPool.Config;
|
||||
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||
|
||||
/**
|
||||
* Subclass of {@link Config} that includes setters for instantiation in Spring
|
||||
* Subclass of {@link GenericObjectPoolConfig} that includes setters for instantiation in Spring
|
||||
*
|
||||
* @author Jennifer Hickey
|
||||
* @author Christoph Strobl
|
||||
* @deprecated use {@link GenericObjectPoolConfig} instead. Will be removed in {@literal 1.4}.
|
||||
*/
|
||||
public class PoolConfig extends Config {
|
||||
public class PoolConfig extends GenericObjectPoolConfig {
|
||||
|
||||
public PoolConfig() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void setMaxIdle(int maxIdle) {
|
||||
this.maxIdle = maxIdle;
|
||||
}
|
||||
|
||||
public void setMinIdle(int minIdle) {
|
||||
this.minIdle = minIdle;
|
||||
}
|
||||
|
||||
public void setMaxActive(int maxActive) {
|
||||
this.maxActive = maxActive;
|
||||
}
|
||||
|
||||
public void setMaxWait(long maxWait) {
|
||||
this.maxWait = maxWait;
|
||||
}
|
||||
|
||||
public void setWhenExhaustedAction(byte whenExhaustedAction) {
|
||||
this.whenExhaustedAction = whenExhaustedAction;
|
||||
}
|
||||
|
||||
public void setTestOnBorrow(boolean testOnBorrow) {
|
||||
this.testOnBorrow = testOnBorrow;
|
||||
}
|
||||
|
||||
public void setTestOnReturn(boolean testOnReturn) {
|
||||
this.testOnReturn = testOnReturn;
|
||||
}
|
||||
|
||||
public void setTestWhileIdle(boolean testWhileIdle) {
|
||||
this.testWhileIdle = testWhileIdle;
|
||||
}
|
||||
|
||||
public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
|
||||
this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
|
||||
}
|
||||
|
||||
public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
|
||||
this.numTestsPerEvictionRun = numTestsPerEvictionRun;
|
||||
}
|
||||
|
||||
public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
|
||||
this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
|
||||
}
|
||||
|
||||
public void setSoftMinEvictableIdleTimeMillis(long softMinEvictableIdleTimeMillis) {
|
||||
this.softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis;
|
||||
setMaxTotal(maxActive);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,9 +15,11 @@
|
||||
*/
|
||||
package org.springframework.data.redis.connection.jredis;
|
||||
|
||||
import org.apache.commons.pool.BasePoolableObjectFactory;
|
||||
import org.apache.commons.pool.impl.GenericObjectPool;
|
||||
import org.apache.commons.pool.impl.GenericObjectPool.Config;
|
||||
import org.apache.commons.pool2.BasePooledObjectFactory;
|
||||
import org.apache.commons.pool2.PooledObject;
|
||||
import org.apache.commons.pool2.impl.DefaultPooledObject;
|
||||
import org.apache.commons.pool2.impl.GenericObjectPool;
|
||||
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||
import org.jredis.JRedis;
|
||||
import org.jredis.connector.Connection;
|
||||
import org.jredis.connector.Connection.Socket.Property;
|
||||
@@ -32,10 +34,11 @@ import org.springframework.util.StringUtils;
|
||||
* JRedis implementation of {@link Pool}
|
||||
*
|
||||
* @author Jennifer Hickey
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class JredisPool implements Pool<JRedis> {
|
||||
|
||||
private final GenericObjectPool internalPool;
|
||||
private final GenericObjectPool<JRedis> internalPool;
|
||||
|
||||
/**
|
||||
* Uses the {@link Config} and {@link ConnectionSpec} defaults for configuring the connection pool
|
||||
@@ -44,7 +47,7 @@ public class JredisPool implements Pool<JRedis> {
|
||||
* @param port The Redis port
|
||||
*/
|
||||
public JredisPool(String hostName, int port) {
|
||||
this(hostName, port, 0, null, 0, new Config());
|
||||
this(hostName, port, 0, null, 0, new GenericObjectPoolConfig());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,7 +57,7 @@ public class JredisPool implements Pool<JRedis> {
|
||||
* @param port The Redis port
|
||||
* @param poolConfig The pool {@link Config}
|
||||
*/
|
||||
public JredisPool(String hostName, int port, Config poolConfig) {
|
||||
public JredisPool(String hostName, int port, GenericObjectPoolConfig poolConfig) {
|
||||
this(hostName, port, 0, null, 0, poolConfig);
|
||||
}
|
||||
|
||||
@@ -64,15 +67,15 @@ public class JredisPool implements Pool<JRedis> {
|
||||
* @param connectionSpec The {@link ConnectionSpec} for connecting to Redis
|
||||
*/
|
||||
public JredisPool(ConnectionSpec connectionSpec) {
|
||||
this.internalPool = new GenericObjectPool(new JredisFactory(connectionSpec), new Config());
|
||||
this.internalPool = new GenericObjectPool<JRedis>(new JredisFactory(connectionSpec), new GenericObjectPoolConfig());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param connectionSpec The {@link ConnectionSpec} for connecting to Redis
|
||||
* @param poolConfig The pool {@link Config}
|
||||
*/
|
||||
public JredisPool(ConnectionSpec connectionSpec, Config poolConfig) {
|
||||
this.internalPool = new GenericObjectPool(new JredisFactory(connectionSpec), poolConfig);
|
||||
public JredisPool(ConnectionSpec connectionSpec, GenericObjectPoolConfig poolConfig) {
|
||||
this.internalPool = new GenericObjectPool<JRedis>(new JredisFactory(connectionSpec), poolConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,7 +90,7 @@ public class JredisPool implements Pool<JRedis> {
|
||||
* @param timeout The socket timeout or 0 to use the default socket timeout
|
||||
*/
|
||||
public JredisPool(String hostName, int port, int dbIndex, String password, int timeout) {
|
||||
this(hostName, port, dbIndex, password, timeout, new Config());
|
||||
this(hostName, port, dbIndex, password, timeout, new GenericObjectPoolConfig());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,7 +101,8 @@ public class JredisPool implements Pool<JRedis> {
|
||||
* @param timeout The socket timeout or 0 to use the default socket timeout
|
||||
* @param poolConfig The pool {@link Config}
|
||||
*/
|
||||
public JredisPool(String hostName, int port, int dbIndex, String password, int timeout, Config poolConfig) {
|
||||
public JredisPool(String hostName, int port, int dbIndex, String password, int timeout,
|
||||
GenericObjectPoolConfig poolConfig) {
|
||||
ConnectionSpec connectionSpec = DefaultConnectionSpec.newSpec(hostName, port, dbIndex, null);
|
||||
connectionSpec.setConnectionFlag(Connection.Flag.RELIABLE, false);
|
||||
if (StringUtils.hasLength(password)) {
|
||||
@@ -107,12 +111,12 @@ public class JredisPool implements Pool<JRedis> {
|
||||
if (timeout > 0) {
|
||||
connectionSpec.setSocketProperty(Property.SO_TIMEOUT, timeout);
|
||||
}
|
||||
this.internalPool = new GenericObjectPool(new JredisFactory(connectionSpec), poolConfig);
|
||||
this.internalPool = new GenericObjectPool<JRedis>(new JredisFactory(connectionSpec), poolConfig);
|
||||
}
|
||||
|
||||
public JRedis getResource() {
|
||||
try {
|
||||
return (JRedis) internalPool.borrowObject();
|
||||
return internalPool.borrowObject();
|
||||
} catch (Exception e) {
|
||||
throw new PoolException("Could not get a resource from the pool", e);
|
||||
}
|
||||
@@ -142,7 +146,7 @@ public class JredisPool implements Pool<JRedis> {
|
||||
}
|
||||
}
|
||||
|
||||
private static class JredisFactory extends BasePoolableObjectFactory {
|
||||
private static class JredisFactory extends BasePooledObjectFactory<JRedis> {
|
||||
|
||||
private final ConnectionSpec connectionSpec;
|
||||
|
||||
@@ -151,31 +155,33 @@ public class JredisPool implements Pool<JRedis> {
|
||||
this.connectionSpec = connectionSpec;
|
||||
}
|
||||
|
||||
public Object makeObject() throws Exception {
|
||||
@Override
|
||||
public void destroyObject(final PooledObject<JRedis> obj) throws Exception {
|
||||
try {
|
||||
obj.getObject().quit();
|
||||
} catch (Exception e) {
|
||||
// Errors may happen if returning a broken resource
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateObject(final PooledObject<JRedis> obj) {
|
||||
try {
|
||||
obj.getObject().ping();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JRedis create() throws Exception {
|
||||
return new JRedisClient(connectionSpec);
|
||||
}
|
||||
|
||||
public void destroyObject(final Object obj) throws Exception {
|
||||
if (obj instanceof JRedis) {
|
||||
try {
|
||||
((JRedis) obj).quit();
|
||||
} catch (Exception e) {
|
||||
// Errors may happen if returning a broken resource
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean validateObject(final Object obj) {
|
||||
if (obj instanceof JRedis) {
|
||||
try {
|
||||
((JRedis) obj).ping();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public PooledObject<JRedis> wrap(JRedis obj) {
|
||||
return new DefaultPooledObject<JRedis>(obj);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,9 +17,11 @@ package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.pool.BasePoolableObjectFactory;
|
||||
import org.apache.commons.pool.impl.GenericObjectPool;
|
||||
import org.apache.commons.pool.impl.GenericObjectPool.Config;
|
||||
import org.apache.commons.pool2.BasePooledObjectFactory;
|
||||
import org.apache.commons.pool2.PooledObject;
|
||||
import org.apache.commons.pool2.impl.DefaultPooledObject;
|
||||
import org.apache.commons.pool2.impl.GenericObjectPool;
|
||||
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.data.redis.connection.PoolException;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -28,15 +30,18 @@ import com.lambdaworks.redis.RedisAsyncConnection;
|
||||
import com.lambdaworks.redis.RedisClient;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link LettucePool}
|
||||
* Default implementation of {@link LettucePool}.
|
||||
*
|
||||
* @author Jennifer Hickey
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class DefaultLettucePool implements LettucePool, InitializingBean {
|
||||
private GenericObjectPool internalPool;
|
||||
|
||||
@SuppressWarnings("rawtypes")//
|
||||
private GenericObjectPool<RedisAsyncConnection> internalPool;
|
||||
private RedisClient client;
|
||||
private int dbIndex = 0;
|
||||
private Config poolConfig = new Config();
|
||||
private GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
|
||||
private String hostName = "localhost";
|
||||
private int port = 6379;
|
||||
private String password;
|
||||
@@ -63,25 +68,26 @@ public class DefaultLettucePool implements LettucePool, InitializingBean {
|
||||
*
|
||||
* @param hostName The Redis host
|
||||
* @param port The Redis port
|
||||
* @param poolConfig The pool {@link Config}
|
||||
* @param poolConfig The pool {@link GenericObjectPoolConfig}
|
||||
*/
|
||||
public DefaultLettucePool(String hostName, int port, Config poolConfig) {
|
||||
public DefaultLettucePool(String hostName, int port, GenericObjectPoolConfig poolConfig) {
|
||||
this.hostName = hostName;
|
||||
this.port = port;
|
||||
this.poolConfig = poolConfig;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
public void afterPropertiesSet() {
|
||||
this.client = password != null ? new AuthenticatingRedisClient(hostName, port, password) : new RedisClient(
|
||||
hostName, port);
|
||||
client.setDefaultTimeout(timeout, TimeUnit.MILLISECONDS);
|
||||
this.internalPool = new GenericObjectPool(new LettuceFactory(client, dbIndex), poolConfig);
|
||||
this.internalPool = new GenericObjectPool<RedisAsyncConnection>(new LettuceFactory(client, dbIndex), poolConfig);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public RedisAsyncConnection<byte[], byte[]> getResource() {
|
||||
try {
|
||||
return (RedisAsyncConnection<byte[], byte[]>) internalPool.borrowObject();
|
||||
return internalPool.borrowObject();
|
||||
} catch (Exception e) {
|
||||
throw new PoolException("Could not get a resource from the pool", e);
|
||||
}
|
||||
@@ -119,14 +125,14 @@ public class DefaultLettucePool implements LettucePool, InitializingBean {
|
||||
/**
|
||||
* @return The pool configuration
|
||||
*/
|
||||
public Config getPoolConfig() {
|
||||
public GenericObjectPoolConfig getPoolConfig() {
|
||||
return poolConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param poolConfig The pool configuration to use
|
||||
*/
|
||||
public void setPoolConfig(Config poolConfig) {
|
||||
public void setPoolConfig(GenericObjectPoolConfig poolConfig) {
|
||||
this.poolConfig = poolConfig;
|
||||
}
|
||||
|
||||
@@ -221,7 +227,8 @@ public class DefaultLettucePool implements LettucePool, InitializingBean {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
private static class LettuceFactory extends BasePoolableObjectFactory {
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static class LettuceFactory extends BasePooledObjectFactory<RedisAsyncConnection> {
|
||||
|
||||
private final RedisClient client;
|
||||
|
||||
@@ -233,41 +240,37 @@ public class DefaultLettucePool implements LettucePool, InitializingBean {
|
||||
this.dbIndex = dbIndex;
|
||||
}
|
||||
|
||||
public Object makeObject() throws Exception {
|
||||
return client.connectAsync(LettuceConnection.CODEC);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public void activateObject(Object obj) throws Exception {
|
||||
if (obj instanceof RedisAsyncConnection) {
|
||||
((RedisAsyncConnection) obj).select(dbIndex);
|
||||
public void activateObject(PooledObject<RedisAsyncConnection> pooledObject) throws Exception {
|
||||
pooledObject.getObject().select(dbIndex);
|
||||
}
|
||||
|
||||
public void destroyObject(final PooledObject<RedisAsyncConnection> obj) throws Exception {
|
||||
try {
|
||||
obj.getObject().close();
|
||||
} catch (Exception e) {
|
||||
// Errors may happen if returning a broken resource
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void destroyObject(final Object obj) throws Exception {
|
||||
if (obj instanceof RedisAsyncConnection) {
|
||||
try {
|
||||
((RedisAsyncConnection) obj).close();
|
||||
} catch (Exception e) {
|
||||
// Errors may happen if returning a broken resource
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public boolean validateObject(final Object obj) {
|
||||
if (obj instanceof RedisAsyncConnection) {
|
||||
try {
|
||||
((RedisAsyncConnection) obj).ping();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
public boolean validateObject(final PooledObject<RedisAsyncConnection> obj) {
|
||||
try {
|
||||
obj.getObject().ping();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RedisAsyncConnection create() throws Exception {
|
||||
return client.connectAsync(LettuceConnection.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PooledObject<RedisAsyncConnection> wrap(RedisAsyncConnection obj) {
|
||||
return new DefaultPooledObject<RedisAsyncConnection>(obj);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,23 +314,32 @@ public class LettuceConnection implements RedisConnection {
|
||||
}
|
||||
}
|
||||
|
||||
private void returnDedicatedAsyncConnection() {
|
||||
|
||||
if (pool != null) {
|
||||
|
||||
if (!broken) {
|
||||
pool.returnResource(this.asyncDedicatedConn);
|
||||
} else {
|
||||
pool.returnBrokenResource(this.asyncDedicatedConn);
|
||||
}
|
||||
this.asyncDedicatedConn = null;
|
||||
|
||||
} else {
|
||||
|
||||
try {
|
||||
asyncDedicatedConn.close();
|
||||
} catch (RuntimeException ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws DataAccessException {
|
||||
isClosed = true;
|
||||
|
||||
if (asyncDedicatedConn != null) {
|
||||
if (pool != null) {
|
||||
if (!broken) {
|
||||
pool.returnResource(asyncDedicatedConn);
|
||||
} else {
|
||||
pool.returnBrokenResource(asyncDedicatedConn);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
asyncDedicatedConn.close();
|
||||
} catch (RuntimeException ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
returnDedicatedAsyncConnection();
|
||||
}
|
||||
|
||||
if (subscription != null) {
|
||||
|
||||
Reference in New Issue
Block a user