From ee3d4c2e37baf52a169b491e8d929cf6bcc6bca6 Mon Sep 17 00:00:00 2001 From: seakider Date: Wed, 18 Dec 2024 19:27:59 +0800 Subject: [PATCH] Fixed - RPermitExpirableSemaphore.release(java.util.List) shouldn't release permits if one of them doesn't exist #6343 Signed-off-by: xuxiaolei --- .../RedissonPermitExpirableSemaphore.java | 16 ++++++++---- .../RedissonPermitExpirableSemaphoreTest.java | 26 +++++++++++++++++++ 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/redisson/src/main/java/org/redisson/RedissonPermitExpirableSemaphore.java b/redisson/src/main/java/org/redisson/RedissonPermitExpirableSemaphore.java index a1cf3d6a8..39203ac47 100644 --- a/redisson/src/main/java/org/redisson/RedissonPermitExpirableSemaphore.java +++ b/redisson/src/main/java/org/redisson/RedissonPermitExpirableSemaphore.java @@ -657,6 +657,12 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen } return commandExecutor.syncedEvalWithRetry(getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_INTEGER, + "for i = 4, #ARGV, 1 do " + + "local expire = redis.call('zscore', KEYS[3], ARGV[i]);" + + "if expire== false or tonumber(expire) <= tonumber(ARGV[2]) then " + + "return 0;" + + "end; " + + "end; " + "local expiredIds = redis.call('zrangebyscore', KEYS[3], 0, ARGV[2], 'limit', 0, -1); " + "if #expiredIds > 0 then " + "redis.call('zrem', KEYS[3], unpack(expiredIds)); " + @@ -670,9 +676,6 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen "table.insert(keys, ARGV[i]); " + "end; " + "local removed = redis.call('zrem', KEYS[3], unpack(keys)); " + - "if tonumber(removed) == 0 then " + - "return 0;" + - "end; " + "redis.call('incrby', KEYS[1], removed); " + "redis.call(ARGV[3], KEYS[2], removed); " + "return removed;", @@ -733,7 +736,10 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen throw new CompletionException(e); } - if (res == permitsIds.size()) { +// if (res == permitsIds.size()) { +// return null; +// } + if (res != 0) { return null; } throw new CompletionException(new IllegalArgumentException("Permits with ids " + permitsIds + " have already been released or don't exist")); @@ -931,7 +937,7 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen if (e != null) { throw new CompletionException(e); } - + if (res == 0) { throw new CompletionException(new IllegalArgumentException("Permit with id " + permitId + " has already been released or doesn't exist")); } diff --git a/redisson/src/test/java/org/redisson/RedissonPermitExpirableSemaphoreTest.java b/redisson/src/test/java/org/redisson/RedissonPermitExpirableSemaphoreTest.java index 0b8fc1495..e0f08c9a5 100644 --- a/redisson/src/test/java/org/redisson/RedissonPermitExpirableSemaphoreTest.java +++ b/redisson/src/test/java/org/redisson/RedissonPermitExpirableSemaphoreTest.java @@ -476,6 +476,7 @@ public class RedissonPermitExpirableSemaphoreTest extends BaseConcurrentTest { assertThat(semaphore.availablePermits()).isEqualTo(10); Assertions.assertThrows(RedisException.class, () -> semaphore.release(permitsIds)); + } @Test @@ -553,6 +554,31 @@ public class RedissonPermitExpirableSemaphoreTest extends BaseConcurrentTest { assertThat(released).isEqualTo(0); assertThat(s.availablePermits()).isEqualTo(10); } + + @Test + public void testReleaseManyWithout() throws InterruptedException { + RPermitExpirableSemaphore s = redisson.getPermitExpirableSemaphore("test"); + s.trySetPermits(10); + List timedPermitsIds = s.acquire(2,100, TimeUnit.MILLISECONDS); + List permitsIds = s.tryAcquire(8); + List permitsIdsFirstPart = permitsIds.subList(0, 2); + + int released = s.tryRelease(permitsIdsFirstPart); + assertThat(released).isEqualTo(2); + assertThat(s.availablePermits()).isEqualTo(2); + + Thread.sleep(100); + + Assertions.assertThrows(RedisException.class, () -> s.release(timedPermitsIds)); + assertThat(s.availablePermits()).isEqualTo(4); + + List permitsIdsThirdPart = permitsIds.subList(4, 6); + permitsIdsThirdPart.addAll(permitsIdsFirstPart); + Assertions.assertThrows(RedisException.class, () -> s.release(permitsIdsThirdPart)); + assertThat(s.availablePermits()).isEqualTo(4); + + + } @Test public void testGetLeaseTime() throws InterruptedException {