Skip to content

Commit

Permalink
DATAREDIS-1103 - Support new KEEPTTL option of the SET operation
Browse files Browse the repository at this point in the history
Original Pull Request: #562
  • Loading branch information
dengliming authored and christophstrobl committed Oct 8, 2020
1 parent 3920890 commit 232c8a5
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
* @author Ninad Divadkar
* @author Tugdual Grall
* @author Andrey Shlykov
* @author dengliming
*/
public class DefaultStringRedisConnection implements StringRedisConnection, DecoratedRedisConnection {

Expand Down Expand Up @@ -992,6 +993,15 @@ public Boolean set(byte[] key, byte[] value, Expiration expiration, SetOption op
return convertAndReturn(delegate.set(key, value, expiration, option), identityConverter);
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisStringCommands#set(byte[], byte[], org.springframework.data.redis.core.types.Expiration, org.springframework.data.redis.connection.RedisStringCommands.SetOptions, boolean)
*/
@Override
public Boolean set(byte[] key, byte[] value, Expiration expiration, SetOption option, boolean keepTtl) {
return convertAndReturn(delegate.set(key, value, expiration, option, keepTtl), identityConverter);
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisStringCommands#setBit(byte[], long, boolean)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,13 @@ default Boolean set(byte[] key, byte[] value, Expiration expiration, SetOption o
return stringCommands().set(key, value, expiration, option);
}

/** @deprecated in favor of {@link RedisConnection#stringCommands()}}. */
@Override
@Deprecated
default Boolean set(byte[] key, byte[] value, Expiration expiration, SetOption option, boolean keepTtl) {
return stringCommands().set(key, value, expiration, option, keepTtl);
}

/** @deprecated in favor of {@link RedisConnection#stringCommands()}}. */
@Override
@Deprecated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,22 @@ enum BitOperation {
@Nullable
Boolean set(byte[] key, byte[] value, Expiration expiration, SetOption option);

/**
* Set {@code value} for {@code key} applying timeouts from {@code expiration} if set and inserting/updating values
* depending on {@code option}.
*
* @param key must not be {@literal null}.
* @param value must not be {@literal null}.
* @param expiration must not be {@literal null}. Use {@link Expiration#persistent()} to not set any ttl.
* @param option must not be {@literal null}. Use {@link SetOption#upsert()} to add non existing.
* @param keepTtl set the value and retain the existing TTL.
* @return {@literal null} when used in pipeline / transaction.
* @since 2.4
* @see <a href="https://redis.io/commands/set">Redis Documentation: SET</a>
*/
@Nullable
Boolean set(byte[] key, byte[] value, Expiration expiration, SetOption option, boolean keepTtl);

/**
* Set {@code value} for {@code key}, only if {@code key} does not exist.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
* @author Christoph Strobl
* @author Mark Paluch
* @author Xiaohu Zhang
* @author dengliming
* @since 2.0
*/
class JedisClusterStringCommands implements RedisStringCommands {
Expand Down Expand Up @@ -126,11 +127,20 @@ public Boolean set(byte[] key, byte[] value) {
*/
@Override
public Boolean set(byte[] key, byte[] value, Expiration expiration, SetOption option) {
return set(key, value, expiration, option, false);
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisStringCommands#set(byte[], byte[], org.springframework.data.redis.core.types.Expiration, org.springframework.data.redis.connection.RedisStringCommands.SetOptions, boolean)
*/
@Override
public Boolean set(byte[] key, byte[] value, Expiration expiration, SetOption option, boolean keepTtl) {
Assert.notNull(key, "Key must not be null!");
Assert.notNull(value, "Value must not be null!");
Assert.notNull(expiration, "Expiration must not be null!");
Assert.notNull(option, "Option must not be null!");
Assert.isTrue(keepTtl, "KEEPTTL is currently not supported in jedis!");

SetParams setParams = JedisConverters.toSetCommandExPxArgument(expiration,
JedisConverters.toSetCommandNxXxArgument(option));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
/**
* @author Christoph Strobl
* @author Mark Paluch
* @author dengliming
* @since 2.0
*/
class JedisStringCommands implements RedisStringCommands {
Expand Down Expand Up @@ -152,11 +153,20 @@ public Boolean set(byte[] key, byte[] value) {
*/
@Override
public Boolean set(byte[] key, byte[] value, Expiration expiration, SetOption option) {
return set(key, value, expiration, option, false);
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisStringCommands#set(byte[], byte[], org.springframework.data.redis.core.types.Expiration, org.springframework.data.redis.connection.RedisStringCommands.SetOption, boolean)
*/
@Override
public Boolean set(byte[] key, byte[] value, Expiration expiration, SetOption option, boolean keepTtl) {
Assert.notNull(key, "Key must not be null!");
Assert.notNull(value, "Value must not be null!");
Assert.notNull(expiration, "Expiration must not be null!");
Assert.notNull(option, "Option must not be null!");
Assert.isTrue(keepTtl, "KEEPTTL is currently not supported in jedis!");

SetParams params = JedisConverters.toSetCommandExPxArgument(expiration,
JedisConverters.toSetCommandNxXxArgument(option));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
* @author Thomas Darimont
* @author Mark Paluch
* @author Ninad Divadkar
* @author dengliming
*/
abstract public class LettuceConverters extends Converters {

Expand Down Expand Up @@ -767,6 +768,18 @@ public static RedisClusterNode toRedisClusterNode(io.lettuce.core.cluster.models
* @since 1.7
*/
public static SetArgs toSetArgs(@Nullable Expiration expiration, @Nullable SetOption option) {
return toSetArgs(expiration, option, false);
}

/**
* Converts a given {@link Expiration} and {@link SetOption} to the according {@link SetArgs}.<br />
*
* @param expiration can be {@literal null}.
* @param option can be {@literal null}.
* @param keepTtl set the value and retain the existing TTL.
* @since 2.4
*/
public static SetArgs toSetArgs(@Nullable Expiration expiration, @Nullable SetOption option, boolean keepTtl) {

SetArgs args = new SetArgs();
if (expiration != null && !expiration.isPersistent()) {
Expand All @@ -781,6 +794,10 @@ public static SetArgs toSetArgs(@Nullable Expiration expiration, @Nullable SetOp
}
}

if (keepTtl) {
args.keepttl();
}

if (option != null) {

switch (option) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
/**
* @author Christoph Strobl
* @author Mark Paluch
* @author dengliming
* @since 2.0
*/
class LettuceStringCommands implements RedisStringCommands {
Expand Down Expand Up @@ -156,7 +157,15 @@ public Boolean set(byte[] key, byte[] value) {
*/
@Override
public Boolean set(byte[] key, byte[] value, Expiration expiration, SetOption option) {
return set(key, value, expiration, option, false);
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisStringCommands#set(byte[], byte[], org.springframework.data.redis.core.types.Expiration, org.springframework.data.redis.connection.RedisStringCommands.SetOption, boolean)
*/
@Override
public Boolean set(byte[] key, byte[] value, Expiration expiration, SetOption option, boolean keepTtl) {
Assert.notNull(key, "Key must not be null!");
Assert.notNull(value, "Value must not be null!");
Assert.notNull(expiration, "Expiration must not be null!");
Expand All @@ -165,18 +174,18 @@ public Boolean set(byte[] key, byte[] value, Expiration expiration, SetOption op
try {
if (isPipelined()) {
pipeline(connection.newLettuceResult(
getAsyncConnection().set(key, value, LettuceConverters.toSetArgs(expiration, option)),
getAsyncConnection().set(key, value, LettuceConverters.toSetArgs(expiration, option, keepTtl)),
Converters.stringToBooleanConverter(), () -> false));
return null;
}
if (isQueueing()) {
transaction(connection.newLettuceResult(
getAsyncConnection().set(key, value, LettuceConverters.toSetArgs(expiration, option)),
getAsyncConnection().set(key, value, LettuceConverters.toSetArgs(expiration, option, keepTtl)),
Converters.stringToBooleanConverter(), () -> false));
return null;
}
return Converters
.stringToBoolean(getConnection().set(key, value, LettuceConverters.toSetArgs(expiration, option)));
.stringToBoolean(getConnection().set(key, value, LettuceConverters.toSetArgs(expiration, option, keepTtl)));
} catch (Exception ex) {
throw convertLettuceAccessException(ex);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package org.springframework.data.redis.connection.lettuce;

import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.data.Offset.offset;
import static org.springframework.data.redis.connection.BitFieldSubCommands.*;
import static org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldIncrBy.Overflow.*;
Expand Down Expand Up @@ -2466,4 +2467,19 @@ public void bitfieldShouldWorkUsingNonZeroBasedOffset() {
.valueAt(BitFieldSubCommands.Offset.offset(1L).multipliedByTypeLength()))).containsExactly(100L,
-56L);
}

@Test // DATAREDIS-1103
public void setKeepTTL() {

long expireSeconds = 10;
assertThat(clusterConnection.setEx(KEY_1_BYTES, expireSeconds, VALUE_2_BYTES));

assertThat(clusterConnection.get(KEY_1_BYTES)).isEqualTo(VALUE_2_BYTES);

assertThat(clusterConnection.set(KEY_1_BYTES, VALUE_2_BYTES, Expiration.persistent(), SetOption.upsert(), true));

long ttl = clusterConnection.ttl(KEY_1_BYTES);

assertThat(0 < ttl && ttl <= expireSeconds);
}
}

0 comments on commit 232c8a5

Please sign in to comment.