diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveStringCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveStringCommands.java index 1bce0b224..3c1bfc8ee 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveStringCommands.java @@ -195,9 +195,9 @@ public interface ReactiveStringCommands { Flux> set(Publisher commands); /** - * Set {@literal value} for {@literal key} with {@literal expiration} and {@literal options}. Return the old - * string stored at key, or nil if key did not exist. An error is returned and SET aborted if the value - * stored at key is not a string. + * Set {@literal value} for {@literal key} with {@literal expiration} and {@literal options}. Return the old string + * stored at key, or empty if key did not exist. An error is returned and SET aborted if the value stored at key is + * not a string. * * @param key must not be {@literal null}. * @param value must not be {@literal null}. @@ -206,7 +206,7 @@ public interface ReactiveStringCommands { * @param option must not be {@literal null}. * @return * @see Redis Documentation: SET - * @since 3.4 + * @since 3.5 */ @Nullable default Mono setGet(ByteBuffer key, ByteBuffer value, Expiration expiration, SetOption option) { @@ -219,13 +219,13 @@ public interface ReactiveStringCommands { } /** - * Set each and every item separately by invoking {@link SetCommand}. Return the old - * string stored at key, or nil if key did not exist. An error is returned and SET aborted if the value - * stored at key is not a string. + * Set each and every item separately by invoking {@link SetCommand}. Return the old string stored at key, or empty if + * key did not exist. An error is returned and SET aborted if the value stored at key is not a string. * * @param commands must not be {@literal null}. * @return {@link Flux} of {@link ByteBufferResponse} holding the {@link SetCommand} along with the command result. * @see Redis Documentation: SET + * @since 3.5 */ Flux> setGet(Publisher commands); diff --git a/src/main/java/org/springframework/data/redis/connection/RedisStringCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisStringCommands.java index 39ce9f2fd..f591be424 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisStringCommands.java @@ -29,6 +29,7 @@ import org.springframework.lang.Nullable; * @author Costin Leau * @author Christoph Strobl * @author Mark Paluch + * @author Marcin Grzejszczak */ public interface RedisStringCommands { @@ -123,16 +124,16 @@ public interface RedisStringCommands { Boolean set(byte[] key, byte[] value, Expiration expiration, SetOption option); /** - * Set {@code value} for {@code key}. Return the old string stored at key, or nil if key did not exist. - * An error is returned and SET aborted if the value stored at key is not a string. + * Set {@code value} for {@code key}. Return the old string stored at key, or {@literal null} if key did not exist. An + * error is returned and SET aborted if the value stored at key is not a string. * * @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 or * {@link Expiration#keepTtl()} to keep the existing expiration. - * @param option must not be {@literal null}. Use {@link SetOption#upsert()} to add non existing. + * @param option must not be {@literal null}. Use {@link SetOption#upsert()} to add non-existing. * @return {@literal null} when used in pipeline / transaction. - * @since 3.4 + * @since 3.5 * @see Redis Documentation: SET */ @Nullable diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterStringCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterStringCommands.java index 175203971..af51cafe3 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterStringCommands.java @@ -42,6 +42,7 @@ import org.springframework.util.Assert; * @author Mark Paluch * @author Xiaohu Zhang * @author dengliming + * @author Marcin Grzejszczak * @since 2.0 */ class JedisClusterStringCommands implements RedisStringCommands { diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisStringCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisStringCommands.java index 088c71c36..392591e36 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisStringCommands.java @@ -35,6 +35,7 @@ import org.springframework.util.Assert; * @author Christoph Strobl * @author Mark Paluch * @author dengliming + * @author Marcin Grzejszczak * @since 2.0 */ class JedisStringCommands implements RedisStringCommands { @@ -119,6 +120,7 @@ class JedisStringCommands implements RedisStringCommands { @Override @Nullable public byte[] setGet(byte[] key, byte[] value, Expiration expiration, SetOption option) { + Assert.notNull(key, "Key must not be null"); Assert.notNull(value, "Value must not be null"); Assert.notNull(expiration, "Expiration must not be null"); diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommands.java index 08d2972b5..9bb93f398 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommands.java @@ -48,6 +48,7 @@ import org.springframework.util.Assert; * @author Jiahe Cai * @author Michele Mancioppi * @author John Blum + * @author Marcin Grzejszczak * @since 2.0 */ class LettuceReactiveStringCommands implements ReactiveStringCommands { @@ -107,6 +108,7 @@ class LettuceReactiveStringCommands implements ReactiveStringCommands { @Override public Flux> setGet(Publisher commands) { + return this.connection.execute(reactiveCommands -> Flux.from(commands).concatMap((command) -> { Assert.notNull(command.getKey(), "Key must not be null"); diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceStringCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceStringCommands.java index c4c38a41e..5dad73a71 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceStringCommands.java @@ -36,6 +36,7 @@ import org.springframework.util.Assert; * @author Mark Paluch * @author dengliming * @author John Blum + * @author Marcin Grzejszczak * @since 2.0 */ class LettuceStringCommands implements RedisStringCommands { @@ -118,6 +119,7 @@ class LettuceStringCommands implements RedisStringCommands { @Override @Nullable public byte[] setGet(byte[] key, byte[] value, Expiration expiration, SetOption option) { + Assert.notNull(key, "Key must not be null"); Assert.notNull(value, "Value must not be null"); Assert.notNull(expiration, "Expiration must not be null"); diff --git a/src/main/java/org/springframework/data/redis/core/BoundValueOperations.java b/src/main/java/org/springframework/data/redis/core/BoundValueOperations.java index 53b873334..429b053ff 100644 --- a/src/main/java/org/springframework/data/redis/core/BoundValueOperations.java +++ b/src/main/java/org/springframework/data/redis/core/BoundValueOperations.java @@ -28,6 +28,7 @@ import org.springframework.util.Assert; * @author Mark Paluch * @author Jiahe Cai * @author Christoph Strobl + * @author Marcin Grzejszczak */ public interface BoundValueOperations extends BoundKeyOperations { @@ -50,18 +51,32 @@ public interface BoundValueOperations extends BoundKeyOperations { void set(V value, long timeout, TimeUnit unit); /** - * Set the {@code value} and expiration {@code timeout} for the bound key. Return the old - * string stored at key, or nil if key did not exist. An error is returned and SET aborted if the value - * stored at key is not a string. + * Set the {@code value} and expiration {@code timeout} for the bound key. Return the old string stored at key, or + * {@literal null} if key did not exist. An error is returned and SET aborted if the value stored at key is not a + * string. * * @param value must not be {@literal null}. * @param timeout * @param unit must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SET - * @since 3.4 + * @since 3.5 */ V setGet(V value, long timeout, TimeUnit unit); + /** + * Set the {@code value} and expiration {@code timeout} for the bound key. Return the old string stored at key, or + * {@literal null} if key did not exist. An error is returned and SET aborted if the value stored at key is not a + * string. + * + * @param value must not be {@literal null}. + * @param duration expiration duration + * @return {@literal null} when used in pipeline / transaction. + * @see Redis Documentation: SET + * @since 3.5 + */ + V setGet(V value, Duration duration); + /** * Set the {@code value} and expiration {@code timeout} for the bound key. * diff --git a/src/main/java/org/springframework/data/redis/core/DefaultValueOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultValueOperations.java index b20e570f0..357dda961 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultValueOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultValueOperations.java @@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit; import org.springframework.data.redis.connection.BitFieldSubCommands; import org.springframework.data.redis.connection.DefaultedRedisConnection; +import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisStringCommands.SetOption; import org.springframework.data.redis.core.types.Expiration; import org.springframework.lang.Nullable; @@ -219,8 +220,9 @@ class DefaultValueOperations extends AbstractOperations implements V } private V doSetGet(K key, V value, Expiration duration) { + byte[] rawValue = rawValue(value); - return execute( new ValueDeserializingRedisCallback(key) { + return execute(new ValueDeserializingRedisCallback(key) { @Override protected byte[] inRedis(byte[] rawKey, RedisConnection connection) { diff --git a/src/main/java/org/springframework/data/redis/core/ReactiveValueOperations.java b/src/main/java/org/springframework/data/redis/core/ReactiveValueOperations.java index 3eab4929d..9eff05200 100644 --- a/src/main/java/org/springframework/data/redis/core/ReactiveValueOperations.java +++ b/src/main/java/org/springframework/data/redis/core/ReactiveValueOperations.java @@ -59,14 +59,14 @@ public interface ReactiveValueOperations { Mono set(K key, V value, Duration timeout); /** - * Set the {@code value} and expiration {@code timeout} for {@code key}. Return the old - * string stored at key, or nil if key did not exist. An error is returned and SET aborted if the value - * stored at key is not a string. + * Set the {@code value} and expiration {@code timeout} for {@code key}. Return the old string stored at key, or empty + * if key did not exist. An error is returned and SET aborted if the value stored at key is not a string. * * @param key must not be {@literal null}. * @param value * @param timeout must not be {@literal null}. * @see Redis Documentation: SETEX + * @since 3.5 */ Mono setGet(K key, V value, Duration timeout); diff --git a/src/main/java/org/springframework/data/redis/core/ValueOperations.java b/src/main/java/org/springframework/data/redis/core/ValueOperations.java index ac4ac84ad..84ce00f38 100644 --- a/src/main/java/org/springframework/data/redis/core/ValueOperations.java +++ b/src/main/java/org/springframework/data/redis/core/ValueOperations.java @@ -46,29 +46,31 @@ public interface ValueOperations { void set(K key, V value); /** - * Set the {@code value} and expiration {@code timeout} for {@code key}. Return the old - * string stored at key, or nil if key did not exist. An error is returned and SET aborted if the value - * stored at key is not a string. + * Set the {@code value} and expiration {@code timeout} for {@code key}. Return the old string stored at key, or + * {@literal null} if key did not exist. An error is returned and SET aborted if the value stored at key is not a + * string. * * @param key must not be {@literal null}. * @param value must not be {@literal null}. * @param timeout the key expiration timeout. * @param unit must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SET - * @since 3.4 + * @since 3.5 */ V setGet(K key, V value, long timeout, TimeUnit unit); /** - * Set the {@code value} and expiration {@code timeout} for {@code key}. Return the old - * string stored at key, or nil if key did not exist. An error is returned and SET aborted if the value - * stored at key is not a string. + * Set the {@code value} and expiration {@code timeout} for {@code key}. Return the old string stored at key, or + * {@literal null} if key did not exist. An error is returned and SET aborted if the value stored at key is not a + * string. * * @param key must not be {@literal null}. * @param value must not be {@literal null}. * @param duration expiration duration + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SET - * @since 3.4 + * @since 3.5 */ V setGet(K key, V value, Duration duration); diff --git a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommandsIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommandsIntegrationTests.java index 1bb099161..530ec229b 100644 --- a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommandsIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommandsIntegrationTests.java @@ -559,6 +559,7 @@ public class LettuceReactiveStringCommandsIntegrationTests extends LettuceReacti @ParameterizedRedisTest // GH-2853 void setGetMono() { + nativeCommands.set(KEY_1, VALUE_1); connection.stringCommands().setGet(KEY_1_BBUFFER, VALUE_2_BBUFFER, Expiration.keepTtl(), SetOption.upsert()) @@ -571,6 +572,7 @@ public class LettuceReactiveStringCommandsIntegrationTests extends LettuceReacti @ParameterizedRedisTest // GH-2853 void setGetFlux() { + nativeCommands.set(KEY_1, VALUE_1); connection.stringCommands().setGet(Mono.just(SetCommand.set(KEY_1_BBUFFER).value(VALUE_2_BBUFFER).expiring(Expiration.keepTtl()).withSetOption( SetOption.upsert()))) @@ -581,4 +583,5 @@ public class LettuceReactiveStringCommandsIntegrationTests extends LettuceReacti assertThat(nativeCommands.get(KEY_1)).isEqualTo(VALUE_2); } + }