Skip to content
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

Support KEEPTTL via ValueOperations. #2770

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ public Mono<Boolean> set(K key, V value, Duration timeout) {
stringCommands.set(rawKey(key), rawValue(value), Expiration.from(timeout), SetOption.UPSERT));
}

@Override
public Mono<Boolean> set(K key, V value, boolean keepTtl) {

Assert.notNull(key, "Key must not be null");

Expiration expiration = keepTtl ? Expiration.keepTtl() : Expiration.persistent();
return createMono(stringCommands -> stringCommands.set(rawKey(key), rawValue(value), expiration, SetOption.UPSERT));
}

@Override
public Mono<Boolean> setIfAbsent(K key, V value) {

Expand Down Expand Up @@ -115,6 +124,16 @@ public Mono<Boolean> setIfPresent(K key, V value, Duration timeout) {
stringCommands.set(rawKey(key), rawValue(value), Expiration.from(timeout), SetOption.SET_IF_PRESENT));
}

@Override
public Mono<Boolean> setIfPresent(K key, V value, boolean keepTtl) {

Assert.notNull(key, "Key must not be null");

Expiration expiration = keepTtl ? Expiration.keepTtl() : Expiration.persistent();
return createMono(
stringCommands -> stringCommands.set(rawKey(key), rawValue(value), expiration, SetOption.SET_IF_PRESENT));
}

@Override
public Mono<Boolean> multiSet(Map<? extends K, ? extends V> map) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,16 @@ private boolean failsafeInvokePsetEx(RedisConnection connection) {
});
}

@Override
public void set(K key, V value, boolean keepTtl) {

byte[] rawKey = rawKey(key);
byte[] rawValue = rawValue(value);

Expiration expiration = keepTtl ? Expiration.keepTtl() : Expiration.persistent();
execute(connection -> connection.set(rawKey, rawValue, expiration, SetOption.upsert()));
}

@Override
public Boolean setIfAbsent(K key, V value) {

Expand Down Expand Up @@ -320,6 +330,16 @@ public Boolean setIfPresent(K key, V value, long timeout, TimeUnit unit) {
return execute(connection -> connection.set(rawKey, rawValue, expiration, SetOption.ifPresent()));
}

@Override
public Boolean setIfPresent(K key, V value, boolean keepTtl) {

byte[] rawKey = rawKey(key);
byte[] rawValue = rawValue(value);

Expiration expiration = keepTtl ? Expiration.keepTtl() : Expiration.persistent();
return execute(connection -> connection.set(rawKey, rawValue, expiration, SetOption.ifPresent()));
}

@Override
public void set(K key, V value, long offset) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ public interface ReactiveValueOperations<K, V> {
*/
Mono<Boolean> set(K key, V value, Duration timeout);

/**
* Set {@code value} for {@code key}.
*
* @param key must not be {@literal null}.
* @param value
* @param keepTtl whether to retain TTL associated with the key.
* @see <a href="https://redis.io/commands/set">Redis Documentation: SET</a>
*/
Mono<Boolean> set(K key, V value, boolean keepTtl);

/**
* Set {@code key} to hold the string {@code value} if {@code key} is absent.
*
Expand Down Expand Up @@ -98,6 +108,16 @@ public interface ReactiveValueOperations<K, V> {
*/
Mono<Boolean> setIfPresent(K key, V value, Duration timeout);

/**
* Set {@code key} to hold the string {@code value} if {@code key} is present.
*
* @param key must not be {@literal null}.
* @param value
* @param keepTtl whether to retain TTL associated with the key.
* @see <a href="https://redis.io/commands/set">Redis Documentation: SET</a>
*/
Mono<Boolean> setIfPresent(K key, V value, boolean keepTtl);

/**
* Set multiple keys to multiple values using key-value pairs provided in {@code tuple}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ default void set(K key, V value, Duration timeout) {
}
}

/**
* Set {@code value} for {@code key}.
*
* @param key must not be {@literal null}.
* @param value must not be {@literal null}.
* @param keepTtl whether to retain TTL associated with the key.
* @see <a href="https://redis.io/commands/set">Redis Documentation: SET</a>
*/
void set(K key, V value, boolean keepTtl);

/**
* Set {@code key} to hold the string {@code value} if {@code key} is absent.
*
Expand Down Expand Up @@ -175,6 +185,19 @@ default Boolean setIfPresent(K key, V value, Duration timeout) {
return setIfPresent(key, value, timeout.getSeconds(), TimeUnit.SECONDS);
}

/**
* Set {@code key} to hold the string {@code value} if {@code key} is present.
*
* @param key must not be {@literal null}.
* @param value must not be {@literal null}.
* @param keepTtl whether to retain TTL associated with the key.
* @return command result indicating if the key has been set.
* @throws IllegalArgumentException if either {@code key} or {@code value} is not present.
* @see <a href="https://redis.io/commands/set">Redis Documentation: SET</a>
*/
@Nullable
Boolean setIfPresent(K key, V value, boolean keepTtl);

/**
* Set multiple keys to multiple values using key-value pairs provided in {@code tuple}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,50 @@ void set() {
valueOperations.get(key).as(StepVerifier::create).expectNext(value).verifyComplete();
}

@ParameterizedRedisTest // GH-2084
void setWithKeepTtl() {

K key = keyFactory.instance();
V value1 = valueFactory.instance();
V value2 = valueFactory.instance();

valueOperations.set(key, value1, Duration.ofMillis(5500)).as(StepVerifier::create) //
.expectNext(true) //
.verifyComplete();
valueOperations.set(key, value2, true).as(StepVerifier::create) //
.expectNext(true) //
.verifyComplete();

valueOperations.get(key).as(StepVerifier::create) //
.expectNext(value2) //
.verifyComplete();
redisTemplate.getExpire(key).as(StepVerifier::create) //
.assertNext(actual -> assertThat(actual).isBetween(Duration.ofMillis(1), Duration.ofSeconds(6))) //
.verifyComplete();
}

@ParameterizedRedisTest // GH-2084
void setWithoutKeepTtl() {

K key = keyFactory.instance();
V value1 = valueFactory.instance();
V value2 = valueFactory.instance();

valueOperations.set(key, value1, Duration.ofMillis(5500)).as(StepVerifier::create) //
.expectNext(true) //
.verifyComplete();
valueOperations.set(key, value2, false).as(StepVerifier::create) //
.expectNext(true) //
.verifyComplete();

valueOperations.get(key).as(StepVerifier::create) //
.expectNext(value2) //
.verifyComplete();
redisTemplate.getExpire(key).as(StepVerifier::create) //
.assertNext(actual -> assertThat(actual).isZero()) //
.verifyComplete();
}

@ParameterizedRedisTest // DATAREDIS-602
void setWithExpiry() {

Expand Down Expand Up @@ -186,6 +230,58 @@ void setIfPresentWithExpiry() {
}).verifyComplete();
}

@ParameterizedRedisTest // GH-2084
void setIfPresentWithKeepTtl() {

K key = keyFactory.instance();
V value1 = valueFactory.instance();
V value2 = valueFactory.instance();

valueOperations.setIfPresent(key, value1, true).as(StepVerifier::create) //
.expectNext(false) //
.verifyComplete();
valueOperations.set(key, value1, Duration.ofMillis(5500)).as(StepVerifier::create) //
.expectNext(true) //
.verifyComplete();

valueOperations.setIfPresent(key, value2, true).as(StepVerifier::create) //
.expectNext(true) //
.verifyComplete();

valueOperations.get(key).as(StepVerifier::create) //
.expectNext(value2) //
.verifyComplete();
redisTemplate.getExpire(key).as(StepVerifier::create) //
.assertNext(actual -> assertThat(actual).isBetween(Duration.ofMillis(1), Duration.ofSeconds(6))) //
.verifyComplete();
}

@ParameterizedRedisTest // GH-2084
void setIfPresentWithoutKeepTtl() {

K key = keyFactory.instance();
V value1 = valueFactory.instance();
V value2 = valueFactory.instance();

valueOperations.setIfPresent(key, value1, false).as(StepVerifier::create) //
.expectNext(false) //
.verifyComplete();
valueOperations.set(key, value1, Duration.ofMillis(5500)).as(StepVerifier::create) //
.expectNext(true) //
.verifyComplete();

valueOperations.setIfPresent(key, value2, false).as(StepVerifier::create) //
.expectNext(true) //
.verifyComplete();

valueOperations.get(key).as(StepVerifier::create) //
.expectNext(value2) //
.verifyComplete();
redisTemplate.getExpire(key).as(StepVerifier::create) //
.assertNext(actual -> assertThat(actual).isZero()) //
.verifyComplete();
}

@ParameterizedRedisTest // DATAREDIS-602
void multiSet() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,37 @@ void testSetWithExpirationWithTimeUnitMilliseconds() {
await().atMost(Duration.ofMillis(500L)).until(() -> !redisTemplate.hasKey(key));
}

@ParameterizedRedisTest // GH-2084
void testSetWithKeepTtl() {

K key = keyFactory.instance();
V value1 = valueFactory.instance();
V value2 = valueFactory.instance();

valueOps.set(key, value1, Duration.ofMillis(5500));
valueOps.set(key, value2, true);

Long expire = redisTemplate.getExpire(key, TimeUnit.MILLISECONDS);

assertThat(valueOps.get(key)).isEqualTo(value2);
assertThat(expire).isLessThan(TimeUnit.SECONDS.toMillis(6));
assertThat(expire).isGreaterThan(TimeUnit.MILLISECONDS.toMillis(1));
}

@ParameterizedRedisTest // GH-2084
void testSetWithoutKeepTtl() {

K key = keyFactory.instance();
V value1 = valueFactory.instance();
V value2 = valueFactory.instance();

valueOps.set(key, value1, Duration.ofMillis(5500));
valueOps.set(key, value2, false);

assertThat(valueOps.get(key)).isEqualTo(value2);
assertThat(redisTemplate.getExpire(key)).isEqualTo(-1);
}

@ParameterizedRedisTest
void testAppend() {

Expand Down Expand Up @@ -483,6 +514,39 @@ void testSetIfPresentWithExpirationPX() {
assertThat(valueOps.get(key)).isEqualTo(value2);
}

@ParameterizedRedisTest // GH-2084
void testSetIfPresentWithKeepTtl() {

K key = keyFactory.instance();
V value1 = valueFactory.instance();
V value2 = valueFactory.instance();

assertThat(valueOps.setIfPresent(key, value1, true)).isFalse();
valueOps.set(key, value1, Duration.ofMillis(5500));

Long expire = redisTemplate.getExpire(key, TimeUnit.MILLISECONDS);

assertThat(valueOps.setIfPresent(key, value2, true)).isTrue();
assertThat(valueOps.get(key)).isEqualTo(value2);
assertThat(expire).isLessThan(TimeUnit.SECONDS.toMillis(6));
assertThat(expire).isGreaterThan(TimeUnit.MILLISECONDS.toMillis(1));
}

@ParameterizedRedisTest // GH-2084
void testSetIfPresentWithoutKeepTtl() {

K key = keyFactory.instance();
V value1 = valueFactory.instance();
V value2 = valueFactory.instance();

assertThat(valueOps.setIfPresent(key, value1, false)).isFalse();
valueOps.set(key, value1, Duration.ofMillis(5500));

assertThat(valueOps.setIfPresent(key, value2, false)).isTrue();
assertThat(valueOps.get(key)).isEqualTo(value2);
assertThat(redisTemplate.getExpire(key)).isEqualTo(-1);
}

@ParameterizedRedisTest
void testSize() {

Expand Down
Loading