DATAREDIS-1119 - Support XINFO via ReactiveStreamCommands.
Original pull request: #519.
This commit is contained in:
committed by
Mark Paluch
parent
c010472c42
commit
3f5533ea9a
@@ -41,6 +41,9 @@ import org.springframework.data.redis.connection.stream.PendingMessages;
|
||||
import org.springframework.data.redis.connection.stream.PendingMessagesSummary;
|
||||
import org.springframework.data.redis.connection.stream.ReadOffset;
|
||||
import org.springframework.data.redis.connection.stream.RecordId;
|
||||
import org.springframework.data.redis.connection.stream.StreamInfo.XInfoConsumer;
|
||||
import org.springframework.data.redis.connection.stream.StreamInfo.XInfoGroup;
|
||||
import org.springframework.data.redis.connection.stream.StreamInfo.XInfoStream;
|
||||
import org.springframework.data.redis.connection.stream.StreamOffset;
|
||||
import org.springframework.data.redis.connection.stream.StreamReadOptions;
|
||||
import org.springframework.data.redis.connection.stream.StreamRecords;
|
||||
@@ -1030,6 +1033,101 @@ public interface ReactiveStreamCommands {
|
||||
*/
|
||||
Flux<CommandResponse<ReadCommand, Flux<ByteBufferRecord>>> read(Publisher<ReadCommand> commands);
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.3
|
||||
*/
|
||||
class XInfoCommand extends KeyCommand {
|
||||
|
||||
private final @Nullable String groupName;
|
||||
|
||||
public XInfoCommand(@Nullable ByteBuffer key, @Nullable String groupName) {
|
||||
|
||||
super(key);
|
||||
this.groupName = groupName;
|
||||
}
|
||||
|
||||
public static XInfoCommand xInfo() {
|
||||
return new XInfoCommand(null, null);
|
||||
}
|
||||
|
||||
public XInfoCommand of(ByteBuffer key) {
|
||||
return new XInfoCommand(key, groupName);
|
||||
}
|
||||
|
||||
public XInfoCommand consumersIn(String groupName) {
|
||||
return new XInfoCommand(getKey(), groupName);
|
||||
}
|
||||
|
||||
public String getGroupName() {
|
||||
return groupName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain general information about the stream stored at the specified {@literal key}.
|
||||
*
|
||||
* @param key the {@literal key} the stream is stored at.
|
||||
* @return a {@link Mono} emitting {@link XInfoStream} when ready.
|
||||
* @since 2.3
|
||||
*/
|
||||
default Mono<XInfoStream> xInfo(ByteBuffer key) {
|
||||
return xInfo(Mono.just(XInfoCommand.xInfo().of(key))).next().map(CommandResponse::getOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain general information about the stream stored at the specified {@literal key}.
|
||||
*
|
||||
* @param commands must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @since 2.3
|
||||
*/
|
||||
Flux<CommandResponse<XInfoCommand, XInfoStream>> xInfo(Publisher<XInfoCommand> commands);
|
||||
|
||||
/**
|
||||
* Obtain general information about the stream stored at the specified {@literal key}.
|
||||
*
|
||||
* @param key the {@literal key} the stream is stored at.
|
||||
* @return a {@link Flux} emitting consumer group info one by one.
|
||||
* @since 2.3
|
||||
*/
|
||||
default Flux<XInfoGroup> xInfoGroups(ByteBuffer key) {
|
||||
return xInfoGroups(Mono.just(XInfoCommand.xInfo().of(key))).next().flatMapMany(CommandResponse::getOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain general information about the stream stored at the specified {@literal key}.
|
||||
*
|
||||
* @param commands must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @since 2.3
|
||||
*/
|
||||
Flux<CommandResponse<XInfoCommand, Flux<XInfoGroup>>> xInfoGroups(Publisher<XInfoCommand> commands);
|
||||
|
||||
/**
|
||||
* Obtain information about every consumer in a specific {@literal consumer group} for the stream stored at the
|
||||
* specified {@literal key}.
|
||||
*
|
||||
* @param key the {@literal key} the stream is stored at.
|
||||
* @param groupName name of the {@literal consumer group}.
|
||||
* @return a {@link Flux} emitting consumer info one by one.
|
||||
* @since 2.3
|
||||
*/
|
||||
default Flux<XInfoConsumer> xInfoConsumers(ByteBuffer key, String groupName) {
|
||||
return xInfoConsumers(Mono.just(XInfoCommand.xInfo().of(key).consumersIn(groupName))).next()
|
||||
.flatMapMany(CommandResponse::getOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain information about every consumer in a specific {@literal consumer group} for the stream stored at the
|
||||
* specified {@literal key}.
|
||||
*
|
||||
* @param commands must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @since 2.3
|
||||
*/
|
||||
Flux<CommandResponse<XInfoCommand, Flux<XInfoConsumer>>> xInfoConsumers(Publisher<XInfoCommand> commands);
|
||||
|
||||
class GroupCommand extends KeyCommand {
|
||||
|
||||
private final GroupCommandAction action;
|
||||
|
||||
@@ -20,6 +20,7 @@ import io.lettuce.core.XClaimArgs;
|
||||
import io.lettuce.core.XReadArgs;
|
||||
import io.lettuce.core.XReadArgs.StreamOffset;
|
||||
import io.lettuce.core.cluster.api.reactive.RedisClusterReactiveCommands;
|
||||
import org.springframework.data.redis.connection.stream.StreamInfo.XInfoConsumer;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -39,6 +40,8 @@ import org.springframework.data.redis.connection.stream.Consumer;
|
||||
import org.springframework.data.redis.connection.stream.PendingMessages;
|
||||
import org.springframework.data.redis.connection.stream.PendingMessagesSummary;
|
||||
import org.springframework.data.redis.connection.stream.RecordId;
|
||||
import org.springframework.data.redis.connection.stream.StreamInfo.XInfoGroup;
|
||||
import org.springframework.data.redis.connection.stream.StreamInfo.XInfoStream;
|
||||
import org.springframework.data.redis.connection.stream.StreamReadOptions;
|
||||
import org.springframework.data.redis.connection.stream.StreamRecords;
|
||||
import org.springframework.data.redis.util.ByteUtils;
|
||||
@@ -344,6 +347,41 @@ class LettuceReactiveStreamCommands implements ReactiveStreamCommands {
|
||||
.map(it -> StreamRecords.newRecord().in(it.getStream()).withId(it.getId()).ofBuffer(it.getBody()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<CommandResponse<XInfoCommand, XInfoStream>> xInfo(Publisher<XInfoCommand> commands) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(commands).flatMap(command -> {
|
||||
|
||||
Assert.notNull(command.getKey(), "Key must not be null!");
|
||||
|
||||
return cmd.xinfoStream(command.getKey()).collectList().map(XInfoStream::fromList)
|
||||
.map(it -> new CommandResponse<>(command, it));
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<CommandResponse<XInfoCommand, Flux<XInfoGroup>>> xInfoGroups(Publisher<XInfoCommand> commands) {
|
||||
return connection.execute(cmd -> Flux.from(commands).map(command -> {
|
||||
|
||||
Assert.notNull(command.getKey(), "Key must not be null!");
|
||||
|
||||
return new CommandResponse(command, cmd.xinfoGroups(command.getKey()).map(it -> XInfoGroup.fromList((List<Object>) it)));
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<CommandResponse<XInfoCommand, Flux<XInfoConsumer>>> xInfoConsumers(Publisher<XInfoCommand> commands) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(commands).map(command -> {
|
||||
|
||||
Assert.notNull(command.getKey(), "Key must not be null!");
|
||||
|
||||
ByteBuffer groupName = ByteUtils.getByteBuffer(command.getGroupName());
|
||||
return new CommandResponse(command, cmd.xinfoConsumers(command.getKey(), groupName).map(it -> new XInfoConsumer(command.getGroupName(), (List<Object>) it)));
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveStreamCommands#xRevRange(org.reactivestreams.Publisher)
|
||||
|
||||
@@ -315,6 +315,10 @@ public class StreamInfo {
|
||||
private XInfoGroup(List<Object> raw) {
|
||||
super(raw, DEFAULT_TYPE_HINTS);
|
||||
}
|
||||
|
||||
public static XInfoGroup fromList(List<Object> raw) {
|
||||
return new XInfoGroup(raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@literal consumer group} name. Corresponds to {@literal name}.
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.redis.core;
|
||||
|
||||
import org.springframework.data.redis.connection.stream.PendingMessages;
|
||||
import org.springframework.data.redis.connection.stream.PendingMessagesSummary;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -36,9 +34,14 @@ import org.springframework.data.redis.connection.RedisZSetCommands.Limit;
|
||||
import org.springframework.data.redis.connection.stream.ByteBufferRecord;
|
||||
import org.springframework.data.redis.connection.stream.Consumer;
|
||||
import org.springframework.data.redis.connection.stream.MapRecord;
|
||||
import org.springframework.data.redis.connection.stream.PendingMessages;
|
||||
import org.springframework.data.redis.connection.stream.PendingMessagesSummary;
|
||||
import org.springframework.data.redis.connection.stream.ReadOffset;
|
||||
import org.springframework.data.redis.connection.stream.Record;
|
||||
import org.springframework.data.redis.connection.stream.RecordId;
|
||||
import org.springframework.data.redis.connection.stream.StreamInfo.XInfoConsumer;
|
||||
import org.springframework.data.redis.connection.stream.StreamInfo.XInfoGroup;
|
||||
import org.springframework.data.redis.connection.stream.StreamInfo.XInfoStream;
|
||||
import org.springframework.data.redis.connection.stream.StreamOffset;
|
||||
import org.springframework.data.redis.connection.stream.StreamReadOptions;
|
||||
import org.springframework.data.redis.hash.HashMapper;
|
||||
@@ -185,6 +188,43 @@ class DefaultReactiveStreamOperations<K, HK, HV> implements ReactiveStreamOperat
|
||||
return createMono(connection -> connection.xGroupDestroy(rawKey(key), group));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveStreamOperations#consumers(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Flux<XInfoConsumer> consumers(K key, String group) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(group, "Group must not be null!");
|
||||
|
||||
return createFlux(connection -> connection.xInfoConsumers(rawKey(key), group));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveStreamOperations#info(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Mono<XInfoStream> info(K key) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
return createMono(connection -> connection.xInfo(rawKey(key)));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveStreamOperations#groups(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Flux<XInfoGroup> groups(K key) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
return createFlux(connection -> connection.xInfoGroups(rawKey(key)));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.StreamOperations#pending(java.lang.Object, java.lang.String, org.springframework.data.domain.Range, java.lang.Long)
|
||||
@@ -218,7 +258,6 @@ class DefaultReactiveStreamOperations<K, HK, HV> implements ReactiveStreamOperat
|
||||
return createMono(connection -> connection.xPending(rawKey, group));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveStreamOperations#size(java.lang.Object)
|
||||
|
||||
@@ -25,6 +25,9 @@ import org.reactivestreams.Publisher;
|
||||
import org.springframework.data.domain.Range;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Limit;
|
||||
import org.springframework.data.redis.connection.stream.*;
|
||||
import org.springframework.data.redis.connection.stream.StreamInfo.XInfoConsumer;
|
||||
import org.springframework.data.redis.connection.stream.StreamInfo.XInfoGroup;
|
||||
import org.springframework.data.redis.connection.stream.StreamInfo.XInfoStream;
|
||||
import org.springframework.data.redis.hash.HashMapper;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -194,6 +197,36 @@ public interface ReactiveStreamOperations<K, HK, HV> extends HashMapperProvider<
|
||||
*/
|
||||
Mono<String> destroyGroup(K key, String group);
|
||||
|
||||
/**
|
||||
* Obtain information about every consumer in a specific {@literal consumer group} for the stream stored at the
|
||||
* specified {@literal key}.
|
||||
*
|
||||
* @param key the {@literal key} the stream is stored at.
|
||||
* @param group name of the {@literal consumer group}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.3
|
||||
*/
|
||||
Flux<XInfoConsumer> consumers(K key, String group);
|
||||
|
||||
/**
|
||||
* Obtain information about {@literal consumer groups} associated with the stream stored at the specified
|
||||
* {@literal key}.
|
||||
*
|
||||
* @param key the {@literal key} the stream is stored at.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.3
|
||||
*/
|
||||
Flux<XInfoGroup> groups(K key);
|
||||
|
||||
/**
|
||||
* Obtain general information about the stream stored at the specified {@literal key}.
|
||||
*
|
||||
* @param key the {@literal key} the stream is stored at.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.3
|
||||
*/
|
||||
Mono<XInfoStream> info(K key);
|
||||
|
||||
/**
|
||||
* Obtain the {@link PendingMessagesSummary} for a given {@literal consumer group}.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user