DATAREDIS-1042 - Allow consumer group creation without an existing stream.

Original pull request: #527.
This commit is contained in:
Tugdual Grall
2020-05-03 17:32:22 +02:00
committed by Mark Paluch
parent c4623ef059
commit d7b8d9b018
17 changed files with 260 additions and 13 deletions

View File

@@ -98,6 +98,7 @@ import org.springframework.test.annotation.ProfileValueSourceConfiguration;
* @author Christoph Strobl
* @author Thomas Darimont
* @author Mark Paluch
* @author Tugdual Grall
*/
@ProfileValueSourceConfiguration(RedisTestProfileValueSource.class)
public abstract class AbstractConnectionIntegrationTests {
@@ -3058,6 +3059,29 @@ public abstract class AbstractConnectionIntegrationTests {
assertThat((List<MapRecord>) results.get(3)).isEmpty();
}
@Test // DATAREDIS-864
@IfProfileValue(name = "redisVersion", value = "5.0")
@WithRedisDriver({ RedisDriver.LETTUCE })
public void xGroupCreateShouldWorkWithAndWithoutExistingStream() {
actual.add(connection.xGroupCreate(KEY_1, ReadOffset.from("0"), "my-group",true));
actual.add(connection.xAdd(KEY_1, Collections.singletonMap(KEY_2, VALUE_2)));
actual.add(connection.xReadGroupAsString(Consumer.from("my-group", "my-consumer"),
StreamOffset.create(KEY_1, ReadOffset.lastConsumed())));
actual.add(connection.xReadGroupAsString(Consumer.from("my-group", "my-consumer"),
StreamOffset.create(KEY_1, ReadOffset.lastConsumed())));
List<Object> results = getResults();
List<MapRecord<String, String, String>> messages = (List) results.get(2);
assertThat(messages.get(0).getStream()).isEqualTo(KEY_1);
assertThat(messages.get(0).getValue()).isEqualTo(Collections.singletonMap(KEY_2, VALUE_2));
assertThat((List<MapRecord>) results.get(3)).isEmpty();
}
@Test // DATAREDIS-864
@IfProfileValue(name = "redisVersion", value = "5.0")
@WithRedisDriver({ RedisDriver.LETTUCE })
@@ -3252,6 +3276,7 @@ public abstract class AbstractConnectionIntegrationTests {
@WithRedisDriver({ RedisDriver.LETTUCE })
public void xinfo() {
actual.add(connection.xGroupCreate(KEY_1, ReadOffset.from("0"), "my-group-without-stream",true));
actual.add(connection.xAdd(KEY_1, Collections.singletonMap(KEY_2, VALUE_2)));
actual.add(connection.xAdd(KEY_1, Collections.singletonMap(KEY_3, VALUE_3)));
actual.add(connection.xGroupCreate(KEY_1, ReadOffset.from("0"), "my-group"));
@@ -3261,15 +3286,15 @@ public abstract class AbstractConnectionIntegrationTests {
actual.add(connection.xInfo(KEY_1));
List<Object> results = getResults();
assertThat(results).hasSize(5);
RecordId firstRecord = (RecordId) results.get(0);
RecordId lastRecord = (RecordId) results.get(1);
XInfoStream info = (XInfoStream) results.get(4);
assertThat(results).hasSize(6);
RecordId firstRecord = (RecordId) results.get(1);
RecordId lastRecord = (RecordId) results.get(2);
XInfoStream info = (XInfoStream) results.get(5);
assertThat(info.streamLength()).isEqualTo(2L);
assertThat(info.radixTreeKeySize()).isOne();
assertThat(info.radixTreeNodesSize()).isEqualTo(2L);
assertThat(info.groupCount()).isOne();
assertThat(info.groupCount()).isEqualTo(2L);
assertThat(info.lastGeneratedId()).isEqualTo(lastRecord.getValue());
assertThat(info.firstEntryId()).isEqualTo(firstRecord.getValue());
assertThat(info.lastEntryId()).isEqualTo(lastRecord.getValue());

View File

@@ -19,6 +19,7 @@ import static org.assertj.core.api.Assertions.*;
import static org.junit.Assume.*;
import io.lettuce.core.XReadArgs;
import org.springframework.data.redis.RedisSystemException;
import reactor.test.StepVerifier;
import java.time.Duration;
@@ -42,6 +43,7 @@ import org.springframework.data.redis.connection.stream.StreamOffset;
*
* @author Mark Paluch
* @author Christoph Strobl
* @author Tugdual Grall
*/
public class LettuceReactiveStreamCommandsTests extends LettuceReactiveCommandsTestsBase {
@@ -188,6 +190,19 @@ public class LettuceReactiveStreamCommandsTests extends LettuceReactiveCommandsT
.verifyComplete();
}
@Test // DATAREDIS-864
public void xGroupCreateShouldCreateGroupBeforeStream() {
connection.streamCommands().xGroupCreate(KEY_1_BBUFFER, "group-1", ReadOffset.latest(), false)
.as(StepVerifier::create) //
.expectError(RedisSystemException.class) //
.verify();
connection.streamCommands().xGroupCreate(KEY_1_BBUFFER, "group-1", ReadOffset.latest(), true) //
.as(StepVerifier::create) //
.expectNext("OK") //
.verifyComplete();
}
@Test // DATAREDIS-864
@Ignore("commands sent correctly - however lettuce returns false")
public void xGroupDelConsumerShouldRemoveConsumer() {

View File

@@ -55,6 +55,7 @@ import org.springframework.data.redis.stream.StreamReceiver.StreamReceiverOption
* Integration tests for {@link StreamReceiver}.
*
* @author Mark Paluch
* @author Tugdual Grall
*/
public class StreamReceiverIntegrationTests {
@@ -256,6 +257,31 @@ public class StreamReceiverIntegrationTests {
.verify(Duration.ofSeconds(5));
}
@Test // DATAREDIS-864
public void shouldCreateGroupWithOrWithoutExistingStream() {
StreamReceiver<String, MapRecord<String, String, String>> receiver = StreamReceiver.create(connectionFactory);
Flux<MapRecord<String, String, String>> messages = receiver.receive(Consumer.from("my-group", "my-consumer-id"),
StreamOffset.create("my-stream", ReadOffset.lastConsumed()));
// required to initialize stream
redisTemplate.opsForStream().createGroup("my-stream", ReadOffset.from("0-0"), "my-group", true);
redisTemplate.opsForStream().add("my-stream", Collections.singletonMap("key", "value"));
redisTemplate.opsForStream().add("my-stream", Collections.singletonMap("key2", "value2"));
messages.as(StepVerifier::create) //
.consumeNextWith(it -> {
assertThat(it.getStream()).isEqualTo("my-stream");
assertThat(it.getValue()).containsValue("value");
}).consumeNextWith(it -> {
assertThat(it.getStream()).isEqualTo("my-stream");
assertThat(it.getValue()).containsValue("value2");
}) //
.thenCancel() //
.verify(Duration.ofSeconds(5));
}
@Data
@AllArgsConstructor
static class LoginEvent {

View File

@@ -27,6 +27,7 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
*
* @author Christoph Strobl
* @author Thomas Darimont
* @author Tugdual Grall
*/
public abstract class RedisClientRule implements TestRule {
@@ -50,7 +51,7 @@ public abstract class RedisClientRule implements TestRule {
return;
}
}
throw new AssumptionViolatedException("not a vaild redis connection for driver: " + redisConnectionFactory);
throw new AssumptionViolatedException("not a valid redis connection for driver: " + redisConnectionFactory);
}
base.evaluate();