GH-3888: Fix NPE in the RedisLockRegistry.destroy() (#3889)

* GH-3888: Fix NPE in the `RedisLockRegistry.destroy()`

Fixed https://github.com/spring-projects/spring-integration/issues/3888

When `RedisLockType.SPIN_LOCK` (default), the `RedisLockRegistry.destroy()`
causes an NPE on the `redisMessageListenerContainer` since pub-sub is not used
in a busy-spin mode

* Check for `redisMessageListenerContainer` before calling its `destroy()`

**Cherry-pick to 5.5.x**

* * Reset properties in the `RedisLockRegistry` after `destroy()`
This commit is contained in:
Artem Bilan
2022-09-20 14:17:37 -04:00
committed by GitHub
parent ab7b57939c
commit 695e1563ed
2 changed files with 38 additions and 7 deletions

View File

@@ -245,11 +245,15 @@ public final class RedisLockRegistry implements ExpirableLockRegistry, Disposabl
if (!this.executorExplicitlySet) {
((ExecutorService) this.executor).shutdown();
}
try {
this.redisMessageListenerContainer.destroy();
}
catch (Exception ex) {
throw new IllegalStateException(ex);
if (this.redisMessageListenerContainer != null) {
try {
this.redisMessageListenerContainer.destroy();
this.redisMessageListenerContainer = null;
this.isRunningRedisMessageListenerContainer = false;
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
}

View File

@@ -107,6 +107,7 @@ class RedisLockRegistryTests implements RedisContainerTest {
}
registry.expireUnusedOlderThan(-1000);
assertThat(getRedisLockRegistryLocks(registry)).isEmpty();
registry.destroy();
}
@ParameterizedTest
@@ -126,6 +127,7 @@ class RedisLockRegistryTests implements RedisContainerTest {
}
registry.expireUnusedOlderThan(-1000);
assertThat(getRedisLockRegistryLocks(registry)).isEmpty();
registry.destroy();
}
@ParameterizedTest
@@ -153,6 +155,7 @@ class RedisLockRegistryTests implements RedisContainerTest {
}
registry.expireUnusedOlderThan(-1000);
assertThat(getRedisLockRegistryLocks(registry)).isEmpty();
registry.destroy();
}
@ParameterizedTest
@@ -180,6 +183,7 @@ class RedisLockRegistryTests implements RedisContainerTest {
}
registry.expireUnusedOlderThan(-1000);
assertThat(getRedisLockRegistryLocks(registry)).isEmpty();
registry.destroy();
}
@ParameterizedTest
@@ -207,6 +211,7 @@ class RedisLockRegistryTests implements RedisContainerTest {
}
registry.expireUnusedOlderThan(-1000);
assertThat(getRedisLockRegistryLocks(registry)).isEmpty();
registry.destroy();
}
@ParameterizedTest
@@ -238,6 +243,7 @@ class RedisLockRegistryTests implements RedisContainerTest {
assertThat(((Exception) ise).getMessage()).contains("You do not own lock at");
registry.expireUnusedOlderThan(-1000);
assertThat(getRedisLockRegistryLocks(registry)).isEmpty();
registry.destroy();
}
@ParameterizedTest
@@ -277,6 +283,7 @@ class RedisLockRegistryTests implements RedisContainerTest {
assertThat(locked.get()).isTrue();
registry.expireUnusedOlderThan(-1000);
assertThat(getRedisLockRegistryLocks(registry)).isEmpty();
registry.destroy();
}
@ParameterizedTest
@@ -326,6 +333,8 @@ class RedisLockRegistryTests implements RedisContainerTest {
registry2.expireUnusedOlderThan(-1000);
assertThat(getRedisLockRegistryLocks(registry1)).isEmpty();
assertThat(getRedisLockRegistryLocks(registry2)).isEmpty();
registry1.destroy();
registry2.destroy();
}
@ParameterizedTest
@@ -355,6 +364,7 @@ class RedisLockRegistryTests implements RedisContainerTest {
assertThat(((Exception) ise).getMessage()).contains("You do not own lock at");
registry.expireUnusedOlderThan(-1000);
assertThat(getRedisLockRegistryLocks(registry)).isEmpty();
registry.destroy();
}
@ParameterizedTest
@@ -371,6 +381,8 @@ class RedisLockRegistryTests implements RedisContainerTest {
waitForExpire("foo");
assertThat(lock2.tryLock()).isTrue();
assertThat(lock1.tryLock()).isFalse();
registry1.destroy();
registry2.destroy();
}
@ParameterizedTest
@@ -384,6 +396,7 @@ class RedisLockRegistryTests implements RedisContainerTest {
assertThatIllegalStateException()
.isThrownBy(lock1::unlock)
.withMessageContaining("Lock was released in the store due to expiration.");
registry.destroy();
}
@@ -422,6 +435,9 @@ class RedisLockRegistryTests implements RedisContainerTest {
lock2.lock();
lock1.unlock();
lock2.unlock();
registry1.destroy();
registry2.destroy();
registry3.destroy();
}
@ParameterizedTest
@@ -446,6 +462,7 @@ class RedisLockRegistryTests implements RedisContainerTest {
lock.unlock();
}
assertThat(getRedisLockRegistryLocks(registry)).hasSize(10);
registry.destroy();
}
@ParameterizedTest
@@ -468,6 +485,7 @@ class RedisLockRegistryTests implements RedisContainerTest {
result.get();
assertThat(getExpire(registry, "foo")).isEqualTo(expire);
lock.unlock();
registry.destroy();
}
@ParameterizedTest
@@ -510,6 +528,7 @@ class RedisLockRegistryTests implements RedisContainerTest {
registry.expireUnusedOlderThan(-1000);
assertThat(getRedisLockRegistryLocks(registry)).isEmpty();
registry.destroy();
}
@ParameterizedTest
@@ -558,7 +577,8 @@ class RedisLockRegistryTests implements RedisContainerTest {
executorService.awaitTermination(5, TimeUnit.SECONDS);
assertThat(getRedisLockRegistryLocks(registry)).containsKeys(
remainLockCheckQueue.toArray(new String[remainLockCheckQueue.size()]));
remainLockCheckQueue.toArray(new String[0]));
registry.destroy();
}
@ParameterizedTest
@@ -613,7 +633,8 @@ class RedisLockRegistryTests implements RedisContainerTest {
executorService.awaitTermination(5, TimeUnit.SECONDS);
assertThat(getRedisLockRegistryLocks(registry)).containsKeys(
remainLockCheckQueue.toArray(new String[remainLockCheckQueue.size()]));
remainLockCheckQueue.toArray(new String[0]));
registry.destroy();
}
@ParameterizedTest
@@ -642,6 +663,7 @@ class RedisLockRegistryTests implements RedisContainerTest {
registry.obtain("foo:5");
assertThat(getRedisLockRegistryLocks(registry)).hasSize(4);
assertThat(getRedisLockRegistryLocks(registry)).containsKeys("foo:3", "foo:4", "foo:5");
registry.destroy();
}
@ParameterizedTest
@@ -690,6 +712,8 @@ class RedisLockRegistryTests implements RedisContainerTest {
assertThat(future1).isNotCompletedExceptionally();
assertThat(future2).isNotCompletedExceptionally();
registry1.destroy();
registry2.destroy();
}
@ParameterizedTest
@@ -782,6 +806,9 @@ class RedisLockRegistryTests implements RedisContainerTest {
assertThat(awaitTimeout.await(1, TimeUnit.SECONDS)).isFalse();
assertThat(expectOne.get()).isEqualTo(1);
executorService.shutdown();
registry1.destroy();
registry2.destroy();
registry3.destroy();
}
private Long getExpire(RedisLockRegistry registry, String lockKey) {