Skip to content

Commit 779f117

Browse files
committed
GH-2884: RedisUtils improvements
Fixes #2884 - synchronize the map - only call once per component
1 parent 2e2b49a commit 779f117

File tree

4 files changed

+34
-5
lines changed

4 files changed

+34
-5
lines changed

spring-integration-redis/src/main/java/org/springframework/integration/redis/store/RedisMessageStore.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ public class RedisMessageStore extends AbstractKeyValueMessageStore implements B
4545

4646
private final RedisTemplate<Object, Object> redisTemplate;
4747

48+
private final boolean unlinkAvailable;
49+
4850
private boolean valueSerializerSet;
4951

5052
/**
@@ -72,6 +74,7 @@ public RedisMessageStore(RedisConnectionFactory connectionFactory, String prefix
7274
this.redisTemplate.setKeySerializer(new StringRedisSerializer());
7375
this.redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
7476
this.redisTemplate.afterPropertiesSet();
77+
this.unlinkAvailable = RedisUtils.isUnlinkAvailable(this.redisTemplate);
7578
}
7679

7780
@Override
@@ -131,7 +134,7 @@ protected Object doRemove(Object id) {
131134
Assert.notNull(id, "'id' must not be null");
132135
Object removedObject = this.doRetrieve(id);
133136
if (removedObject != null) {
134-
if (RedisUtils.isUnlinkAvailable(this.redisTemplate)) {
137+
if (this.unlinkAvailable) {
135138
this.redisTemplate.unlink(id);
136139
}
137140
else {
@@ -143,7 +146,7 @@ protected Object doRemove(Object id) {
143146

144147
@Override
145148
protected void doRemoveAll(Collection<Object> ids) {
146-
if (RedisUtils.isUnlinkAvailable(this.redisTemplate)) {
149+
if (this.unlinkAvailable) {
147150
this.redisTemplate.unlink(ids);
148151
}
149152
else {

spring-integration-redis/src/main/java/org/springframework/integration/redis/util/RedisLockRegistry.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ public final class RedisLockRegistry implements ExpirableLockRegistry, Disposabl
9797

9898
private final String registryKey;
9999

100+
private final boolean unlinkAvailable;
101+
100102
private final StringRedisTemplate redisTemplate;
101103

102104
private final RedisScript<Boolean> obtainLockScript;
@@ -138,6 +140,7 @@ public RedisLockRegistry(RedisConnectionFactory connectionFactory, String regist
138140
this.obtainLockScript = new DefaultRedisScript<>(OBTAIN_LOCK_SCRIPT, Boolean.class);
139141
this.registryKey = registryKey;
140142
this.expireAfter = expireAfter;
143+
this.unlinkAvailable = RedisUtils.isUnlinkAvailable(this.redisTemplate);
141144
}
142145

143146
/**
@@ -184,6 +187,8 @@ private final class RedisLock implements Lock {
184187

185188
private final ReentrantLock localLock = new ReentrantLock();
186189

190+
private final boolean unlinkAvailable = RedisLockRegistry.this.unlinkAvailable;
191+
187192
private volatile long lockedAt;
188193

189194
private RedisLock(String path) {
@@ -329,7 +334,7 @@ public void unlock() {
329334
}
330335

331336
private void removeLockKey() {
332-
if (RedisUtils.isUnlinkAvailable(RedisLockRegistry.this.redisTemplate)) {
337+
if (this.unlinkAvailable) {
333338
RedisLockRegistry.this.redisTemplate.unlink(this.lockKey);
334339
}
335340
else {

spring-integration-redis/src/main/java/org/springframework/integration/redis/util/RedisUtils.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.integration.redis.util;
1818

19+
import java.util.Collections;
1920
import java.util.LinkedHashMap;
2021
import java.util.Map;
2122
import java.util.Map.Entry;
@@ -41,14 +42,14 @@ public final class RedisUtils {
4142

4243
@SuppressWarnings("serial")
4344
private static final Map<RedisOperations<?, ?>, Boolean> unlinkAvailable =
44-
new LinkedHashMap<RedisOperations<?, ?>, Boolean>() {
45+
Collections.synchronizedMap(new LinkedHashMap<RedisOperations<?, ?>, Boolean>() {
4546

4647
@Override
4748
protected boolean removeEldestEntry(Entry<RedisOperations<?, ?>, Boolean> eldest) {
4849
return size() > 100;
4950
}
5051

51-
};
52+
});
5253

5354
/**
5455
* Perform an {@code INFO} command on the provided {@link RedisOperations} to check

spring-integration-redis/src/test/java/org/springframework/integration/redis/util/RedisLockRegistryTests.java

+20
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@
1818

1919
import static org.assertj.core.api.Assertions.assertThat;
2020
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
21+
import static org.mockito.ArgumentMatchers.any;
22+
import static org.mockito.BDDMockito.willReturn;
23+
import static org.mockito.Mockito.mock;
2124

2225
import java.util.Map;
26+
import java.util.Properties;
2327
import java.util.UUID;
2428
import java.util.concurrent.CountDownLatch;
2529
import java.util.concurrent.Executors;
@@ -35,6 +39,8 @@
3539
import org.junit.Test;
3640

3741
import org.springframework.data.redis.connection.RedisConnectionFactory;
42+
import org.springframework.data.redis.core.RedisCallback;
43+
import org.springframework.data.redis.core.RedisOperations;
3844
import org.springframework.data.redis.core.StringRedisTemplate;
3945
import org.springframework.integration.redis.rules.RedisAvailable;
4046
import org.springframework.integration.redis.rules.RedisAvailableTests;
@@ -429,6 +435,20 @@ public void testExpireNotChanged() throws Exception {
429435
lock.unlock();
430436
}
431437

438+
@SuppressWarnings({ "unchecked", "rawtypes" })
439+
@Test
440+
public void ntestUlink() {
441+
RedisOperations ops = mock(RedisOperations.class);
442+
Properties props = new Properties();
443+
willReturn(props).given(ops).execute(any(RedisCallback.class));
444+
props.setProperty("redis_version", "3.0.0");
445+
RedisLockRegistry registry = new RedisLockRegistry(mock(RedisConnectionFactory.class), "foo");
446+
assertThat(TestUtils.getPropertyValue(registry, "ulinkAvailable", Boolean.class)).isFalse();
447+
props.setProperty("redis_version", "4.0.0");
448+
registry = new RedisLockRegistry(mock(RedisConnectionFactory.class), "foo");
449+
assertThat(TestUtils.getPropertyValue(registry, "ulinkAvailable", Boolean.class)).isTrue();
450+
}
451+
432452
private Long getExpire(RedisLockRegistry registry, String lockKey) {
433453
StringRedisTemplate template = createTemplate();
434454
String registryKey = TestUtils.getPropertyValue(registry, "registryKey", String.class);

0 commit comments

Comments
 (0)