DATAREDIS-170 - Cancel SubscriptionTask can leave connection open.
RedisMessageListenerContainer did not properly close connections if the subscription was canceled immediately after staring the container. Since DARAREDIS-242 the container waits for the subscription to complete and therefor no more connections remain open. Additionally added missing parameters to run tests with JRedis. Original pull request: #29
This commit is contained in:
committed by
Thomas Darimont
parent
5b2781377d
commit
c2bbf8a3b0
@@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -15,6 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.redis.listener;
|
package org.springframework.data.redis.listener;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -29,24 +36,22 @@ import org.springframework.data.redis.connection.MessageListener;
|
|||||||
import org.springframework.data.redis.connection.RedisConnection;
|
import org.springframework.data.redis.connection.RedisConnection;
|
||||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
||||||
|
import org.springframework.data.redis.connection.jredis.JredisConnectionFactory;
|
||||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||||
import org.springframework.data.redis.connection.srp.SrpConnectionFactory;
|
import org.springframework.data.redis.connection.srp.SrpConnectionFactory;
|
||||||
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
|
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration tests confirming that {@link RedisMessageListenerContainer} closes connections after unsubscribing
|
* Integration tests confirming that {@link RedisMessageListenerContainer} closes connections after unsubscribing
|
||||||
*
|
*
|
||||||
* @author Jennifer Hickey
|
* @author Jennifer Hickey
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
|
* @author Christoph Strobl
|
||||||
*/
|
*/
|
||||||
@RunWith(Parameterized.class)
|
@RunWith(Parameterized.class)
|
||||||
public class SubscriptionConnectionTests {
|
public class SubscriptionConnectionTests {
|
||||||
|
|
||||||
|
private static final Log logger = LogFactory.getLog(SubscriptionConnectionTests.class);
|
||||||
private static final String CHANNEL = "pubsub::test";
|
private static final String CHANNEL = "pubsub::test";
|
||||||
|
|
||||||
private RedisConnectionFactory connectionFactory;
|
private RedisConnectionFactory connectionFactory;
|
||||||
@@ -56,7 +61,7 @@ public class SubscriptionConnectionTests {
|
|||||||
private final Object handler = new Object() {
|
private final Object handler = new Object() {
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public void handleMessage(String message) {
|
public void handleMessage(String message) {
|
||||||
System.out.println(message);
|
logger.debug(message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -81,28 +86,39 @@ public class SubscriptionConnectionTests {
|
|||||||
|
|
||||||
@Parameters
|
@Parameters
|
||||||
public static Collection<Object[]> testParams() {
|
public static Collection<Object[]> testParams() {
|
||||||
|
int port = SettingsUtils.getPort();
|
||||||
|
String host = SettingsUtils.getHost();
|
||||||
|
|
||||||
// Jedis
|
// Jedis
|
||||||
JedisConnectionFactory jedisConnFactory = new JedisConnectionFactory();
|
JedisConnectionFactory jedisConnFactory = new JedisConnectionFactory();
|
||||||
jedisConnFactory.setPort(SettingsUtils.getPort());
|
jedisConnFactory.setPort(port);
|
||||||
jedisConnFactory.setHostName(SettingsUtils.getHost());
|
jedisConnFactory.setHostName(host);
|
||||||
jedisConnFactory.setDatabase(2);
|
jedisConnFactory.setDatabase(2);
|
||||||
jedisConnFactory.afterPropertiesSet();
|
jedisConnFactory.afterPropertiesSet();
|
||||||
|
|
||||||
// Lettuce
|
// Lettuce
|
||||||
LettuceConnectionFactory lettuceConnFactory = new LettuceConnectionFactory();
|
LettuceConnectionFactory lettuceConnFactory = new LettuceConnectionFactory();
|
||||||
lettuceConnFactory.setPort(SettingsUtils.getPort());
|
lettuceConnFactory.setPort(port);
|
||||||
lettuceConnFactory.setHostName(SettingsUtils.getHost());
|
lettuceConnFactory.setHostName(host);
|
||||||
lettuceConnFactory.setDatabase(2);
|
lettuceConnFactory.setDatabase(2);
|
||||||
lettuceConnFactory.setValidateConnection(true);
|
lettuceConnFactory.setValidateConnection(true);
|
||||||
lettuceConnFactory.afterPropertiesSet();
|
lettuceConnFactory.afterPropertiesSet();
|
||||||
|
|
||||||
// SRP
|
// SRP
|
||||||
SrpConnectionFactory srpConnFactory = new SrpConnectionFactory();
|
SrpConnectionFactory srpConnFactory = new SrpConnectionFactory();
|
||||||
srpConnFactory.setPort(SettingsUtils.getPort());
|
srpConnFactory.setPort(port);
|
||||||
srpConnFactory.setHostName(SettingsUtils.getHost());
|
srpConnFactory.setHostName(host);
|
||||||
srpConnFactory.afterPropertiesSet();
|
srpConnFactory.afterPropertiesSet();
|
||||||
|
|
||||||
return Arrays.asList(new Object[][] { { jedisConnFactory }, { lettuceConnFactory }, { srpConnFactory } });
|
// JRedis
|
||||||
|
JredisConnectionFactory jRedisConnectionFactory = new JredisConnectionFactory();
|
||||||
|
jRedisConnectionFactory.setPort(port);
|
||||||
|
jRedisConnectionFactory.setHostName(host);
|
||||||
|
jRedisConnectionFactory.setDatabase(2);
|
||||||
|
jRedisConnectionFactory.afterPropertiesSet();
|
||||||
|
|
||||||
|
return Arrays.asList(new Object[][] { { jedisConnFactory }, { lettuceConnFactory }, { srpConnFactory },
|
||||||
|
{ jRedisConnectionFactory } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -118,12 +134,15 @@ public class SubscriptionConnectionTests {
|
|||||||
container.setSubscriptionExecutor(new SimpleAsyncTaskExecutor());
|
container.setSubscriptionExecutor(new SimpleAsyncTaskExecutor());
|
||||||
container.afterPropertiesSet();
|
container.afterPropertiesSet();
|
||||||
container.start();
|
container.start();
|
||||||
// DATAREDIS-170 Need time for subscription to fully complete or
|
|
||||||
// cancelTask won't close connection b/c subscription is null
|
// Need to sleep shortly as jedis cannot deal propery with multiple repsonses within one connection
|
||||||
Thread.sleep(100);
|
// @see https://github.com/xetorthio/jedis/issues/186
|
||||||
|
Thread.sleep(1000);
|
||||||
|
|
||||||
container.stop();
|
container.stop();
|
||||||
containers.add(container);
|
containers.add(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify we can now get a connection from the pool
|
// verify we can now get a connection from the pool
|
||||||
RedisConnection connection = connectionFactory.getConnection();
|
RedisConnection connection = connectionFactory.getConnection();
|
||||||
connection.close();
|
connection.close();
|
||||||
@@ -145,10 +164,6 @@ public class SubscriptionConnectionTests {
|
|||||||
containers.add(container);
|
containers.add(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DATAREDIS-170 Need time for subscription to fully complete or
|
|
||||||
// cancelTask won't close connection b/c subscription is null
|
|
||||||
Thread.sleep(100);
|
|
||||||
|
|
||||||
// Removing the sole listener from the container should free up a
|
// Removing the sole listener from the container should free up a
|
||||||
// connection
|
// connection
|
||||||
containers.get(0).removeMessageListener(listener);
|
containers.get(0).removeMessageListener(listener);
|
||||||
@@ -174,10 +189,6 @@ public class SubscriptionConnectionTests {
|
|||||||
containers.add(container);
|
containers.add(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DATAREDIS-170 Need time for subscription to fully complete or
|
|
||||||
// cancelTask won't close connection b/c subscription is null
|
|
||||||
Thread.sleep(100);
|
|
||||||
|
|
||||||
// Unsubscribe all listeners from all topics, freeing up a connection
|
// Unsubscribe all listeners from all topics, freeing up a connection
|
||||||
containers.get(0).removeMessageListener(null, Arrays.asList(new Topic[] {}));
|
containers.get(0).removeMessageListener(null, Arrays.asList(new Topic[] {}));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user