From 3576bbfa8c29c792b0ad1e4e15c8bd6ad820dc43 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 13 Sep 2022 15:11:41 +0200 Subject: [PATCH] Return null elements for absent keys using reactive MGET. We now use correctly null to indicate absent keys when using reactive MGET. Previously, we used an empty byte buffer that could be incorrectly translated to an empty string when using the string codec. An empty byte buffer can also be returned if the value length is zero leading to a state that doesn't allow distinguishing between absence and empty value. Closes #2402 --- .../lettuce/LettuceReactiveStringCommands.java | 15 ++++++++------- ...uceReactiveStringCommandsIntegrationTests.java | 2 +- ...ltReactiveValueOperationsIntegrationTests.java | 7 ------- 3 files changed, 9 insertions(+), 15 deletions(-) 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 aad56435d..7f1ea6c01 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 @@ -17,11 +17,13 @@ package org.springframework.data.redis.connection.lettuce; import io.lettuce.core.BitFieldArgs; import io.lettuce.core.GetExArgs; +import io.lettuce.core.KeyValue; import io.lettuce.core.SetArgs; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -47,8 +49,6 @@ import org.springframework.util.Assert; */ class LettuceReactiveStringCommands implements ReactiveStringCommands { - private static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.wrap(new byte[0]); - private final LettuceReactiveRedisConnection connection; /** @@ -70,8 +70,9 @@ class LettuceReactiveStringCommands implements ReactiveStringCommands { Assert.notNull(keys, "Keys must not be null"); - return cmd.mget(keys.toArray(new ByteBuffer[0])).map((value) -> value.getValueOrElse(EMPTY_BYTE_BUFFER)) - .collectList().map((values) -> new MultiValueResponse<>(keys, values)); + return cmd.mget(keys.toArray(new ByteBuffer[0])).collectList().map((value) -> { + return value.stream().map(keyValue -> keyValue.getValueOrElse(null)).collect(Collectors.toList()); + }).map((values) -> new MultiValueResponse<>(keys, values)); })); } @@ -295,9 +296,9 @@ class LettuceReactiveStringCommands implements ReactiveStringCommands { Range range = command.getRange(); - return (!Range.unbounded().equals(range) ? cmd.bitcount(command.getKey(), - LettuceConverters.getLowerBoundIndex(range), // - LettuceConverters.getUpperBoundIndex(range)) // + return (!Range.unbounded().equals(range) + ? cmd.bitcount(command.getKey(), LettuceConverters.getLowerBoundIndex(range), // + LettuceConverters.getUpperBoundIndex(range)) // : cmd.bitcount(command.getKey())).map(responseValue -> new NumericResponse<>(command, responseValue)); })); } 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 ce238e2b4..8a382b4ea 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 @@ -202,7 +202,7 @@ public class LettuceReactiveStringCommandsIntegrationTests extends LettuceReacti Mono> result = connection.stringCommands() .mGet(Arrays.asList(KEY_1_BBUFFER, KEY_2_BBUFFER, KEY_3_BBUFFER)); - assertThat(result.block()).containsExactly(VALUE_1_BBUFFER, ByteBuffer.allocate(0), VALUE_3_BBUFFER); + assertThat(result.block()).containsExactly(VALUE_1_BBUFFER, null, VALUE_3_BBUFFER); } @ParameterizedRedisTest // DATAREDIS-525 diff --git a/src/test/java/org/springframework/data/redis/core/DefaultReactiveValueOperationsIntegrationTests.java b/src/test/java/org/springframework/data/redis/core/DefaultReactiveValueOperationsIntegrationTests.java index b05deaa38..617de44fd 100644 --- a/src/test/java/org/springframework/data/redis/core/DefaultReactiveValueOperationsIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/core/DefaultReactiveValueOperationsIntegrationTests.java @@ -306,13 +306,6 @@ public class DefaultReactiveValueOperationsIntegrationTests { V value2 = valueFactory.instance(); V absentValue = null; - if (serializer instanceof StringRedisSerializer) { - absentValue = (V) ""; - } - if (value1 instanceof ByteBuffer) { - absentValue = (V) ByteBuffer.wrap(new byte[0]); - } - Map map = new LinkedHashMap<>(); map.put(key1, value1); map.put(key2, value2);