From 934b95496396157fa1b25348f7f8f5f2374bb227 Mon Sep 17 00:00:00 2001 From: Emerson Dallagnol Date: Fri, 3 Jan 2020 20:30:25 -0300 Subject: [PATCH 1/3] #2515 - Test case for expiration renewal not working after connection problem; Signed-off-by: Emerson Dallagnol --- .../RedissonExpirationRenewalTest.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 redisson/src/test/java/org/redisson/RedissonExpirationRenewalTest.java diff --git a/redisson/src/test/java/org/redisson/RedissonExpirationRenewalTest.java b/redisson/src/test/java/org/redisson/RedissonExpirationRenewalTest.java new file mode 100644 index 000000000..a54c0fcec --- /dev/null +++ b/redisson/src/test/java/org/redisson/RedissonExpirationRenewalTest.java @@ -0,0 +1,45 @@ +package org.redisson; + +import org.junit.Test; +import org.redisson.api.RLock; + +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class RedissonExpirationRenewalTest extends BaseTest { + + private static final String LOCK_KEY = "LOCK_KEY"; + + @Test + public void testExpirationRenewal() throws IOException, InterruptedException { + redisson.getConfig().setLockWatchdogTimeout(3_000L); + + { + RLock lock = redisson.getLock(LOCK_KEY); + lock.lock(); + try { + Thread.sleep(5_000L); + int port = RedisRunner.defaultRedisInstance.getRedisServerPort(); + // force expiration renewal error + RedisRunner.shutDownDefaultRedisServerInstance(); + RedisRunner.defaultRedisInstance = new RedisRunner().nosave().randomDir().port(port).run(); + Thread.sleep(10_000L); + } finally { + assertThatThrownBy(lock::unlock).isInstanceOf(IllegalMonitorStateException.class); + } + } + + { + RLock lock = redisson.getLock(LOCK_KEY); + lock.lock(); + try { + // wait for timeout + Thread.sleep(30_000L); + } finally { + lock.unlock(); + } + } + } + +} From 2464e06616537a8fe35a7a772fb9cdd9860361ae Mon Sep 17 00:00:00 2001 From: Emerson Dallagnol Date: Fri, 3 Jan 2020 20:30:46 -0300 Subject: [PATCH 2/3] #2515 - Expiration renewal not working after connection problem; Signed-off-by: Emerson Dallagnol --- redisson/src/main/java/org/redisson/RedissonLock.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/redisson/src/main/java/org/redisson/RedissonLock.java b/redisson/src/main/java/org/redisson/RedissonLock.java index 35896d012..b1167ec06 100644 --- a/redisson/src/main/java/org/redisson/RedissonLock.java +++ b/redisson/src/main/java/org/redisson/RedissonLock.java @@ -570,8 +570,9 @@ public class RedissonLock extends RedissonExpirable implements RLock { RFuture future = unlockInnerAsync(threadId); future.onComplete((opStatus, e) -> { + cancelExpirationRenewal(threadId); + if (e != null) { - cancelExpirationRenewal(threadId); result.tryFailure(e); return; } @@ -582,8 +583,7 @@ public class RedissonLock extends RedissonExpirable implements RLock { result.tryFailure(cause); return; } - - cancelExpirationRenewal(threadId); + result.trySuccess(null); }); From 7048a860592678f79b9e41bcddcd6958e33c26e2 Mon Sep 17 00:00:00 2001 From: Emerson Dallagnol Date: Sat, 4 Jan 2020 21:56:22 -0300 Subject: [PATCH 3/3] #2515 - Test case for expiration renewal not working after connection problem (refactor); Signed-off-by: Emerson Dallagnol --- .../RedissonExpirationRenewalTest.java | 45 ----------- .../RedissonLockExpirationRenewalTest.java | 78 +++++++++++++++++++ 2 files changed, 78 insertions(+), 45 deletions(-) delete mode 100644 redisson/src/test/java/org/redisson/RedissonExpirationRenewalTest.java create mode 100644 redisson/src/test/java/org/redisson/RedissonLockExpirationRenewalTest.java diff --git a/redisson/src/test/java/org/redisson/RedissonExpirationRenewalTest.java b/redisson/src/test/java/org/redisson/RedissonExpirationRenewalTest.java deleted file mode 100644 index a54c0fcec..000000000 --- a/redisson/src/test/java/org/redisson/RedissonExpirationRenewalTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.redisson; - -import org.junit.Test; -import org.redisson.api.RLock; - -import java.io.IOException; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -public class RedissonExpirationRenewalTest extends BaseTest { - - private static final String LOCK_KEY = "LOCK_KEY"; - - @Test - public void testExpirationRenewal() throws IOException, InterruptedException { - redisson.getConfig().setLockWatchdogTimeout(3_000L); - - { - RLock lock = redisson.getLock(LOCK_KEY); - lock.lock(); - try { - Thread.sleep(5_000L); - int port = RedisRunner.defaultRedisInstance.getRedisServerPort(); - // force expiration renewal error - RedisRunner.shutDownDefaultRedisServerInstance(); - RedisRunner.defaultRedisInstance = new RedisRunner().nosave().randomDir().port(port).run(); - Thread.sleep(10_000L); - } finally { - assertThatThrownBy(lock::unlock).isInstanceOf(IllegalMonitorStateException.class); - } - } - - { - RLock lock = redisson.getLock(LOCK_KEY); - lock.lock(); - try { - // wait for timeout - Thread.sleep(30_000L); - } finally { - lock.unlock(); - } - } - } - -} diff --git a/redisson/src/test/java/org/redisson/RedissonLockExpirationRenewalTest.java b/redisson/src/test/java/org/redisson/RedissonLockExpirationRenewalTest.java new file mode 100644 index 000000000..5dcc38f34 --- /dev/null +++ b/redisson/src/test/java/org/redisson/RedissonLockExpirationRenewalTest.java @@ -0,0 +1,78 @@ +package org.redisson; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.redisson.config.Config; + +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class RedissonLockExpirationRenewalTest { + + private static final String LOCK_KEY = "LOCK_KEY"; + public static final long LOCK_WATCHDOG_TIMEOUT = 1_000L; + + private RedissonClient redisson; + + @Before + public void before() throws IOException, InterruptedException { + RedisRunner.startDefaultRedisServerInstance(); + redisson = createInstance(); + } + + @After + public void after() throws InterruptedException { + redisson.shutdown(); + RedisRunner.shutDownDefaultRedisServerInstance(); + } + + @Test + public void testExpirationRenewalIsWorkingAfterTimeout() throws IOException, InterruptedException { + { + RLock lock = redisson.getLock(LOCK_KEY); + lock.lock(); + try { + // force expiration renewal error + restartRedisServer(); + // wait for timeout + Thread.sleep(LOCK_WATCHDOG_TIMEOUT * 2); + } finally { + assertThatThrownBy(lock::unlock).isInstanceOf(IllegalMonitorStateException.class); + } + } + + { + RLock lock = redisson.getLock(LOCK_KEY); + lock.lock(); + try { + // wait for timeout + Thread.sleep(LOCK_WATCHDOG_TIMEOUT * 2); + } finally { + lock.unlock(); + } + } + } + + private void restartRedisServer() throws InterruptedException, IOException { + int currentPort = RedisRunner.defaultRedisInstance.getRedisServerPort(); + RedisRunner.shutDownDefaultRedisServerInstance(); + RedisRunner.defaultRedisInstance = new RedisRunner().nosave().randomDir().port(currentPort).run(); + } + + public static Config createConfig() { + Config config = new Config(); + config.useSingleServer() + .setAddress(RedisRunner.getDefaultRedisServerBindAddressAndPort()); + config.setLockWatchdogTimeout(LOCK_WATCHDOG_TIMEOUT); + return config; + } + + public static RedissonClient createInstance() { + Config config = createConfig(); + return Redisson.create(config); + } +}