Skip to content

Use Key Expire Event Listener in RedisLockRegistry [INT-4286] #8227

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
spring-operator opened this issue Jun 5, 2017 · 2 comments
Closed
Labels
in: redis status: duplicate There is already an issue similar to this. The link to it should be present type: enhancement

Comments

@spring-operator
Copy link
Contributor

Gary Russell opened INT-4286 and commented

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]>

Reference URL: https://redis.io/topics/notifications

@spring-operator
Copy link
Contributor Author

Artem Bilan commented

See also: #2894

@artembilan artembilan modified the milestones: General Backlog, Backlog Feb 14, 2023
@artembilan
Copy link
Member

Has been fixed via: #3805.

Treating as duplication.

@artembilan artembilan closed this as not planned Won't fix, can't repro, duplicate, stale Aug 30, 2023
@artembilan artembilan added the status: duplicate There is already an issue similar to this. The link to it should be present label Aug 30, 2023
@artembilan artembilan removed this from the Backlog milestone Aug 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: redis status: duplicate There is already an issue similar to this. The link to it should be present type: enhancement
Projects
None yet
Development

No branches or pull requests

2 participants