org.springframework.data.redis.connection.lettuce.LettuceReactiveStreamCommands Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.servicemix.bundles.spring-data-redis
Show all versions of org.apache.servicemix.bundles.spring-data-redis
This OSGi bundle wraps ${pkgArtifactId} ${pkgVersion} jar files.
/*
* Copyright 2018-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.redis.connection.lettuce;
import io.lettuce.core.XAddArgs;
import io.lettuce.core.XClaimArgs;
import io.lettuce.core.XGroupCreateArgs;
import io.lettuce.core.XReadArgs;
import io.lettuce.core.XReadArgs.StreamOffset;
import io.lettuce.core.cluster.api.reactive.RedisClusterReactiveCommands;
import reactor.core.publisher.Flux;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import org.reactivestreams.Publisher;
import org.springframework.data.redis.connection.ReactiveRedisConnection.CommandResponse;
import org.springframework.data.redis.connection.ReactiveRedisConnection.KeyCommand;
import org.springframework.data.redis.connection.ReactiveRedisConnection.NumericResponse;
import org.springframework.data.redis.connection.ReactiveStreamCommands;
import org.springframework.data.redis.connection.ReactiveStreamCommands.GroupCommand.GroupCommandAction;
import org.springframework.data.redis.connection.stream.ByteBufferRecord;
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.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.StreamReadOptions;
import org.springframework.data.redis.connection.stream.StreamRecords;
import org.springframework.data.redis.util.ByteUtils;
import org.springframework.util.Assert;
/**
* {@link ReactiveStreamCommands} implementation for {@literal Lettuce}.
*
* @author Mark Paluch
* @author Tugdual Grall
* @since 2.2
*/
class LettuceReactiveStreamCommands implements ReactiveStreamCommands {
private final LettuceReactiveRedisConnection connection;
/**
* Create new {@link LettuceReactiveStreamCommands}.
*
* @param connection must not be {@literal null}.
*/
LettuceReactiveStreamCommands(LettuceReactiveRedisConnection connection) {
Assert.notNull(connection, "Connection must not be null!");
this.connection = connection;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.ReactiveStreamCommands#xAck(org.reactivestreams.Publisher)
*/
@Override
public Flux> xAck(Publisher commands) {
return connection.execute(cmd -> Flux.from(commands).concatMap(command -> {
Assert.notNull(command.getKey(), "Key must not be null!");
Assert.notNull(command.getGroup(), "Group must not be null!");
Assert.notNull(command.getRecordIds(), "recordIds must not be null!");
return cmd
.xack(command.getKey(), ByteUtils.getByteBuffer(command.getGroup()), entryIdsToString(command.getRecordIds()))
.map(value -> new NumericResponse<>(command, value));
}));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.ReactiveStreamCommands#xAdd(org.reactivestreams.Publisher)
*/
@Override
public Flux> xAdd(Publisher commands) {
return connection.execute(cmd -> Flux.from(commands).concatMap(command -> {
Assert.notNull(command.getKey(), "Key must not be null!");
Assert.notNull(command.getBody(), "Body must not be null!");
XAddArgs args = new XAddArgs();
if (!command.getRecord().getId().shouldBeAutoGenerated()) {
args.id(command.getRecord().getId().getValue());
}
if (command.hasMaxlen()) {
args.maxlen(command.getMaxlen());
}
return cmd.xadd(command.getKey(), args, command.getBody())
.map(value -> new CommandResponse<>(command, RecordId.of(value)));
}));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.ReactiveStreamCommands#xClaimJustId(byte[], java.lang.String, java.lang.String, org.springframework.data.redis.connection.RedisStreamCommands.XClaimOptions)
*/
@Override
public Flux>> xClaimJustId(Publisher commands) {
if (true /* TODO: set the JUSTID flag */ ) {
throw new UnsupportedOperationException("Lettuce does not support XCLAIM with JUSTID. (Ref: lettuce-io#1233)");
}
return connection.execute(cmd -> Flux.from(commands).map(command -> {
String[] ids = command.getOptions().getIdsAsStringArray();
io.lettuce.core.Consumer from = io.lettuce.core.Consumer
.from(ByteUtils.getByteBuffer(command.getGroupName()), ByteUtils.getByteBuffer(command.getNewOwner()));
XClaimArgs args = StreamConverters.toXClaimArgs(command.getOptions());
Flux result = cmd.xclaim(command.getKey(), from, args, ids).map(it -> RecordId.of(it.getId()));
return new CommandResponse<>(command, result);
}));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.ReactiveStreamCommands#xClaim(byte[], java.lang.String, java.lang.String, org.springframework.data.redis.connection.RedisStreamCommands.XClaimOptions)
*/
@Override
public Flux>> xClaim(Publisher commands) {
return connection.execute(cmd -> Flux.from(commands).map(command -> {
String[] ids = command.getOptions().getIdsAsStringArray();
io.lettuce.core.Consumer from = io.lettuce.core.Consumer
.from(ByteUtils.getByteBuffer(command.getGroupName()), ByteUtils.getByteBuffer(command.getNewOwner()));
XClaimArgs args = StreamConverters.toXClaimArgs(command.getOptions());
Flux result = cmd.xclaim(command.getKey(), from, args, ids)
.map(it -> StreamRecords.newRecord().in(it.getStream()).withId(it.getId()).ofBuffer(it.getBody()));
return new CommandResponse<>(command, result);
}));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.ReactiveStreamCommands#xDel(org.reactivestreams.Publisher)
*/
@Override
public Flux> xDel(Publisher commands) {
return connection.execute(cmd -> Flux.from(commands).concatMap(command -> {
Assert.notNull(command.getKey(), "Key must not be null!");
Assert.notNull(command.getRecordIds(), "recordIds must not be null!");
return cmd.xdel(command.getKey(), entryIdsToString(command.getRecordIds()))
.map(value -> new NumericResponse<>(command, value));
}));
}
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public Flux> xGroup(Publisher commands) {
return connection.execute(cmd -> Flux.from(commands).concatMap(command -> {
Assert.notNull(command.getKey(), "Key must not be null!");
Assert.notNull(command.getGroupName(), "GroupName must not be null!");
if (command.getAction().equals(GroupCommandAction.CREATE)) {
Assert.notNull(command.getReadOffset(), "ReadOffset must not be null!");
StreamOffset offset = StreamOffset.from(command.getKey(), command.getReadOffset().getOffset());
return cmd.xgroupCreate(offset,
ByteUtils.getByteBuffer(command.getGroupName()),
XGroupCreateArgs.Builder.mkstream(command.isMkStream()))
.map(it ->
new CommandResponse<>(command, it)
);
}
if (command.getAction().equals(GroupCommandAction.DELETE_CONSUMER)) {
return cmd
.xgroupDelconsumer(command.getKey(),
io.lettuce.core.Consumer.from(ByteUtils.getByteBuffer(command.getGroupName()),
ByteUtils.getByteBuffer(command.getConsumerName())))
.map(it -> new CommandResponse<>(command, Boolean.TRUE.equals(it) ? "OK" : "Error"));
}
if (command.getAction().equals(GroupCommandAction.DESTROY)) {
return cmd.xgroupDestroy(command.getKey(), ByteUtils.getByteBuffer(command.getGroupName()))
.map(it -> new CommandResponse<>(command, Boolean.TRUE.equals(it) ? "OK" : "Error"));
}
throw new IllegalArgumentException("Unknown group command " + command.getAction());
}));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.ReactiveStreamCommands#xLen(org.reactivestreams.Publisher)
*/
@Override
public Flux> xLen(Publisher commands) {
return connection.execute(cmd -> Flux.from(commands).concatMap(command -> {
Assert.notNull(command.getKey(), "Key must not be null!");
return cmd.xlen(command.getKey()).map(value -> new NumericResponse<>(command, value));
}));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.ReactiveStreamCommands#xPendingSummary(org.reactivestreams.Publisher)
*/
@Override
public Flux> xPendingSummary(
Publisher commands) {
return connection.execute(cmd -> Flux.from(commands).concatMap(command -> {
Assert.notNull(command.getKey(), "Key must not be null!");
return cmd.xpending(command.getKey(), ByteUtils.getByteBuffer(command.getGroupName())).collectList().map(it -> {
// begin
// {* hacking *}
// while (https://github.com/lettuce-io/lettuce-core/issues/1229 != resolved) begin
ArrayList