Skip to content

Commit 0f45851

Browse files
Polishing.
Remove no longer needed wasLocked flag from CacheWriter. Original Pull Request: #2948
1 parent 49542ec commit 0f45851

File tree

3 files changed

+46
-18
lines changed

3 files changed

+46
-18
lines changed

src/main/java/org/springframework/data/redis/cache/DefaultRedisCacheWriter.java

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.concurrent.CompletableFuture;
2525
import java.util.concurrent.TimeUnit;
2626
import java.util.concurrent.atomic.AtomicLong;
27+
import java.util.function.Consumer;
2728
import java.util.function.Function;
2829
import java.util.function.Supplier;
2930

@@ -177,10 +178,8 @@ public byte[] get(String name, byte[] key, Supplier<byte[]> valueLoader, @Nullab
177178

178179
return execute(name, connection -> {
179180

180-
boolean wasLocked = false;
181181
if (isLockingCacheWriter()) {
182182
doLock(name, key, null, connection);
183-
wasLocked = true;
184183
}
185184

186185
try {
@@ -195,7 +194,7 @@ public byte[] get(String name, byte[] key, Supplier<byte[]> valueLoader, @Nullab
195194
doPut(connection, name, key, value, ttl);
196195
return value;
197196
} finally {
198-
if (isLockingCacheWriter() && wasLocked) {
197+
if (isLockingCacheWriter()) {
199198
doUnlock(name, connection);
200199
}
201200
}
@@ -274,10 +273,8 @@ public byte[] putIfAbsent(String name, byte[] key, byte[] value, @Nullable Durat
274273

275274
return execute(name, connection -> {
276275

277-
boolean wasLocked = false;
278276
if (isLockingCacheWriter()) {
279277
doLock(name, key, value, connection);
280-
wasLocked = true;
281278
}
282279

283280
try {
@@ -299,7 +296,7 @@ public byte[] putIfAbsent(String name, byte[] key, byte[] value, @Nullable Durat
299296
return connection.stringCommands().get(key);
300297

301298
} finally {
302-
if (isLockingCacheWriter() && wasLocked) {
299+
if (isLockingCacheWriter()) {
303300
doUnlock(name, connection);
304301
}
305302
}
@@ -324,12 +321,9 @@ public void clean(String name, byte[] pattern) {
324321

325322
execute(name, connection -> {
326323

327-
boolean wasLocked = false;
328-
329324
try {
330325
if (isLockingCacheWriter()) {
331326
doLock(name, name, pattern, connection);
332-
wasLocked = true;
333327
}
334328

335329
long deleteCount = batchStrategy.cleanCache(connection, name, pattern);
@@ -342,7 +336,7 @@ public void clean(String name, byte[] pattern) {
342336
statistics.incDeletesBy(name, (int) deleteCount);
343337

344338
} finally {
345-
if (wasLocked && isLockingCacheWriter()) {
339+
if (isLockingCacheWriter()) {
346340
doUnlock(name, connection);
347341
}
348342
}
@@ -373,10 +367,10 @@ public RedisCacheWriter withStatisticsCollector(CacheStatisticsCollector cacheSt
373367
* @param name the name of the cache to lock.
374368
*/
375369
void lock(String name) {
376-
execute(name, connection -> doLock(name, name, null, connection));
370+
executeWithoutResult(name, connection -> doLock(name, name, null, connection));
377371
}
378372

379-
boolean doLock(String name, Object contextualKey, @Nullable Object contextualValue, RedisConnection connection) {
373+
void doLock(String name, Object contextualKey, @Nullable Object contextualValue, RedisConnection connection) {
380374

381375
RedisStringCommands commands = connection.stringCommands();
382376
Expiration expiration = Expiration.from(this.lockTtl.getTimeToLive(contextualKey, contextualValue));
@@ -386,8 +380,6 @@ boolean doLock(String name, Object contextualKey, @Nullable Object contextualVal
386380
true)) {
387381
checkAndPotentiallyWaitUntilUnlocked(name, connection);
388382
}
389-
390-
return true;
391383
}
392384

393385
/**
@@ -412,6 +404,14 @@ private <T> T execute(String name, Function<RedisConnection, T> callback) {
412404
}
413405
}
414406

407+
private void executeWithoutResult(String name, Consumer<RedisConnection> callback) {
408+
409+
try (RedisConnection connection = this.connectionFactory.getConnection()) {
410+
checkAndPotentiallyWaitUntilUnlocked(name, connection);
411+
callback.accept(connection);
412+
}
413+
}
414+
415415
private <T> T executeLockFree(Function<RedisConnection, T> callback) {
416416

417417
try (RedisConnection connection = this.connectionFactory.getConnection()) {

src/test/java/org/springframework/data/redis/cache/DefaultRedisCachWriterUnitTests.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@
1616
package org.springframework.data.redis.cache;
1717

1818
import static org.assertj.core.api.Assertions.assertThat;
19+
import static org.assertj.core.api.Assertions.assertThatException;
1920
import static org.mockito.ArgumentMatchers.any;
2021
import static org.mockito.ArgumentMatchers.eq;
2122
import static org.mockito.Mockito.doReturn;
23+
import static org.mockito.Mockito.doThrow;
2224
import static org.mockito.Mockito.mock;
25+
import static org.mockito.Mockito.never;
2326
import static org.mockito.Mockito.spy;
2427
import static org.mockito.Mockito.times;
2528
import static org.mockito.Mockito.verify;
@@ -32,16 +35,18 @@
3235
import org.junit.jupiter.api.extension.ExtendWith;
3336
import org.mockito.Mock;
3437
import org.mockito.junit.jupiter.MockitoExtension;
35-
38+
import org.springframework.dao.PessimisticLockingFailureException;
3639
import org.springframework.data.redis.connection.RedisConnection;
3740
import org.springframework.data.redis.connection.RedisConnectionFactory;
41+
import org.springframework.data.redis.connection.RedisKeyCommands;
3842
import org.springframework.data.redis.connection.RedisStringCommands;
3943
import org.springframework.data.redis.core.types.Expiration;
4044

4145
/**
4246
* Unit tests for {@link DefaultRedisCacheWriter}
4347
*
4448
* @author John Blum
49+
* @author Christoph Strobl
4550
*/
4651
@ExtendWith(MockitoExtension.class)
4752
class DefaultRedisCacheWriterUnitTests {
@@ -109,4 +114,28 @@ void getWithNullTtl() {
109114
verify(this.mockConnection, times(1)).close();
110115
verifyNoMoreInteractions(this.mockConnection, mockStringCommands);
111116
}
117+
118+
@Test // GH-2890
119+
void mustNotUnlockWhenLockingFails() {
120+
121+
byte[] key = "TestKey".getBytes();
122+
byte[] value = "TestValue".getBytes();
123+
124+
RedisStringCommands mockStringCommands = mock(RedisStringCommands.class);
125+
RedisKeyCommands mockKeyCommands = mock(RedisKeyCommands.class);
126+
127+
doReturn(mockStringCommands).when(this.mockConnection).stringCommands();
128+
doReturn(mockKeyCommands).when(this.mockConnection).keyCommands();
129+
doThrow(new PessimisticLockingFailureException("you-shall-not-pass")).when(mockStringCommands).set(any(byte[].class),
130+
any(byte[].class), any(), any());
131+
132+
RedisCacheWriter cacheWriter = spy(
133+
new DefaultRedisCacheWriter(this.mockConnectionFactory, Duration.ofMillis(10), mock(BatchStrategy.class))
134+
.withStatisticsCollector(this.mockCacheStatisticsCollector));
135+
136+
assertThatException()
137+
.isThrownBy(() -> cacheWriter.get("TestCache", key, () -> value, Duration.ofMillis(10), false));
138+
139+
verify(mockKeyCommands, never()).del(any());
140+
}
112141
}

src/test/java/org/springframework/data/redis/cache/DefaultRedisCacheWriterTests.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -453,13 +453,12 @@ void doLockShouldGetLock() throws InterruptedException {
453453
DefaultRedisCacheWriter cw = new DefaultRedisCacheWriter(connectionFactory, Duration.ofMillis(10),
454454
BatchStrategies.keys()) {
455455

456-
boolean doLock(String name, Object contextualKey, @Nullable Object contextualValue, RedisConnection connection) {
456+
void doLock(String name, Object contextualKey, @Nullable Object contextualValue, RedisConnection connection) {
457457

458-
boolean doLock = super.doLock(name, contextualKey, contextualValue, connection);
458+
super.doLock(name, contextualKey, contextualValue, connection);
459459

460460
// any concurrent access (aka not waiting until the lock is acquired) will result in a concurrency greater 1
461461
assertThat(concurrency.incrementAndGet()).isOne();
462-
return doLock;
463462
}
464463

465464
@Nullable

0 commit comments

Comments
 (0)