Uploaded image for project: 'Spring Integration'
  1. Spring Integration
  2. INT-4286

Use Key Expire Event Listener in RedisLockRegistry

    XMLWordPrintable

    Details

    • Type: Improvement
    • Status: Open
    • Priority: Minor
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: 5.2 Backlog
    • Component/s: Redis Support
    • Labels:
      None

      Description

      Since 1.7, spring-data-redis provides a canned RedisKeyExpiredEvent which publishes expiration events as ApplicationEvents.

      Quick test:

      diff --git a/spring-integration-redis/src/main/java/org/springframework/integration/redis/util/RedisLockRegistry.java b/spring-integration-redis/src/main/java/org/springframework/integration/redis/util/RedisLockRegistry.java
      index b9940a9..1c9dc44 100644
      --- a/spring-integration-redis/src/main/java/org/springframework/integration/redis/util/RedisLockRegistry.java
      +++ b/spring-integration-redis/src/main/java/org/springframework/integration/redis/util/RedisLockRegistry.java
      @@ -31,8 +31,10 @@ import java.util.concurrent.locks.ReentrantLock;
       import org.apache.commons.logging.Log;
       import org.apache.commons.logging.LogFactory;
       
      +import org.springframework.context.ApplicationListener;
       import org.springframework.dao.CannotAcquireLockException;
       import org.springframework.data.redis.connection.RedisConnectionFactory;
      +import org.springframework.data.redis.core.RedisKeyExpiredEvent;
       import org.springframework.data.redis.core.StringRedisTemplate;
       import org.springframework.data.redis.core.script.DefaultRedisScript;
       import org.springframework.data.redis.core.script.RedisScript;
      @@ -68,7 +70,7 @@ import org.springframework.util.Assert;
        * @since 4.0
        *
        */
      -public final class RedisLockRegistry implements ExpirableLockRegistry {
      +public final class RedisLockRegistry implements ExpirableLockRegistry, ApplicationListener<RedisKeyExpiredEvent<?>> {
       
       	private static final Log logger = LogFactory.getLog(RedisLockRegistry.class);
       
      @@ -333,4 +335,9 @@ public final class RedisLockRegistry implements ExpirableLockRegistry {
       
       	}
       
      +	@Override
      +	public void onApplicationEvent(RedisKeyExpiredEvent<?> event) {
      +		logger.warn(event);
      +              // invalidate lock here
      +	}
      +
       }
      diff --git a/spring-integration-redis/src/test/java/org/springframework/integration/redis/util/RedisLockRegistryTests.java b/spring-integration-redis/src/test/java/org/springframework/integration/redis/util/RedisLockRegistryTests.java
      index ef3df49..c47a278 100644
      --- a/spring-integration-redis/src/test/java/org/springframework/integration/redis/util/RedisLockRegistryTests.java
      +++ b/spring-integration-redis/src/test/java/org/springframework/integration/redis/util/RedisLockRegistryTests.java
      @@ -44,8 +44,14 @@ import org.junit.Rule;
       import org.junit.Test;
       import org.junit.rules.ExpectedException;
       
      +import org.springframework.context.annotation.AnnotationConfigApplicationContext;
      +import org.springframework.context.annotation.Bean;
      +import org.springframework.context.annotation.Configuration;
       import org.springframework.data.redis.connection.RedisConnectionFactory;
      +import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
       import org.springframework.data.redis.core.StringRedisTemplate;
      +import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
      +import org.springframework.data.redis.listener.RedisMessageListenerContainer;
       import org.springframework.integration.redis.rules.RedisAvailable;
       import org.springframework.integration.redis.rules.RedisAvailableTests;
       import org.springframework.integration.test.rule.Log4jLevelAdjuster;
      @@ -68,7 +74,8 @@ public class RedisLockRegistryTests extends RedisAvailableTests {
       	private final String registryKey2 = UUID.randomUUID().toString();
       
       	@Rule
      -	public Log4jLevelAdjuster adjuster = new Log4jLevelAdjuster(Level.TRACE, "org.springframework.integration.redis");
      +	public Log4jLevelAdjuster adjuster = new Log4jLevelAdjuster(Level.TRACE,
      +			"org.springframework.integration.redis", "org.springframework.data.redis");
       
       	@Rule
       	public ExpectedException thrown = ExpectedException.none();
      @@ -389,6 +396,48 @@ public class RedisLockRegistryTests extends RedisAvailableTests {
       		lock2.unlock();
       	}
       
      +	@Configuration
      +	public static class Config {
      +
      +		@Bean
      +		public RedisConnectionFactory cf() {
      +			JedisConnectionFactory connectionFactory = new JedisConnectionFactory();
      +			connectionFactory.setPort(6379);
      +			connectionFactory.setTimeout(10000);
      +			return connectionFactory;
      +		}
      +
      +		@Bean
      +		public RedisLockRegistry registry() {
      +			return new RedisLockRegistry(cf(), "foo", 10_000L);
      +		}
      +
      +		@Bean
      +		public RedisMessageListenerContainer container() {
      +			RedisMessageListenerContainer container = new RedisMessageListenerContainer();
      +			container.setConnectionFactory(cf());
      +			return container;
      +		}
      +
      +		@Bean
      +		public KeyExpirationEventMessageListener listener() {
      +			return new KeyExpirationEventMessageListener(container());
      +		}
      +
      +	}
      +
      +	@Test
      +	@RedisAvailable
      +	public void testEvent() throws Exception {
      +		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
      +		RedisLockRegistry registry1 = ctx.getBean(RedisLockRegistry.class);
      +		Lock lock1 = registry1.obtain("foo");
      +		lock1.lock();
      +		Thread.sleep(30_000);
      +		lock1.unlock();
      +		ctx.close();
      +	}
      +
       	@Test
       	@RedisAvailable
       	public void testThreadLocalListLeaks() {
      
      2017-06-05 16:39:05,030  WARN container-2 [org.springframework.integration.redis.util.RedisLockRegistry] - <RedisKeyExpiredEvent [keyspace=foo, id=[B@39a8b068]>
      

        Attachments

          Activity

            People

            Assignee:
            grussell Gary Russell
            Reporter:
            grussell Gary Russell
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated: