DATAREDIS-645 - Introduce absent values in ReactiveStringCommands.

We now return AbsentByteBufferResponse to indicate absence of a Redis key when retrieving the key as top-level element. CommandResponse indicates via isPresent its presence or absence of a response value. Omission of absent values can cause a stream with a different response structure compared to the request. Retaining the stream sequence is required for response to request correlation.

GET and GETSET commands use presence of CommandResponse to filter response emission. Both commands return a single element so absence does not interferes with the request structure.

Previously, we just returned an empty byte-array that caused downstream errors deserializing and emitting null values that are prohibited in Reactive Streams.

Original Pull Request: #249
This commit is contained in:
Mark Paluch
2017-05-11 13:08:22 +02:00
committed by Christoph Strobl
parent 18a6440e98
commit d6ea867e37
5 changed files with 49 additions and 14 deletions

View File

@@ -20,7 +20,11 @@ import static org.hamcrest.core.Is.*;
import static org.hamcrest.core.IsEqual.*;
import static org.hamcrest.core.IsNull.*;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeThat;
import static org.junit.Assume.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.TestSubscriber;
import java.nio.ByteBuffer;
import java.util.Arrays;
@@ -37,14 +41,11 @@ import org.springframework.data.redis.connection.ReactiveRedisConnection.MultiVa
import org.springframework.data.redis.connection.ReactiveStringCommands.SetCommand;
import org.springframework.data.redis.connection.RedisStringCommands.BitOperation;
import org.springframework.data.redis.core.types.Expiration;
import org.springframework.data.redis.test.util.LettuceRedisClientProvider;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.TestSubscriber;
/**
* @author Christoph Strobl
* @author Mark Paluch
*/
public class LettuceReactiveStringCommandsTests extends LettuceReactiveCommandsTestsBase {
@@ -59,14 +60,13 @@ public class LettuceReactiveStringCommandsTests extends LettuceReactiveCommandsT
assertThat(nativeCommands.get(KEY_1), is(equalTo(VALUE_2)));
}
@Test // DATAREDIS-525
@Test // DATAREDIS-525, DATAREDIS-645
public void getSetShouldReturnPreviousValueCorrectlyWhenNoExists() {
Mono<ByteBuffer> result = connection.stringCommands().getSet(KEY_1_BBUFFER, VALUE_2_BBUFFER);
ByteBuffer value = result.block();
assertThat(value, is(notNullValue()));
assertThat(value, is(equalTo(ByteBuffer.allocate(0))));
assertThat(value, is(nullValue()));
assertThat(nativeCommands.get(KEY_1), is(equalTo(VALUE_2)));
}
@@ -104,11 +104,11 @@ public class LettuceReactiveStringCommandsTests extends LettuceReactiveCommandsT
assertThat(result.block(), is(equalTo(VALUE_1_BBUFFER)));
}
@Test // DATAREDIS-525
@Test // DATAREDIS-525, DATAREDIS-645
public void getShouldRetriveNullValueCorrectly() {
Mono<ByteBuffer> result = connection.stringCommands().get(KEY_1_BBUFFER);
assertThat(result.block(), is(equalTo(ByteBuffer.allocate(0))));
assertThat(result.block(), is(nullValue()));
}
@Test // DATAREDIS-525

View File

@@ -195,6 +195,8 @@ public class DefaultReactiveValueOperationsIntegrationTests<K, V> {
K key = keyFactory.instance();
V value = valueFactory.instance();
StepVerifier.create(valueOperations.get(key)).verifyComplete();
StepVerifier.create(valueOperations.set(key, value)).expectNext(true).verifyComplete();
StepVerifier.create(valueOperations.get(key)).expectNext(value).verifyComplete();
@@ -207,6 +209,8 @@ public class DefaultReactiveValueOperationsIntegrationTests<K, V> {
V value = valueFactory.instance();
V nextValue = valueFactory.instance();
StepVerifier.create(valueOperations.getAndSet(key, nextValue)).verifyComplete();
StepVerifier.create(valueOperations.set(key, value)).expectNext(true).verifyComplete();
StepVerifier.create(valueOperations.getAndSet(key, nextValue)).expectNext(value).verifyComplete();