Skip to content

Commit 49542ec

Browse files
mp911dechristophstrobl
authored andcommitted
Apply time to idle in RedisCache.retrieve(…).
We now correctly apply time to idle on retrievals. Original Pull Request: #2948
1 parent 06bbd3d commit 49542ec

File tree

3 files changed

+55
-34
lines changed

3 files changed

+55
-34
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,12 @@ protected String convertKey(Object key) {
423423
}
424424

425425
private CompletableFuture<ValueWrapper> retrieveValue(Object key) {
426-
return getCacheWriter().retrieve(getName(), createAndConvertCacheKey(key)) //
426+
427+
CompletableFuture<byte[]> retrieve = getCacheConfiguration().isTimeToIdleEnabled()
428+
? getCacheWriter().retrieve(getName(), createAndConvertCacheKey(key), getTimeToLive(key))
429+
: getCacheWriter().retrieve(getName(), createAndConvertCacheKey(key));
430+
431+
return retrieve //
427432
.thenApply(binaryValue -> binaryValue != null ? deserializeCacheValue(binaryValue) : null) //
428433
.thenApply(this::toValueWrapper);
429434
}

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

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -213,10 +213,10 @@ default CompletableFuture<byte[]> retrieve(String name, byte[] key) {
213213
/**
214214
* Write the given key/value pair to Redis and set the expiration time if defined.
215215
*
216-
* @param name The cache name must not be {@literal null}.
217-
* @param key The key for the cache entry. Must not be {@literal null}.
218-
* @param value The value stored for the key. Must not be {@literal null}.
219-
* @param ttl Optional expiration time. Can be {@literal null}.
216+
* @param name cache name must not be {@literal null}.
217+
* @param key key for the cache entry. Must not be {@literal null}.
218+
* @param value value stored for the key. Must not be {@literal null}.
219+
* @param ttl optional expiration time. Can be {@literal null}.
220220
*/
221221
void put(String name, byte[] key, byte[] value, @Nullable Duration ttl);
222222

@@ -225,21 +225,21 @@ default CompletableFuture<byte[]> retrieve(String name, byte[] key) {
225225
* <p>
226226
* This operation is non-blocking.
227227
*
228-
* @param name The cache name must not be {@literal null}.
229-
* @param key The key for the cache entry. Must not be {@literal null}.
230-
* @param value The value stored for the key. Must not be {@literal null}.
231-
* @param ttl Optional expiration time. Can be {@literal null}.
228+
* @param name cache name must not be {@literal null}.
229+
* @param key key for the cache entry. Must not be {@literal null}.
230+
* @param value value stored for the key. Must not be {@literal null}.
231+
* @param ttl optional expiration time. Can be {@literal null}.
232232
* @since 3.2
233233
*/
234234
CompletableFuture<Void> store(String name, byte[] key, byte[] value, @Nullable Duration ttl);
235235

236236
/**
237237
* Write the given value to Redis if the key does not already exist.
238238
*
239-
* @param name The cache name must not be {@literal null}.
240-
* @param key The key for the cache entry. Must not be {@literal null}.
241-
* @param value The value stored for the key. Must not be {@literal null}.
242-
* @param ttl Optional expiration time. Can be {@literal null}.
239+
* @param name cache name must not be {@literal null}.
240+
* @param key key for the cache entry. Must not be {@literal null}.
241+
* @param value value stored for the key. Must not be {@literal null}.
242+
* @param ttl optional expiration time. Can be {@literal null}.
243243
* @return {@literal null} if the value has been written, the value stored for the key if it already exists.
244244
*/
245245
@Nullable
@@ -248,16 +248,16 @@ default CompletableFuture<byte[]> retrieve(String name, byte[] key) {
248248
/**
249249
* Remove the given key from Redis.
250250
*
251-
* @param name The cache name must not be {@literal null}.
252-
* @param key The key for the cache entry. Must not be {@literal null}.
251+
* @param name cache name must not be {@literal null}.
252+
* @param key key for the cache entry. Must not be {@literal null}.
253253
*/
254254
void remove(String name, byte[] key);
255255

256256
/**
257257
* Remove all keys following the given pattern.
258258
*
259-
* @param name The cache name must not be {@literal null}.
260-
* @param pattern The pattern for the keys to remove. Must not be {@literal null}.
259+
* @param name cache name must not be {@literal null}.
260+
* @param pattern pattern for the keys to remove. Must not be {@literal null}.
261261
*/
262262
void clean(String name, byte[] pattern);
263263

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

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616
package org.springframework.data.redis.cache;
1717

1818
import static org.assertj.core.api.Assertions.*;
19-
import static org.awaitility.Awaitility.*;
20-
21-
import io.netty.util.concurrent.DefaultThreadFactory;
2219

2320
import java.io.Serializable;
2421
import java.nio.charset.StandardCharsets;
@@ -29,20 +26,16 @@
2926
import java.util.Date;
3027
import java.util.Objects;
3128
import java.util.concurrent.CompletableFuture;
32-
import java.util.concurrent.CountDownLatch;
33-
import java.util.concurrent.LinkedBlockingDeque;
34-
import java.util.concurrent.ThreadPoolExecutor;
29+
import java.util.concurrent.ExecutionException;
3530
import java.util.concurrent.TimeUnit;
3631
import java.util.concurrent.atomic.AtomicBoolean;
37-
import java.util.concurrent.atomic.AtomicInteger;
3832
import java.util.concurrent.atomic.AtomicLong;
39-
import java.util.concurrent.atomic.AtomicReference;
4033
import java.util.function.Consumer;
4134
import java.util.function.Function;
4235
import java.util.function.Supplier;
43-
import java.util.stream.IntStream;
4436

4537
import org.junit.jupiter.api.BeforeEach;
38+
4639
import org.springframework.cache.Cache.ValueWrapper;
4740
import org.springframework.cache.interceptor.SimpleKey;
4841
import org.springframework.cache.interceptor.SimpleKeyGenerator;
@@ -478,11 +471,10 @@ void cacheGetWithTimeToIdleExpirationWhenEntryNotExpiredShouldReturnValue() {
478471

479472
assertThat(unwrap(cache.get(this.key))).isEqualTo(this.sample);
480473

481-
for (int count = 0; count < 5; count++) {
474+
doWithConnection(connection -> {
482475

483-
await().atMost(Duration.ofMillis(100));
484-
assertThat(unwrap(cache.get(this.key))).isEqualTo(this.sample);
485-
}
476+
assertThat(connection.keyCommands().ttl(this.binaryCacheKey)).isGreaterThan(1);
477+
});
486478
}
487479

488480
@EnabledOnCommand("GETEX")
@@ -496,9 +488,9 @@ void cacheGetWithTimeToIdleExpirationAfterEntryExpiresShouldReturnNull() {
496488

497489
assertThat(unwrap(cache.get(this.key))).isEqualTo(this.sample);
498490

499-
await().atMost(Duration.ofMillis(200));
500-
501-
assertThat(cache.get(this.cacheKey, Person.class)).isNull();
491+
doWithConnection(connection -> {
492+
assertThat(connection.keyCommands().ttl(this.binaryCacheKey)).isGreaterThan(1);
493+
});
502494
}
503495

504496
@ParameterizedRedisTest // GH-2650
@@ -533,6 +525,30 @@ void retrieveReturnsCachedValue() throws Exception {
533525
assertThat(value.get(5, TimeUnit.SECONDS)).isNotNull();
534526
assertThat(value.get().get()).isEqualTo(this.sample);
535527
assertThat(value).isDone();
528+
529+
doWithConnection(connection -> {
530+
assertThat(connection.keyCommands().ttl(this.binaryCacheKey)).isEqualTo(-1);
531+
});
532+
}
533+
534+
@ParameterizedRedisTest // GH-2890
535+
@EnabledOnRedisDriver(RedisDriver.LETTUCE)
536+
void retrieveAppliesTimeToIdle() throws ExecutionException, InterruptedException {
537+
538+
doWithConnection(connection -> connection.stringCommands().set(this.binaryCacheKey, this.binarySample));
539+
540+
RedisCache cache = new RedisCache("cache", usingRedisCacheWriter(),
541+
usingRedisCacheConfiguration(withTtiExpiration()));
542+
543+
CompletableFuture<ValueWrapper> value = cache.retrieve(this.key);
544+
545+
assertThat(value).isNotNull();
546+
assertThat(value.get().get()).isEqualTo(this.sample);
547+
assertThat(value).isDone();
548+
549+
doWithConnection(connection -> {
550+
assertThat(connection.keyCommands().ttl(this.binaryCacheKey)).isGreaterThan(1);
551+
});
536552
}
537553

538554
@ParameterizedRedisTest // GH-2650
@@ -689,7 +705,7 @@ private Object unwrap(@Nullable Object value) {
689705
private Function<RedisCacheConfiguration, RedisCacheConfiguration> withTtiExpiration() {
690706

691707
Function<RedisCacheConfiguration, RedisCacheConfiguration> entryTtlFunction = cacheConfiguration -> cacheConfiguration
692-
.entryTtl(Duration.ofMillis(100));
708+
.entryTtl(Duration.ofSeconds(10));
693709

694710
return entryTtlFunction.andThen(RedisCacheConfiguration::enableTimeToIdle);
695711
}

0 commit comments

Comments
 (0)