Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2016-2018 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
*
* http://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;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.reactivestreams.Publisher;
import org.springframework.data.redis.connection.ReactiveRedisConnection.BooleanResponse;
import org.springframework.data.redis.connection.ReactiveRedisConnection.ByteBufferResponse;
import org.springframework.data.redis.connection.ReactiveRedisConnection.Command;
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.ReactiveRedisConnection.RangeCommand;
import org.springframework.data.redis.connection.RedisListCommands.Position;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Redis List commands executed using reactive infrastructure.
*
* @author Christoph Strobl
* @author Mark Paluch
* @since 2.0
*/
public interface ReactiveListCommands {
/**
* @author Christoph Strobl
*/
enum Direction {
LEFT, RIGHT
}
/**
* {@code LPUSH}/{@literal RPUSH} command parameters.
*
* @author Christoph Strobl
* @see Redis Documentation: LPUSH
* @see Redis Documentation: RPUSH
*/
class PushCommand extends KeyCommand {
private List values;
private boolean upsert;
private Direction direction;
private PushCommand(@Nullable ByteBuffer key, List values, Direction direction, boolean upsert) {
super(key);
this.values = values;
this.upsert = upsert;
this.direction = direction;
}
/**
* Creates a new {@link PushCommand} for right push ({@literal RPUSH}).
*
* @return a new {@link PushCommand} for right push ({@literal RPUSH}).
*/
public static PushCommand right() {
return new PushCommand(null, Collections.emptyList(), Direction.RIGHT, true);
}
/**
* Creates a new {@link PushCommand} for left push ({@literal LPUSH}).
*
* @return a new {@link PushCommand} for left push ({@literal LPUSH}).
*/
public static PushCommand left() {
return new PushCommand(null, Collections.emptyList(), Direction.LEFT, true);
}
/**
* Applies the {@literal value}. Constructs a new command instance with all previously configured properties.
*
* @param value must not be {@literal null}.
* @return a new {@link PushCommand} with {@literal value} applied.
*/
public PushCommand value(ByteBuffer value) {
Assert.notNull(value, "Value must not be null!");
return new PushCommand(null, Collections.singletonList(value), direction, upsert);
}
/**
* Applies a {@link List} of {@literal values}.
*
* @param values must not be {@literal null}.
* @return a new {@link PushCommand} with {@literal values} applied.
*/
public PushCommand values(List values) {
Assert.notNull(values, "Values must not be null!");
return new PushCommand(null, new ArrayList<>(values), direction, upsert);
}
/**
* Applies the {@literal key}. Constructs a new command instance with all previously configured properties.
*
* @param key must not be {@literal null}.
* @return a new {@link PushCommand} with {@literal key} applied.
*/
public PushCommand to(ByteBuffer key) {
Assert.notNull(key, "Key must not be null!");
return new PushCommand(key, values, direction, upsert);
}
/**
* Disable upsert. Constructs a new command instance with all previously configured properties.
*
* @return a new {@link PushCommand} with upsert disabled.
*/
public PushCommand ifExists() {
return new PushCommand(getKey(), values, direction, false);
}
/**
* @return never {@literal null}.
*/
public List getValues() {
return values;
}
/**
* @return
*/
public boolean getUpsert() {
return upsert;
}
/**
* @return never {@literal null}.
*/
public Direction getDirection() {
return direction;
}
}
/**
* Append {@literal values} to {@literal key}.
*
* @param key must not be {@literal null}.
* @param values must not be {@literal null}.
* @return
* @see Redis Documentation: RPUSH
*/
default Mono rPush(ByteBuffer key, List values) {
Assert.notNull(key, "Key must not be null!");
Assert.notNull(values, "Values must not be null!");
return push(Mono.just(PushCommand.right().values(values).to(key))).next().map(NumericResponse::getOutput);
}
/**
* Append {@literal values} to {@literal key} only if {@literal key} already exists.
*
* @param key must not be {@literal null}.
* @param value must not be {@literal null}.
* @return
* @see Redis Documentation: RPUSHX
*/
default Mono rPushX(ByteBuffer key, ByteBuffer value) {
Assert.notNull(key, "Key must not be null!");
Assert.notNull(value, "Value must not be null!");
return push(Mono.just(PushCommand.right().value(value).to(key).ifExists())).next().map(NumericResponse::getOutput);
}
/**
* Prepend {@literal values} to {@literal key}.
*
* @param key must not be {@literal null}.
* @param values must not be {@literal null}.
* @return
* @see Redis Documentation: LPUSH
*/
default Mono lPush(ByteBuffer key, List values) {
Assert.notNull(key, "Key must not be null!");
Assert.notNull(values, "Values must not be null!");
return push(Mono.just(PushCommand.left().values(values).to(key))).next().map(NumericResponse::getOutput);
}
/**
* Prepend {@literal value} to {@literal key} if {@literal key} already exists.
*
* @param key must not be {@literal null}.
* @param value must not be {@literal null}.
* @return
* @see Redis Documentation: LPUSHX
*/
default Mono lPushX(ByteBuffer key, ByteBuffer value) {
Assert.notNull(key, "Key must not be null!");
Assert.notNull(value, "Value must not be null!");
return push(Mono.just(PushCommand.left().value(value).to(key).ifExists())).next().map(NumericResponse::getOutput);
}
/**
* Prepend {@link PushCommand#getValues()} to {@link PushCommand#getKey()}.
*
* @param commands must not be {@literal null}.
* @return
* @see Redis Documentation: LPUSH
* @see Redis Documentation: RPUSH
*/
Flux> push(Publisher commands);
/**
* Get the size of list stored at {@literal key}.
*
* @param key must not be {@literal null}.
* @return
* @see Redis Documentation: LLEN
*/
default Mono lLen(ByteBuffer key) {
Assert.notNull(key, "Key must not be null!");
return lLen(Mono.just(new KeyCommand(key))).next().map(NumericResponse::getOutput);
}
/**
* Get the size of list stored at {@link KeyCommand#getKey()}
*
* @param commands must not be {@literal null}.
* @return
* @see Redis Documentation: LLEN
*/
Flux> lLen(Publisher commands);
/**
* Get elements between {@literal start} and {@literal end} from list at {@literal key}.
*
* @param key must not be {@literal null}.
* @param start
* @param end
* @return
* @see Redis Documentation: LRANGE
*/
default Flux lRange(ByteBuffer key, long start, long end) {
Assert.notNull(key, "Key must not be null!");
return lRange(Mono.just(RangeCommand.key(key).fromIndex(start).toIndex(end))).flatMap(CommandResponse::getOutput);
}
/**
* Get elements in {@link RangeCommand#getRange()} from list at {@link RangeCommand#getKey()}
*
* @param commands must not be {@literal null}.
* @return
* @see Redis Documentation: LRANGE
*/
Flux>> lRange(Publisher commands);
/**
* Trim list at {@literal key} to elements between {@literal start} and {@literal end}.
*
* @param key must not be {@literal null}.
* @param start
* @param end
* @return
* @see Redis Documentation: LTRIM
*/
default Mono lTrim(ByteBuffer key, long start, long end) {
Assert.notNull(key, "Key must not be null!");
return lTrim(Mono.just(RangeCommand.key(key).fromIndex(start).toIndex(end))) //
.next() //
.map(BooleanResponse::getOutput);
}
/**
* Trim list at {@link RangeCommand#getKey()} to elements within {@link RangeCommand#getRange()}.
*
* @param commands must not be {@literal null}.
* @return
* @see Redis Documentation: LTRIM
*/
Flux> lTrim(Publisher commands);
/**
* {@code LINDEX} command parameters.
*
* @author Christoph Strobl
* @see Redis Documentation: LINDEX
*/
class LIndexCommand extends KeyCommand {
private final Long index;
private LIndexCommand(@Nullable ByteBuffer key, Long index) {
super(key);
this.index = index;
}
/**
* Creates a new {@link LIndexCommand} given an {@literal index}.
*
* @param index
* @return a new {@link LIndexCommand} for {@literal index}.
*/
public static LIndexCommand elementAt(long index) {
return new LIndexCommand(null, index);
}
/**
* Applies the {@literal key}. Constructs a new command instance with all previously configured properties.
*
* @param key must not be {@literal null}.
* @return a new {@link LIndexCommand} with {@literal key} applied.
*/
public LIndexCommand from(ByteBuffer key) {
Assert.notNull(key, "Key must not be null!");
return new LIndexCommand(key, index);
}
/**
* @return
*/
public Long getIndex() {
return index;
}
}
/**
* Get element at {@literal index} form list at {@literal key}.
*
* @param key must not be {@literal null}.
* @param index
* @return
* @see Redis Documentation: LINDEX
*/
default Mono lIndex(ByteBuffer key, long index) {
Assert.notNull(key, "Key must not be null!");
return lIndex(Mono.just(LIndexCommand.elementAt(index).from(key))).next().map(ByteBufferResponse::getOutput);
}
/**
* Get element at {@link LIndexCommand#getIndex()} form list at {@link LIndexCommand#getKey()}.
*
* @param commands must not be {@literal null}.
* @return
* @see Redis Documentation: LINDEX
*/
Flux> lIndex(Publisher commands);
/**
* {@code LINSERT} command parameters.
*
* @author Christoph Strobl
* @see Redis Documentation: LINSERT
*/
class LInsertCommand extends KeyCommand {
private final @Nullable Position position;
private final @Nullable ByteBuffer pivot;
private final ByteBuffer value;
private LInsertCommand(@Nullable ByteBuffer key, @Nullable Position position, @Nullable ByteBuffer pivot,
ByteBuffer value) {
super(key);
this.position = position;
this.pivot = pivot;
this.value = value;
}
/**
* Creates a new {@link LInsertCommand} given a {@link ByteBuffer value}.
*
* @param value must not be {@literal null}.
* @return a new {@link LInsertCommand} for {@link ByteBuffer value}.
*/
public static LInsertCommand value(ByteBuffer value) {
Assert.notNull(value, "Value must not be null!");
return new LInsertCommand(null, null, null, value);
}
/**
* Applies the before {@literal pivot}. Constructs a new command instance with all previously configured properties.
*
* @param pivot must not be {@literal null}.
* @return a new {@link LInsertCommand} with {@literal pivot} applied.
*/
public LInsertCommand before(ByteBuffer pivot) {
Assert.notNull(pivot, "Before pivot must not be null!");
return new LInsertCommand(getKey(), Position.BEFORE, pivot, value);
}
/**
* Applies the after {@literal pivot}. Constructs a new command instance with all previously configured properties.
*
* @param pivot must not be {@literal null}.
* @return a new {@link LInsertCommand} with {@literal pivot} applied.
*/
public LInsertCommand after(ByteBuffer pivot) {
Assert.notNull(pivot, "After pivot must not be null!");
return new LInsertCommand(getKey(), Position.AFTER, pivot, value);
}
/**
* Applies the {@literal key}. Constructs a new command instance with all previously configured properties.
*
* @param key must not be {@literal null}.
* @return a new {@link LInsertCommand} with {@literal key} applied.
*/
public LInsertCommand forKey(ByteBuffer key) {
Assert.notNull(key, "Key must not be null!");
return new LInsertCommand(key, position, pivot, value);
}
/**
* @return never {@literal null}.
*/
public ByteBuffer getValue() {
return value;
}
/**
* @return can be {@literal null}.
*/
@Nullable
public Position getPosition() {
return position;
}
/**
* @return can be {@literal null}.
*/
@Nullable
public ByteBuffer getPivot() {
return pivot;
}
}
/**
* Insert {@literal value} {@link Position#BEFORE} or {@link Position#AFTER} existing {@literal pivot} for
* {@literal key}.
*
* @param key must not be {@literal null}.
* @param position must not be {@literal null}.
* @param pivot must not be {@literal null}.
* @param value must not be {@literal null}.
* @return
* @see Redis Documentation: LINSERT
*/
default Mono lInsert(ByteBuffer key, Position position, ByteBuffer pivot, ByteBuffer value) {
Assert.notNull(key, "Key must not be null!");
Assert.notNull(position, "Position must not be null!");
Assert.notNull(pivot, "Pivot must not be null!");
Assert.notNull(value, "Value must not be null!");
LInsertCommand command = LInsertCommand.value(value);
command = Position.BEFORE.equals(position) ? command.before(pivot) : command.after(pivot);
command = command.forKey(key);
return lInsert(Mono.just(command)).next().map(NumericResponse::getOutput);
}
/**
* Insert {@link LInsertCommand#getValue()} {@link Position#BEFORE} or {@link Position#AFTER} existing
* {@link LInsertCommand#getPivot()} for {@link LInsertCommand#getKey()}
*
* @param commands must not be {@literal null}.
* @return
* @see Redis Documentation: LINSERT
*/
Flux> lInsert(Publisher commands);
/**
* {@code LSET} command parameters.
*
* @author Christoph Strobl
* @see Redis Documentation: LSET
*/
class LSetCommand extends KeyCommand {
private final Long index;
private final @Nullable ByteBuffer value;
private LSetCommand(@Nullable ByteBuffer key, Long index, @Nullable ByteBuffer value) {
super(key);
this.index = index;
this.value = value;
}
/**
* Creates a new {@link LSetCommand} given an {@literal index}.
*
* @param index
* @return a new {@link LSetCommand} for {@literal index}.
*/
public static LSetCommand elementAt(long index) {
return new LSetCommand(null, index, null);
}
/**
* Applies the {@literal value}. Constructs a new command instance with all previously configured properties.
*
* @param value must not be {@literal null}.
* @return a new {@link LSetCommand} with {@literal value} applied.
*/
public LSetCommand to(ByteBuffer value) {
Assert.notNull(value, "Value must not be null!");
return new LSetCommand(getKey(), index, value);
}
/**
* Applies the {@literal key}. Constructs a new command instance with all previously configured properties.
*
* @param key must not be {@literal null}.
* @return a new {@link LSetCommand} with {@literal value} applied.
*/
public LSetCommand forKey(ByteBuffer key) {
Assert.notNull(key, "Key must not be null!");
return new LSetCommand(key, index, value);
}
/**
* @return can be {@literal null}.
*/
@Nullable
public ByteBuffer getValue() {
return value;
}
/**
* @return never {@literal null}.
*/
public Long getIndex() {
return index;
}
}
/**
* Set the {@literal value} list element at {@literal index}.
*
* @param key must not be {@literal null}.
* @param index
* @param value must not be {@literal null}.
* @return
* @see Redis Documentation: LSET
*/
default Mono lSet(ByteBuffer key, long index, ByteBuffer value) {
Assert.notNull(key, "Key must not be null!");
Assert.notNull(value, "Value must not be null!");
return lSet(Mono.just(LSetCommand.elementAt(index).to(value).forKey(key))).next().map(BooleanResponse::getOutput);
}
/**
* Set the {@link LSetCommand#getValue()} list element at {@link LSetCommand#getKey()}.
*
* @param commands
* @return
* @see Redis Documentation: LSET
*/
Flux> lSet(Publisher commands);
/**
* {@code LREM} command parameters.
*
* @author Christoph Strobl
* @see Redis Documentation: LREM
*/
class LRemCommand extends KeyCommand {
private final Long count;
private final @Nullable ByteBuffer value;
private LRemCommand(@Nullable ByteBuffer key, Long count, @Nullable ByteBuffer value) {
super(key);
this.count = count;
this.value = value;
}
/**
* Creates a new {@link LRemCommand} to delete all values.
*
* @return a new {@link LRemCommand} for {@link ByteBuffer value}.
*/
public static LRemCommand all() {
return new LRemCommand(null, 0L, null);
}
/**
* Creates a new {@link LRemCommand} to first {@literal count} values.
*
* @return a new {@link LRemCommand} to delete first {@literal count} values.
*/
public static LRemCommand first(long count) {
return new LRemCommand(null, count, null);
}
/**
* Creates a new {@link LRemCommand} to last {@literal count} values.
*
* @return a new {@link LRemCommand} to delete last {@literal count} values.
*/
public static LRemCommand last(long count) {
Long value = count < 0L ? count : Math.negateExact(count);
return new LRemCommand(null, value, null);
}
/**
* Applies the {@literal value}. Constructs a new command instance with all previously configured properties.
*
* @param value must not be {@literal null}.
* @return a new {@link LRemCommand} with {@literal value} applied.
*/
public LRemCommand occurrencesOf(ByteBuffer value) {
Assert.notNull(value, "Value must not be null!");
return new LRemCommand(getKey(), count, value);
}
/**
* Applies the {@literal key}. Constructs a new command instance with all previously configured properties.
*
* @param key must not be {@literal null}.
* @return a new {@link LRemCommand} with {@literal key} applied.
*/
public LRemCommand from(ByteBuffer key) {
Assert.notNull(key, "Key must not be null!");
return new LRemCommand(key, count, value);
}
/**
* @return never {@literal null}.
*/
public Long getCount() {
return count;
}
/**
* @return can be {@literal null}.
*/
@Nullable
public ByteBuffer getValue() {
return value;
}
}
/**
* Removes all occurrences of {@literal value} from the list stored at {@literal key}.
*
* @param key must not be {@literal null}.
* @param value must not be {@literal null}.
* @return
* @see Redis Documentation: LREM
*/
default Mono lRem(ByteBuffer key, ByteBuffer value) {
Assert.notNull(key, "Key must not be null!");
Assert.notNull(value, "Value must not be null!");
return lRem(Mono.just(LRemCommand.all().occurrencesOf(value).from(key))).next().map(NumericResponse::getOutput);
}
/**
* Removes the first {@literal count} occurrences of {@literal value} from the list stored at {@literal key}.
*
* @param key must not be {@literal null}.
* @param count must not be {@literal null}.
* @param value must not be {@literal null}.
* @return
* @see Redis Documentation: LREM
*/
default Mono lRem(ByteBuffer key, Long count, ByteBuffer value) {
Assert.notNull(key, "Key must not be null!");
Assert.notNull(count, "Count must not be null!");
Assert.notNull(value, "Value must not be null!");
return lRem(Mono.just(LRemCommand.first(count).occurrencesOf(value).from(key))).next()
.map(NumericResponse::getOutput);
}
/**
* Removes the {@link LRemCommand#getCount()} occurrences of {@link LRemCommand#getValue()} from the list stored at
* {@link LRemCommand#getKey()}.
*
* @param commands must not be {@literal null}.
* @return
* @see Redis Documentation: LREM
*/
Flux> lRem(Publisher commands);
/**
* {@code LPOP}/{@literal RPOP} command parameters.
*
* @author Christoph Strobl
* @see Redis Documentation: LPOP
* @see Redis Documentation: RPOP
*/
class PopCommand extends KeyCommand {
private final Direction direction;
private PopCommand(@Nullable ByteBuffer key, Direction direction) {
super(key);
this.direction = direction;
}
/**
* Creates a new {@link PopCommand} for right push ({@literal RPOP}).
*
* @return a new {@link PopCommand} for right push ({@literal RPOP}).
*/
public static PopCommand right() {
return new PopCommand(null, Direction.RIGHT);
}
/**
* Creates a new {@link PopCommand} for right push ({@literal LPOP}).
*
* @return a new {@link PopCommand} for right push ({@literal LPOP}).
*/
public static PopCommand left() {
return new PopCommand(null, Direction.LEFT);
}
/**
* Applies the {@literal key}. Constructs a new command instance with all previously configured properties.
*
* @param key must not be {@literal null}.
* @return a new {@link LSetCommand} with {@literal value} applied.
*/
public PopCommand from(ByteBuffer key) {
Assert.notNull(key, "Key must not be null!");
return new PopCommand(key, direction);
}
/**
* @return never {@literal null}.
*/
public Direction getDirection() {
return direction;
}
}
/**
* Removes and returns first element in list stored at {@literal key}.
*
* @param key must not be {@literal null}.
* @return
* @see Redis Documentation: LPOP
*/
default Mono lPop(ByteBuffer key) {
Assert.notNull(key, "Key must not be null!");
return pop(Mono.just(PopCommand.left().from(key))).next().map(ByteBufferResponse::getOutput);
}
/**
* Removes and returns last element in list stored at {@literal key}.
*
* @param key must not be {@literal null}.
* @return
* @see Redis Documentation: RPOP
*/
default Mono rPop(ByteBuffer key) {
Assert.notNull(key, "Key must not be null!");
return pop(Mono.just(PopCommand.right().from(key))).next().map(ByteBufferResponse::getOutput);
}
/**
* Removes and returns last element in list stored at {@link KeyCommand#getKey()}
*
* @param commands must not be {@literal null}.
* @return
* @see Redis Documentation: LPOP
* @see Redis Documentation: RPOP
*/
Flux> pop(Publisher commands);
/**
* @author Christoph Strobl
* @see Redis Documentation: BLPOP
* @see Redis Documentation: BRPOP
*/
class BPopCommand implements Command {
private final List keys;
private final Duration timeout;
private final Direction direction;
private BPopCommand(List keys, Duration timeout, Direction direction) {
this.keys = keys;
this.timeout = timeout;
this.direction = direction;
}
/**
* Creates a new {@link BPopCommand} for right push ({@literal BRPOP}).
*
* @return a new {@link BPopCommand} for right push ({@literal BRPOP}).
*/
public static BPopCommand right() {
return new BPopCommand(Collections.emptyList(), Duration.ZERO, Direction.RIGHT);
}
/**
* Creates a new {@link BPopCommand} for right push ({@literal BLPOP}).
*
* @return a new {@link BPopCommand} for right push ({@literal BLPOP}).
*/
public static BPopCommand left() {
return new BPopCommand(Collections.emptyList(), Duration.ZERO, Direction.LEFT);
}
/**
* Applies the {@literal value}. Constructs a new command instance with all previously configured properties.
*
* @param keys must not be {@literal null}.
* @return a new {@link BPopCommand} with {@literal value} applied.
*/
public BPopCommand from(List keys) {
Assert.notNull(keys, "Keys must not be null!");
return new BPopCommand(new ArrayList<>(keys), Duration.ZERO, direction);
}
/**
* Applies a {@link Duration timeout}. Constructs a new command instance with all previously configured properties.
*
* @param timeout must not be {@literal null}.
* @return a new {@link BPopCommand} with {@link Duration timeout} applied.
*/
public BPopCommand blockingFor(Duration timeout) {
Assert.notNull(timeout, "Timeout must not be null!");
return new BPopCommand(keys, timeout, direction);
}
/* (non-Javadoc)
* @see org.springframework.data.redis.connection.ReactiveRedisConnection.Command#getKey()
*/
@Override
public ByteBuffer getKey() {
return null;
}
/**
* @return
*/
public List getKeys() {
return keys;
}
/**
* @return
*/
public Duration getTimeout() {
return timeout;
}
/**
* @return
*/
public Direction getDirection() {
return direction;
}
}
/**
* Result for {@link PopCommand}/{@link BPopCommand}.
*
* @author Christoph Strobl
*/
class PopResult {
private final List result;
public PopResult(List result) {
this.result = result;
}
public ByteBuffer getKey() {
return ObjectUtils.isEmpty(result) ? null : result.get(0);
}
public ByteBuffer getValue() {
return ObjectUtils.isEmpty(result) ? null : result.get(1);
}
public List getRaw() {
return Collections.unmodifiableList(result);
}
}
/**
* Result for {@link PopCommand}/{@link BPopCommand}.
*
* @author Christoph Strobl
*/
class PopResponse extends CommandResponse {
public PopResponse(BPopCommand input, PopResult output) {
super(input, output);
}
}
/**
* Removes and returns first element from lists stored at {@literal keys}.
* Blocks connection until element available or {@literal timeout} reached.
*
* @param keys must not be {@literal null}.
* @param timeout must not be {@literal null}.
* @return
* @see Redis Documentation: BLPOP
*/
default Mono blPop(List keys, Duration timeout) {
Assert.notNull(keys, "Keys must not be null.");
Assert.notNull(timeout, "Timeout must not be null.");
return bPop(Mono.just(BPopCommand.left().from(keys).blockingFor(timeout))).next().map(PopResponse::getOutput);
}
/**
* Removes and returns last element from lists stored at {@literal keys}.
* Blocks connection until element available or {@literal timeout} reached.
*
* @param keys must not be {@literal null}.
* @param timeout must not be {@literal null}.
* @return
* @see Redis Documentation: BRPOP
*/
default Mono brPop(List keys, Duration timeout) {
Assert.notNull(keys, "Keys must not be null.");
Assert.notNull(timeout, "Timeout must not be null.");
return bPop(Mono.just(BPopCommand.right().from(keys).blockingFor(timeout))).next().map(PopResponse::getOutput);
}
/**
* Removes and returns the top {@link BPopCommand#getDirection()} element from lists stored at
* {@link BPopCommand#getKeys()}.
* Blocks connection until element available or {@link BPopCommand#getTimeout()} reached.
*
* @param commands
* @return
* @see Redis Documentation: BLPOP
* @see Redis Documentation: BRPOP
*/
Flux bPop(Publisher commands);
/**
* {@code RPOPLPUSH} command parameters.
*
* @author Christoph Strobl
* @see Redis Documentation: RPOPLPUSH
*/
class RPopLPushCommand extends KeyCommand {
private final @Nullable ByteBuffer destination;
private RPopLPushCommand(ByteBuffer key, @Nullable ByteBuffer destination) {
super(key);
this.destination = destination;
}
/**
* Creates a new {@link RPopLPushCommand} given a {@literal sourceKey}.
*
* @param sourceKey must not be {@literal null}.
* @return a new {@link RPopLPushCommand} for a {@literal sourceKey}.
*/
public static RPopLPushCommand from(ByteBuffer sourceKey) {
Assert.notNull(sourceKey, "Source key must not be null!");
return new RPopLPushCommand(sourceKey, null);
}
/**
* Applies the {@literal destinationKey}. Constructs a new command instance with all previously configured
* properties.
*
* @param destinationKey must not be {@literal null}.
* @return a new {@link BPopCommand} with {@literal value} applied.
*/
public RPopLPushCommand to(ByteBuffer destinationKey) {
Assert.notNull(destinationKey, "Destination key must not be null!");
return new RPopLPushCommand(getKey(), destinationKey);
}
/**
* @return can be {@literal null}.
*/
@Nullable
public ByteBuffer getDestination() {
return destination;
}
}
/**
* Remove the last element from list at {@literal source}, append it to {@literal destination} and return its value.
*
* @param source must not be {@literal null}.
* @param destination must not be {@literal null}.
* @return
* @see Redis Documentation: RPOPLPUSH
*/
default Mono rPopLPush(ByteBuffer source, ByteBuffer destination) {
Assert.notNull(source, "Source must not be null!");
Assert.notNull(destination, "Destination must not be null!");
return rPopLPush(Mono.just(RPopLPushCommand.from(source).to(destination))) //
.next() //
.map(ByteBufferResponse::getOutput);
}
/**
* Remove the last element from list at {@link RPopLPushCommand#getKey()}, append it to
* {@link RPopLPushCommand#getDestination()} and return its value.
*
* @param commands must not be {@literal null}.
* @return
* @see Redis Documentation: RPOPLPUSH
*/
Flux> rPopLPush(Publisher commands);
/**
* {@code BRPOPLPUSH} command parameters.
*
* @author Christoph Strobl
* @see Redis Documentation: BRPOPLPUSH
*/
class BRPopLPushCommand extends KeyCommand {
private final @Nullable ByteBuffer destination;
private final Duration timeout;
private BRPopLPushCommand(ByteBuffer key, @Nullable ByteBuffer destination, Duration timeout) {
super(key);
this.destination = destination;
this.timeout = timeout;
}
/**
* Creates a new {@link BRPopLPushCommand} given a {@literal sourceKey}.
*
* @param sourceKey must not be {@literal null}.
* @return a new {@link BRPopLPushCommand} for a {@literal sourceKey}.
*/
public static BRPopLPushCommand from(ByteBuffer sourceKey) {
Assert.notNull(sourceKey, "Source key must not be null!");
return new BRPopLPushCommand(sourceKey, null, Duration.ZERO);
}
/**
* Applies the {@literal destinationKey}. Constructs a new command instance with all previously configured
* properties.
*
* @param destinationKey must not be {@literal null}.
* @return a new {@link BRPopLPushCommand} with {@literal value} applied.
*/
public BRPopLPushCommand to(ByteBuffer destinationKey) {
Assert.notNull(destinationKey, "Destination key must not be null!");
return new BRPopLPushCommand(getKey(), destinationKey, timeout);
}
/**
* Applies a {@link Duration timeout}. Constructs a new command instance with all previously configured properties.
*
* @param timeout must not be {@literal null}.
* @return a new {@link BRPopLPushCommand} with {@link Duration timeout} applied.
*/
public BRPopLPushCommand blockingFor(Duration timeout) {
Assert.notNull(timeout, "Timeout must not be null!");
return new BRPopLPushCommand(getKey(), destination, timeout);
}
/**
* @return can be {@literal null}.
*/
@Nullable
public ByteBuffer getDestination() {
return destination;
}
/**
* @return never {@literal null}.
*/
public Duration getTimeout() {
return timeout;
}
}
/**
* Remove the last element from list at {@literal source}, append it to {@literal destination} and return its value.
* Blocks connection until element available or {@literal timeout} reached.
*
* @param source must not be {@literal null}.
* @param destination must not be {@literal null}.
* @return
* @see Redis Documentation: BRPOPLPUSH
*/
default Mono bRPopLPush(ByteBuffer source, ByteBuffer destination, Duration timeout) {
Assert.notNull(source, "Source must not be null!");
Assert.notNull(destination, "Destination must not be null!");
return bRPopLPush(Mono.just(BRPopLPushCommand.from(source).to(destination).blockingFor(timeout))).next()
.map(ByteBufferResponse::getOutput);
}
/**
* Remove the last element from list at {@link BRPopLPushCommand#getKey()}, append it to
* {@link BRPopLPushCommand#getDestination()} and return its value.
* Blocks connection until element available or {@link BRPopLPushCommand#getTimeout()} reached.
*
* @param commands must not be {@literal null}.
* @return
* @see Redis Documentation: BRPOPLPUSH
*/
Flux> bRPopLPush(Publisher commands);
}