Skip to content

Reinstate RedisCacheConfiguration.getTtl() #2629

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>3.2.0-SNAPSHOT</version>
<version>3.2.0-GH-2628-SNAPSHOT</version>

<name>Spring Data Redis</name>
<description>Spring Data module for Redis</description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,26 @@ public SerializationPair<Object> getValueSerializationPair() {
return this.valueSerializationPair;
}

/**
* Returns a computed {@link Duration TTL expiration timeout} based on cache entry key/value
* if a {@link TtlFunction} was confiugred using {@link #entryTtl(TtlFunction)}.
* <p>
* Otherwise, returns the user-provided, fixed {@link Duration} if {@link #entryTtl(Duration)}
* was called during cache configuration.
*
* @return the configured {@link Duration TTL expiration}.
* @deprecated use {@link #getTtlFunction()} instead.
*/
@Deprecated
@SuppressWarnings("all")
public Duration getTtl() {

TtlFunction ttlFunction = getTtlFunction();

return ttlFunction instanceof FixedDurationTtlFunction it ? it.duration()
: ttlFunction.getTimeToLive(null, null);
Comment on lines +345 to +346
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The key parameter of TtlFunction#getTimeToLive does not seem to be nullable. Also why cast to FixedDurationTtlFunction?

Copy link
Contributor Author

@jxblum jxblum Jul 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why a null key?

Because this is what the old, mistakingly removed, now deprecated (once again) getTtl() method did with the introduction of dynamic TTL cache configuration using the new RedisCacheWriter.TtlFunction interface.

See original Issue tickets and Pull Requests referenced in Issue #2628.

Copy link
Contributor Author

@jxblum jxblum Jul 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why cast to FixedDurationTtlFunction?

Because it is still possible to configure a "fixed" Duration TTL cache entry expiration policy using the overloaded entryTtl(:Duration) (source) builder method in RedisCacheConfiguration.

NOTE: entryTtl(:Duration) (fixed) is an alternative to entryTtl(:TtlFunction) (dynamic; here), hence the overload. Internally, a "fixed" Duration is still represented with a TtlFunction.

From this line, it will then create a (non-dynamically computed) FixedDurationTtlFunction instance (here).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FixedDurationTtlFunction#getTimeToLive would return the duration nevertheless, so really I do not see the need for a cast here.

Copy link
Contributor Author

@jxblum jxblum Jul 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Outside of a potential JVM runtime optimization here, it is true, there probably is no a need for the instance of check and implicit cast to a FixedDurationTtlFunction and direct call to the duration() method.

Feel free to change it in the polishing commit if you like. Otherwise, let me know, and I can take care of it.

}

/**
* Gets the {@link TtlFunction} used to compute a cache key {@literal time-to-live (TTL) expiration}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,18 @@
*/
package org.springframework.data.redis.cache;

import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;

import java.time.Duration;

import static org.assertj.core.api.Assertions.*;
import org.junit.jupiter.api.Test;

import org.springframework.beans.DirectFieldAccessor;
import org.springframework.core.convert.converter.Converter;
Expand All @@ -28,6 +37,7 @@
* Unit tests for {@link RedisCacheConfiguration}.
*
* @author Mark Paluch
* @author John Blum
*/
class RedisCacheConfigurationUnitTests {

Expand Down Expand Up @@ -56,6 +66,42 @@ void shouldAllowConverterRegistration() {
assertThat(config.getConversionService().canConvert(DomainType.class, String.class)).isTrue();
}

@Test // GH-2628
@SuppressWarnings("deprecation")
void getTtlReturnsFixedDuration() {

Duration sixtySeconds = Duration.ofSeconds(60);

RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(sixtySeconds);


assertThat(cacheConfiguration).isNotNull();
assertThat(cacheConfiguration.getTtl()).isEqualByComparingTo(sixtySeconds);
assertThat(cacheConfiguration.getTtl()).isEqualByComparingTo(sixtySeconds); // does not change!
}

@Test // GH-2628
@SuppressWarnings("deprecation")
public void getTtlCanReturnDynamicDuration() {

Duration thirtyMinutes = Duration.ofMinutes(30);
Duration twoHours = Duration.ofHours(2);

RedisCacheWriter.TtlFunction mockTtlFunction = mock(RedisCacheWriter.TtlFunction.class);

doReturn(thirtyMinutes).doReturn(twoHours).when(mockTtlFunction).getTimeToLive(any(), any());

RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(mockTtlFunction);

assertThat(cacheConfiguration.getTtl()).isEqualTo(thirtyMinutes);
assertThat(cacheConfiguration.getTtl()).isEqualTo(twoHours);

verify(mockTtlFunction, times(2)).getTimeToLive(isNull(), isNull());
verifyNoMoreInteractions(mockTtlFunction);
}

private static class DomainType {

}
Expand Down