DATAREDIS-1196 - Add support for LPOS command.
Original pull request: #563.
This commit is contained in:
committed by
Mark Paluch
parent
1a025fea46
commit
76cbe5124d
@@ -702,6 +702,15 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco
|
||||
return convertAndReturn(delegate.lPop(key), identityConverter);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lPos(byte[], byte[], java.lang.Integer, java.lang.Integer)
|
||||
*/
|
||||
@Override
|
||||
public List<Long> lPos(byte[] key, byte[] element, @Nullable Integer rank, @Nullable Integer count) {
|
||||
return convertAndReturn(delegate.lPos(key, element, rank, count), identityConverter);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lPush(byte[], byte[][])
|
||||
@@ -2138,6 +2147,15 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco
|
||||
return convertAndReturn(delegate.lPop(serialize(key)), bytesToString);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.StringRedisConnection#lPos(java.lang.String, java.lang.String, java.lang.Integer, java.lang.Integer)
|
||||
*/
|
||||
@Override
|
||||
public List<Long> lPos(String key, String element, @Nullable Integer rank, @Nullable Integer count) {
|
||||
return lPos(serialize(key), serialize(element), rank, count);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.StringRedisConnection#lPush(java.lang.String, java.lang.String[])
|
||||
|
||||
@@ -621,6 +621,13 @@ public interface DefaultedRedisConnection extends RedisConnection {
|
||||
return listCommands().rPush(key, values);
|
||||
}
|
||||
|
||||
/** @deprecated in favor of {@link RedisConnection#listCommands()}}. */
|
||||
@Override
|
||||
@Deprecated
|
||||
default List<Long> lPos(byte[] key, byte[] element, @Nullable Integer rank, @Nullable Integer count) {
|
||||
return listCommands().lPos(key, element, rank, count);
|
||||
}
|
||||
|
||||
/** @deprecated in favor of {@link RedisConnection#listCommands()}}. */
|
||||
@Override
|
||||
@Deprecated
|
||||
|
||||
@@ -312,6 +312,125 @@ public interface ReactiveListCommands {
|
||||
*/
|
||||
Flux<BooleanResponse<RangeCommand>> lTrim(Publisher<RangeCommand> commands);
|
||||
|
||||
/**
|
||||
* {@code LPOS} command parameters.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
*/
|
||||
class LPosCommand extends KeyCommand {
|
||||
|
||||
private final ByteBuffer element;
|
||||
private final @Nullable Integer count;
|
||||
private final @Nullable Integer rank;
|
||||
|
||||
private LPosCommand(@Nullable ByteBuffer key, ByteBuffer element, @Nullable Integer count, @Nullable Integer rank) {
|
||||
|
||||
super(key);
|
||||
this.element = element;
|
||||
this.count = count;
|
||||
this.rank = rank;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link LPosCommand} for given {@literal element}.
|
||||
*
|
||||
* @param element
|
||||
* @return a new {@link LPosCommand} for {@literal element}.
|
||||
*/
|
||||
public static LPosCommand lPosOf(ByteBuffer element) {
|
||||
return new LPosCommand(null, element, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 LPosCommand} with {@literal key} applied.
|
||||
*/
|
||||
public LPosCommand from(ByteBuffer key) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
return new LPosCommand(key, element, count, rank);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the {@literal count} parameter specifying the number of matches to return. Constructs a new command
|
||||
* instance with all previously configured properties.
|
||||
*
|
||||
* @param count can be {@literal null}.
|
||||
* @return a new {@link LPosCommand} with {@literal count} applied.
|
||||
*/
|
||||
public LPosCommand count(Integer count) {
|
||||
return new LPosCommand(getKey(), element, count, rank);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the {@literal rank} parameter specifying the "rank" of the first element to return. Constructs a new
|
||||
* command instance with all previously configured properties.
|
||||
*
|
||||
* @param rank can be {@literal null}.
|
||||
* @return a new {@link LPosCommand} with {@literal count} applied.
|
||||
*/
|
||||
public LPosCommand rank(Integer rank) {
|
||||
return new LPosCommand(getKey(), element, count, rank);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getRank() {
|
||||
return rank;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ByteBuffer getElement() {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get first index of the {@literal element} from list at {@literal key}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param element
|
||||
* @return a {@link Mono} emitting the elements index.
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lindex">Redis Documentation: LINDEX</a>
|
||||
*/
|
||||
default Mono<Long> lPos(ByteBuffer key, ByteBuffer element) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
return lPos(LPosCommand.lPosOf(element).from(key)).next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get indices of the {@literal element} from list at {@link LPosCommand#getKey()}.
|
||||
*
|
||||
* @param command must not be {@literal null}.
|
||||
* @return a {@link Flux} emitting the elements indices one by one.
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lindex">Redis Documentation: LINDEX</a>
|
||||
*/
|
||||
default Flux<Long> lPos(LPosCommand command) {
|
||||
return lPos(Mono.just(command)).map(NumericResponse::getOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get indices of the {@literal element} from list at {@link LPosCommand#getKey()}.
|
||||
*
|
||||
* @param commands must not be {@literal null}.
|
||||
* @return a {@link Flux} emitting the elements indices one by one.
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lindex">Redis Documentation: LINDEX</a>
|
||||
*/
|
||||
Flux<NumericResponse<LPosCommand, Long>> lPos(Publisher<LPosCommand> commands);
|
||||
|
||||
/**
|
||||
* {@code LINDEX} command parameters.
|
||||
*
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.redis.connection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* List-specific commands supported by Redis.
|
||||
@@ -46,6 +47,36 @@ public interface RedisListCommands {
|
||||
@Nullable
|
||||
Long rPush(byte[] key, byte[]... values);
|
||||
|
||||
/**
|
||||
* Returns the index of matching elements inside the list stored at given {@literal key}. <br />
|
||||
* Requires Redis 6.0.6.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param element must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
* @since 2.4
|
||||
*/
|
||||
@Nullable
|
||||
default Long lPos(byte[] key, byte[] element) {
|
||||
return CollectionUtils.firstElement(lPos(key, element, null, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of matching elements inside the list stored at given {@literal key}. <br />
|
||||
* Requires Redis 6.0.6.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param element must not be {@literal null}.
|
||||
* @param rank specifies the "rank" of the first element to return, in case there are multiple matches. A rank of 1
|
||||
* means to return the first match, 2 to return the second match, and so forth.
|
||||
* @param count number of matches to return.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
* @since 2.4
|
||||
*/
|
||||
List<Long> lPos(byte[] key, byte[] element, @Nullable Integer rank, @Nullable Integer count);
|
||||
|
||||
/**
|
||||
* Prepend {@code values} to {@code key}.
|
||||
*
|
||||
|
||||
@@ -49,6 +49,7 @@ import org.springframework.data.redis.core.types.Expiration;
|
||||
import org.springframework.data.redis.core.types.RedisClientInfo;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Convenience extension of {@link RedisConnection} that accepts and returns {@link String}s instead of byte arrays.
|
||||
@@ -685,6 +686,36 @@ public interface StringRedisConnection extends RedisConnection {
|
||||
*/
|
||||
Long rPush(String key, String... values);
|
||||
|
||||
/**
|
||||
* Returns the index of matching elements inside the list stored at given {@literal key}. <br />
|
||||
* Requires Redis 6.0.6.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param element must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
* @since 2.4
|
||||
*/
|
||||
@Nullable
|
||||
default Long lPos(String key, String element) {
|
||||
return CollectionUtils.firstElement(lPos(key, element, null, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of matching elements inside the list stored at given {@literal key}. <br />
|
||||
* Requires Redis 6.0.6.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param element must not be {@literal null}.
|
||||
* @param rank specifies the "rank" of the first element to return, in case there are multiple matches. A rank of 1
|
||||
* means to return the first match, 2 to return the second match, and so forth.
|
||||
* @param count number of matches to return.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
* @since 2.4
|
||||
*/
|
||||
List<Long> lPos(String key, String element, @Nullable Integer rank, @Nullable Integer count);
|
||||
|
||||
/**
|
||||
* Prepend {@code values} to {@code key}.
|
||||
*
|
||||
|
||||
@@ -20,9 +20,11 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.redis.connection.ClusterSlotHashUtil;
|
||||
import org.springframework.data.redis.connection.RedisListCommands;
|
||||
import org.springframework.data.redis.connection.jedis.JedisClusterConnection.JedisMultiKeyClusterCommandCallback;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@@ -55,6 +57,19 @@ class JedisClusterListCommands implements RedisListCommands {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#l{lPos(byte[], byte[], java.lang.Integer, java.lang.Integer)
|
||||
*/
|
||||
@Override
|
||||
public List<Long> lPos(byte[] key, byte[] element, @Nullable Integer rank, @Nullable Integer count) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(element, "Element must not be null!");
|
||||
|
||||
throw new InvalidDataAccessApiUsageException("LPOS is not supported by jedis.");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lPush(byte[], byte[][])
|
||||
|
||||
@@ -20,7 +20,9 @@ import redis.clients.jedis.Protocol;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.redis.connection.RedisListCommands;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -60,6 +62,19 @@ class JedisListCommands implements RedisListCommands {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#l{lPos(byte[], byte[], java.lang.Integer, java.lang.Integer)
|
||||
*/
|
||||
@Override
|
||||
public List<Long> lPos(byte[] key, byte[] element, @Nullable Integer rank, @Nullable Integer count) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(element, "Element must not be null!");
|
||||
|
||||
throw new InvalidDataAccessApiUsageException("LPOS is not supported by jedis.");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lPush(byte[], byte[][])
|
||||
|
||||
@@ -1136,6 +1136,7 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
COMMAND_OUTPUT_TYPE_MAPPING.put(LINSERT, IntegerOutput.class);
|
||||
COMMAND_OUTPUT_TYPE_MAPPING.put(LLEN, IntegerOutput.class);
|
||||
COMMAND_OUTPUT_TYPE_MAPPING.put(LPUSH, IntegerOutput.class);
|
||||
COMMAND_OUTPUT_TYPE_MAPPING.put(LPOS, IntegerOutput.class);
|
||||
COMMAND_OUTPUT_TYPE_MAPPING.put(LPUSHX, IntegerOutput.class);
|
||||
COMMAND_OUTPUT_TYPE_MAPPING.put(LREM, IntegerOutput.class);
|
||||
COMMAND_OUTPUT_TYPE_MAPPING.put(PTTL, IntegerOutput.class);
|
||||
|
||||
@@ -15,13 +15,16 @@
|
||||
*/
|
||||
package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import io.lettuce.core.LPosArgs;
|
||||
import io.lettuce.core.cluster.api.async.RedisClusterAsyncCommands;
|
||||
import io.lettuce.core.cluster.api.sync.RedisClusterCommands;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.connection.RedisListCommands;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -61,6 +64,47 @@ class LettuceListCommands implements RedisListCommands {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#l{lPos(byte[], byte[], java.lang.Integer, java.lang.Integer)
|
||||
*/
|
||||
@Override
|
||||
public List<Long> lPos(byte[] key, byte[] element, @Nullable Integer rank, @Nullable Integer count) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(element, "Element must not be null!");
|
||||
|
||||
LPosArgs args = new LPosArgs();
|
||||
if (rank != null) {
|
||||
args.rank(rank);
|
||||
}
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
if (count != null) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().lpos(key, element, count, args)));
|
||||
} else {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().lpos(key, element, args)));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
if (count != null) {
|
||||
transaction(connection.newLettuceResult(getAsyncConnection().lpos(key, element, count, args)));
|
||||
} else {
|
||||
transaction(connection.newLettuceResult(getAsyncConnection().lpos(key, element, args)));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (count != null) {
|
||||
return getConnection().lpos(key, element, count, args);
|
||||
}
|
||||
|
||||
return Collections.singletonList(getConnection().lpos(key, element, args));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lPush(byte[], byte[][])
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import io.lettuce.core.LPosArgs;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -146,8 +147,32 @@ class LettuceReactiveListCommands implements ReactiveListCommands {
|
||||
LettuceConverters.getLowerBoundIndex(range), //
|
||||
LettuceConverters.getUpperBoundIndex(range));
|
||||
|
||||
return result
|
||||
.map(LettuceConverters::stringToBoolean).map(value -> new BooleanResponse<>(command, value));
|
||||
return result.map(LettuceConverters::stringToBoolean).map(value -> new BooleanResponse<>(command, value));
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveListCommands#lPos(org.reactivestreams.Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<NumericResponse<LPosCommand, Long>> lPos(Publisher<LPosCommand> commands) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(commands).concatMap(command -> {
|
||||
|
||||
LPosArgs args = new LPosArgs();
|
||||
if (command.getRank() != null) {
|
||||
args.rank(command.getRank());
|
||||
}
|
||||
|
||||
Flux<Long> values;
|
||||
if (command.getCount() != null) {
|
||||
values = cmd.lpos(command.getKey(), command.getElement(), command.getCount(), args);
|
||||
} else {
|
||||
values = cmd.lpos(command.getKey(), command.getElement(), args).flux();
|
||||
}
|
||||
|
||||
return values.map(value -> new NumericResponse<>(command, value));
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -238,7 +263,8 @@ class LettuceReactiveListCommands implements ReactiveListCommands {
|
||||
Assert.notNull(command.getDirection(), "Direction must not be null!");
|
||||
|
||||
Mono<ByteBuffer> popResult = ObjectUtils.nullSafeEquals(Direction.RIGHT, command.getDirection())
|
||||
? cmd.rpop(command.getKey()) : cmd.lpop(command.getKey());
|
||||
? cmd.rpop(command.getKey())
|
||||
: cmd.lpop(command.getKey());
|
||||
|
||||
return popResult.map(value -> new ByteBufferResponse<>(command, value));
|
||||
}));
|
||||
|
||||
@@ -169,6 +169,28 @@ public interface BoundListOperations<K, V> extends BoundKeyOperations<K> {
|
||||
@Nullable
|
||||
V index(long index);
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of the specified value in the list at at {@code key}. <br />
|
||||
* Requires Redis 6.0.6
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction or when not contained in list.
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
*/
|
||||
Long indexOf(V value);
|
||||
|
||||
/**
|
||||
* Returns the index of the last occurrence of the specified value in the list at at {@code key}. <br />
|
||||
* Requires Redis 6.0.6
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction or when not contained in list.
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
*/
|
||||
Long lastIndexOf(V value);
|
||||
|
||||
/**
|
||||
* Removes and returns first element in list stored at the bound key.
|
||||
*
|
||||
|
||||
@@ -55,6 +55,24 @@ class DefaultBoundListOperations<K, V> extends DefaultBoundKeyOperations<K> impl
|
||||
return ops.index(getKey(), index);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.BoundListOperations#indexOf(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Long indexOf(V value) {
|
||||
return ops.indexOf(getKey(), value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.BoundListOperations#lastIndexOf(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Long lastIndexOf(V value) {
|
||||
return ops.lastIndexOf(getKey(), value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.BoundListOperations#leftPop()
|
||||
|
||||
@@ -53,6 +53,34 @@ class DefaultListOperations<K, V> extends AbstractOperations<K, V> implements Li
|
||||
}, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ListOperations#indexOf(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Long indexOf(K key, V value) {
|
||||
|
||||
byte[] rawKey = rawKey(key);
|
||||
byte[] rawValue = rawValue(value);
|
||||
return execute(connection -> connection.lPos(rawKey, rawValue), true);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ListOperations#lastIndexOf(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Long lastIndexOf(K key, V value) {
|
||||
|
||||
byte[] rawKey = rawKey(key);
|
||||
byte[] rawValue = rawValue(value);
|
||||
return execute(connection -> {
|
||||
|
||||
List<Long> indexes = connection.lPos(rawKey, rawValue, -1, null);
|
||||
return CollectionUtils.firstElement(indexes);
|
||||
}, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ListOperations#leftPop(java.lang.Object)
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.util.function.Function;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.springframework.data.redis.connection.ReactiveListCommands;
|
||||
import org.springframework.data.redis.connection.ReactiveListCommands.LPosCommand;
|
||||
import org.springframework.data.redis.connection.RedisListCommands.Position;
|
||||
import org.springframework.data.redis.serializer.RedisSerializationContext;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -232,6 +233,30 @@ class DefaultReactiveListOperations<K, V> implements ReactiveListOperations<K, V
|
||||
return createMono(connection -> connection.lIndex(rawKey(key), index).map(this::readValue));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveListOperations#indexOf(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Mono<Long> indexOf(K key, V value) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
return createMono(connection -> connection.lPos(rawKey(key), rawValue(value)));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveListOperations#lastIndexOf(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Mono<Long> lastIndexOf(K key, V value) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
return createMono(connection -> connection.lPos(LPosCommand.lPosOf(rawValue(value)).from(rawKey(key)).rank(-1)));
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveListOperations#leftPop(java.lang.Object)
|
||||
*/
|
||||
|
||||
@@ -213,6 +213,30 @@ public interface ListOperations<K, V> {
|
||||
@Nullable
|
||||
V index(K key, long index);
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of the specified value in the list at at {@code key}. <br />
|
||||
* Requires Redis 6.0.6
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param value must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction or when not contained in list.
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
*/
|
||||
Long indexOf(K key, V value);
|
||||
|
||||
/**
|
||||
* Returns the index of the last occurrence of the specified value in the list at at {@code key}. <br />
|
||||
* Requires Redis 6.0.6
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param value must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction or when not contained in list.
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
*/
|
||||
Long lastIndexOf(K key, V value);
|
||||
|
||||
/**
|
||||
* Removes and returns first element in list stored at {@code key}.
|
||||
*
|
||||
|
||||
@@ -20,7 +20,6 @@ import reactor.core.publisher.Mono;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Redis list specific operations.
|
||||
@@ -197,6 +196,30 @@ public interface ReactiveListOperations<K, V> {
|
||||
*/
|
||||
Mono<V> index(K key, long index);
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of the specified value in the list at at {@code key}. <br />
|
||||
* Requires Redis 6.0.6
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param value must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
*/
|
||||
Mono<Long> indexOf(K key, V value);
|
||||
|
||||
/**
|
||||
* Returns the index of the last occurrence of the specified value in the list at at {@code key}. <br />
|
||||
* Requires Redis 6.0.6
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param value must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
*/
|
||||
Mono<Long> lastIndexOf(K key, V value);
|
||||
|
||||
/**
|
||||
* Removes and returns first element in list stored at {@code key}.
|
||||
*
|
||||
|
||||
@@ -250,7 +250,9 @@ public class DefaultRedisList<E> extends AbstractRedisCollection<E> implements R
|
||||
*/
|
||||
@Override
|
||||
public int indexOf(Object o) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
Long index = listOps.indexOf((E) o);
|
||||
return index != null ? index.intValue() : -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -259,7 +261,9 @@ public class DefaultRedisList<E> extends AbstractRedisCollection<E> implements R
|
||||
*/
|
||||
@Override
|
||||
public int lastIndexOf(Object o) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
Long index = listOps.lastIndexOf((E) o);
|
||||
return index != null ? index.intValue() : -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1479,6 +1479,72 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
verifyResults(Arrays.asList(new Object[] { 2l, Arrays.asList(new String[] { "baz", "bar" }) }));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-1196
|
||||
@IfProfileValue(name = "redisVersion", value = "6.0.6+")
|
||||
@WithRedisDriver({ RedisDriver.LETTUCE })
|
||||
public void lPos() {
|
||||
|
||||
actual.add(connection.rPush("mylist", "a", "b", "c", "1", "2", "3", "c", "c"));
|
||||
actual.add(connection.lPos("mylist", "c"));
|
||||
|
||||
assertThat((Long) getResults().get(1)).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-1196
|
||||
@IfProfileValue(name = "redisVersion", value = "6.0.6+")
|
||||
@WithRedisDriver({ RedisDriver.LETTUCE })
|
||||
public void lPosRank() {
|
||||
|
||||
actual.add(connection.rPush("mylist", "a", "b", "c", "1", "2", "3", "c", "c"));
|
||||
actual.add(connection.lPos("mylist", "c", 2, null));
|
||||
|
||||
assertThat((List<Long>) getResults().get(1)).containsExactly(6L);
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-1196
|
||||
@IfProfileValue(name = "redisVersion", value = "6.0.6+")
|
||||
@WithRedisDriver({ RedisDriver.LETTUCE })
|
||||
public void lPosNegativeRank() {
|
||||
|
||||
actual.add(connection.rPush("mylist", "a", "b", "c", "1", "2", "3", "c", "c"));
|
||||
actual.add(connection.lPos("mylist", "c", -1, null));
|
||||
|
||||
assertThat((List<Long>) getResults().get(1)).containsExactly(7L);
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-1196
|
||||
@IfProfileValue(name = "redisVersion", value = "6.0.6+")
|
||||
@WithRedisDriver({ RedisDriver.LETTUCE })
|
||||
public void lPosCount() {
|
||||
|
||||
actual.add(connection.rPush("mylist", "a", "b", "c", "1", "2", "3", "c", "c"));
|
||||
actual.add(connection.lPos("mylist", "c", null, 2));
|
||||
|
||||
assertThat((List<Long>) getResults().get(1)).containsExactly(2L, 6L);
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-1196
|
||||
@IfProfileValue(name = "redisVersion", value = "6.0.6+")
|
||||
@WithRedisDriver({ RedisDriver.LETTUCE })
|
||||
public void lPosRankCount() {
|
||||
|
||||
actual.add(connection.rPush("mylist", "a", "b", "c", "1", "2", "3", "c", "c"));
|
||||
actual.add(connection.lPos("mylist", "c", -1, 2));
|
||||
|
||||
assertThat((List<Long>) getResults().get(1)).containsExactly(7L, 6L);
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-1196
|
||||
@IfProfileValue(name = "redisVersion", value = "6.0.6+")
|
||||
@WithRedisDriver({ RedisDriver.LETTUCE })
|
||||
public void lPosCountZero() {
|
||||
|
||||
actual.add(connection.rPush("mylist", "a", "b", "c", "1", "2", "3", "c", "c"));
|
||||
actual.add(connection.lPos("mylist", "c", null, 0));
|
||||
|
||||
assertThat((List<Long>) getResults().get(1)).containsExactly(2L, 6L, 7L);
|
||||
}
|
||||
|
||||
// Set operations
|
||||
|
||||
@Test
|
||||
|
||||
@@ -23,19 +23,23 @@ import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.domain.Range;
|
||||
import org.springframework.data.redis.connection.ReactiveListCommands.LPosCommand;
|
||||
import org.springframework.data.redis.connection.ReactiveListCommands.PopResult;
|
||||
import org.springframework.data.redis.connection.ReactiveListCommands.PushCommand;
|
||||
import org.springframework.data.redis.connection.ReactiveRedisConnection;
|
||||
import org.springframework.data.redis.connection.ReactiveRedisConnection.CommandResponse;
|
||||
import org.springframework.data.redis.connection.ReactiveRedisConnection.RangeCommand;
|
||||
import org.springframework.data.redis.connection.RedisListCommands.Position;
|
||||
import org.springframework.data.redis.test.util.MinimumRedisVersionRule;
|
||||
import org.springframework.test.annotation.IfProfileValue;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
@@ -44,6 +48,8 @@ import org.springframework.data.redis.connection.RedisListCommands.Position;
|
||||
*/
|
||||
public class LettuceReactiveListCommandTests extends LettuceReactiveCommandsTestsBase {
|
||||
|
||||
@Rule public MinimumRedisVersionRule redisVersion = new MinimumRedisVersionRule();
|
||||
|
||||
@Test // DATAREDIS-525
|
||||
public void rPushShouldAppendValuesCorrectly() {
|
||||
|
||||
@@ -304,4 +310,88 @@ public class LettuceReactiveListCommandTests extends LettuceReactiveCommandsTest
|
||||
assertThat(nativeCommands.llen(KEY_2)).isEqualTo(2L);
|
||||
assertThat(nativeCommands.lindex(KEY_2, 0)).isEqualTo(VALUE_3);
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-1196
|
||||
@IfProfileValue(name = "redisVersion", value = "6.0.6+")
|
||||
public void lPos() {
|
||||
|
||||
nativeCommands.rpush(KEY_1, "a", "b", "c", "1", "2", "3", "c", "c");
|
||||
|
||||
connection.listCommands().lPos(KEY_1_BBUFFER, ByteBuffer.wrap("c".getBytes(StandardCharsets.UTF_8))) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(2L) //
|
||||
.verifyComplete();
|
||||
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-1196
|
||||
@IfProfileValue(name = "redisVersion", value = "6.0.6+")
|
||||
public void lPosRank() {
|
||||
|
||||
nativeCommands.rpush(KEY_1, "a", "b", "c", "1", "2", "3", "c", "c");
|
||||
|
||||
connection.listCommands()
|
||||
.lPos(LPosCommand.lPosOf(ByteBuffer.wrap("c".getBytes(StandardCharsets.UTF_8))).from(KEY_1_BBUFFER).rank(2)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(6L) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-1196
|
||||
@IfProfileValue(name = "redisVersion", value = "6.0.6+")
|
||||
public void lPosNegativeRank() {
|
||||
|
||||
nativeCommands.rpush(KEY_1, "a", "b", "c", "1", "2", "3", "c", "c");
|
||||
|
||||
connection.listCommands()
|
||||
.lPos(LPosCommand.lPosOf(ByteBuffer.wrap("c".getBytes(StandardCharsets.UTF_8))).from(KEY_1_BBUFFER).rank(-1)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(7L) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-1196
|
||||
@IfProfileValue(name = "redisVersion", value = "6.0.6+")
|
||||
public void lPosCount() {
|
||||
|
||||
nativeCommands.rpush(KEY_1, "a", "b", "c", "1", "2", "3", "c", "c");
|
||||
|
||||
connection.listCommands()
|
||||
.lPos(LPosCommand.lPosOf(ByteBuffer.wrap("c".getBytes(StandardCharsets.UTF_8))).from(KEY_1_BBUFFER).count(2)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(2L) //
|
||||
.expectNext(6L) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-1196
|
||||
@IfProfileValue(name = "redisVersion", value = "6.0.6+")
|
||||
public void lPosRankCount() {
|
||||
|
||||
nativeCommands.rpush(KEY_1, "a", "b", "c", "1", "2", "3", "c", "c");
|
||||
|
||||
connection.listCommands()
|
||||
.lPos(LPosCommand.lPosOf(ByteBuffer.wrap("c".getBytes(StandardCharsets.UTF_8))).from(KEY_1_BBUFFER)
|
||||
.from(KEY_1_BBUFFER).rank(-1).count(2)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(7L) //
|
||||
.expectNext(6L) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-1196
|
||||
@IfProfileValue(name = "redisVersion", value = "6.0.6+")
|
||||
public void lPosCountZero() {
|
||||
|
||||
nativeCommands.rpush(KEY_1, "a", "b", "c", "1", "2", "3", "c", "c");
|
||||
|
||||
connection.listCommands()
|
||||
.lPos(LPosCommand.lPosOf(ByteBuffer.wrap("c".getBytes(StandardCharsets.UTF_8))).from(KEY_1_BBUFFER).count(0)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(2L) //
|
||||
.expectNext(6L) //
|
||||
.expectNext(7L) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,15 +27,18 @@ import java.util.concurrent.TimeUnit;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
import org.springframework.data.redis.ConnectionFactoryTracker;
|
||||
import org.springframework.data.redis.ObjectFactory;
|
||||
import org.springframework.data.redis.RedisTestProfileValueSource;
|
||||
import org.springframework.data.redis.StringObjectFactory;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.data.redis.test.util.MinimumRedisVersionRule;
|
||||
import org.springframework.test.annotation.IfProfileValue;
|
||||
|
||||
/**
|
||||
* Integration test of {@link DefaultListOperations}
|
||||
@@ -49,6 +52,8 @@ import org.springframework.data.redis.StringObjectFactory;
|
||||
@RunWith(Parameterized.class)
|
||||
public class DefaultListOperationsTests<K, V> {
|
||||
|
||||
@Rule public MinimumRedisVersionRule redisVersion = new MinimumRedisVersionRule();
|
||||
|
||||
private RedisTemplate<K, V> redisTemplate;
|
||||
|
||||
private ObjectFactory<K> keyFactory;
|
||||
@@ -284,6 +289,8 @@ public class DefaultListOperationsTests<K, V> {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testLeftPushAllCollection() {
|
||||
|
||||
assumeTrue(redisTemplate.getConnectionFactory() instanceof LettuceConnectionFactory);
|
||||
|
||||
K key = keyFactory.instance();
|
||||
|
||||
V v1 = valueFactory.instance();
|
||||
@@ -311,4 +318,35 @@ public class DefaultListOperationsTests<K, V> {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> listOps.leftPushAll(keyFactory.instance(), (Collection<V>) null));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-1196
|
||||
@IfProfileValue(name = "redisVersion", value = "6.0.6+")
|
||||
public void indexOf() {
|
||||
|
||||
K key = keyFactory.instance();
|
||||
V v1 = valueFactory.instance();
|
||||
V v2 = valueFactory.instance();
|
||||
V v3 = valueFactory.instance();
|
||||
|
||||
assertThat(listOps.rightPush(key, v1)).isEqualTo(Long.valueOf(1));
|
||||
assertThat(listOps.rightPush(key, v2)).isEqualTo(Long.valueOf(2));
|
||||
assertThat(listOps.rightPush(key, v1, v3)).isEqualTo(Long.valueOf(3));
|
||||
assertThat(listOps.indexOf(key, v1)).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-1196
|
||||
@IfProfileValue(name = "redisVersion", value = "6.0.6+")
|
||||
public void lastIndexOf() {
|
||||
|
||||
K key = keyFactory.instance();
|
||||
V v1 = valueFactory.instance();
|
||||
V v2 = valueFactory.instance();
|
||||
V v3 = valueFactory.instance();
|
||||
|
||||
assertThat(listOps.rightPush(key, v1)).isEqualTo(Long.valueOf(1));
|
||||
assertThat(listOps.rightPush(key, v2)).isEqualTo(Long.valueOf(2));
|
||||
assertThat(listOps.rightPush(key, v1)).isEqualTo(Long.valueOf(3));
|
||||
assertThat(listOps.rightPush(key, v3)).isEqualTo(Long.valueOf(4));
|
||||
assertThat(listOps.lastIndexOf(key, v1)).isEqualTo(2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.Collection;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
@@ -34,6 +35,8 @@ import org.springframework.data.redis.ObjectFactory;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.data.redis.test.util.MinimumRedisVersionRule;
|
||||
import org.springframework.test.annotation.IfProfileValue;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link DefaultReactiveListOperations}.
|
||||
@@ -45,6 +48,8 @@ import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
@SuppressWarnings("unchecked")
|
||||
public class DefaultReactiveListOperationsIntegrationTests<K, V> {
|
||||
|
||||
@Rule public MinimumRedisVersionRule redisVersion = new MinimumRedisVersionRule();
|
||||
|
||||
private final ReactiveRedisTemplate<K, V> redisTemplate;
|
||||
private final ReactiveListOperations<K, V> listOperations;
|
||||
|
||||
@@ -366,6 +371,34 @@ public class DefaultReactiveListOperationsIntegrationTests<K, V> {
|
||||
listOperations.index(key, 1).as(StepVerifier::create).expectNext(value2).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-1196
|
||||
@IfProfileValue(name = "redisVersion", value = "6.0.6+")
|
||||
public void indexOf() {
|
||||
|
||||
K key = keyFactory.instance();
|
||||
V v1 = valueFactory.instance();
|
||||
V v2 = valueFactory.instance();
|
||||
V v3 = valueFactory.instance();
|
||||
|
||||
listOperations.rightPushAll(key, v1, v2, v1, v3).as(StepVerifier::create).expectNext(4L).verifyComplete();
|
||||
|
||||
listOperations.indexOf(key, v1).as(StepVerifier::create).expectNext(0L).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-1196
|
||||
@IfProfileValue(name = "redisVersion", value = "6.0.6+")
|
||||
public void lastIndexOf() {
|
||||
|
||||
K key = keyFactory.instance();
|
||||
V v1 = valueFactory.instance();
|
||||
V v2 = valueFactory.instance();
|
||||
V v3 = valueFactory.instance();
|
||||
|
||||
listOperations.rightPushAll(key, v1, v2, v1, v3).as(StepVerifier::create).expectNext(4L).verifyComplete();
|
||||
|
||||
listOperations.lastIndexOf(key, v1).as(StepVerifier::create).expectNext(2L).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-602
|
||||
public void leftPop() {
|
||||
|
||||
|
||||
@@ -24,11 +24,15 @@ import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.assertj.core.api.Assumptions;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.data.redis.ObjectFactory;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.test.util.MinimumRedisVersionRule;
|
||||
import org.springframework.test.annotation.IfProfileValue;
|
||||
|
||||
/**
|
||||
* Integration test for RedisList
|
||||
@@ -38,6 +42,8 @@ import org.springframework.data.redis.core.RedisTemplate;
|
||||
*/
|
||||
public abstract class AbstractRedisListTests<T> extends AbstractRedisCollectionTests<T> {
|
||||
|
||||
@Rule public MinimumRedisVersionRule redisVersion = new MinimumRedisVersionRule();
|
||||
|
||||
protected RedisList<T> list;
|
||||
|
||||
/**
|
||||
@@ -54,6 +60,7 @@ public abstract class AbstractRedisListTests<T> extends AbstractRedisCollectionT
|
||||
@SuppressWarnings("unchecked")
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
super.setUp();
|
||||
list = (RedisList<T>) collection;
|
||||
}
|
||||
@@ -157,8 +164,12 @@ public abstract class AbstractRedisListTests<T> extends AbstractRedisCollectionT
|
||||
assertThat(list.addAll(1, asList)).isTrue();
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
@Test // DATAREDIS-1196
|
||||
@IfProfileValue(name = "redisVersion", value = "6.0.6+")
|
||||
public void testIndexOfObject() {
|
||||
|
||||
Assumptions.assumeThat(template.getConnectionFactory()).isInstanceOf(LettuceConnectionFactory.class);
|
||||
|
||||
T t1 = getT();
|
||||
T t2 = getT();
|
||||
|
||||
@@ -168,7 +179,7 @@ public abstract class AbstractRedisListTests<T> extends AbstractRedisCollectionT
|
||||
|
||||
assertThat(list.indexOf(t2)).isEqualTo(-1);
|
||||
list.add(t2);
|
||||
assertThat(list.indexOf(t1)).isEqualTo(1);
|
||||
assertThat(list.indexOf(t2)).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -519,4 +530,22 @@ public abstract class AbstractRedisListTests<T> extends AbstractRedisCollectionT
|
||||
public void testTakeLast() {
|
||||
testPollLast();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-1196
|
||||
@IfProfileValue(name = "redisVersion", value = "6.0.6+")
|
||||
public void lastIndexOf() {
|
||||
|
||||
Assumptions.assumeThat(template.getConnectionFactory()).isInstanceOf(LettuceConnectionFactory.class);
|
||||
|
||||
T t1 = getT();
|
||||
T t2 = getT();
|
||||
T t3 = getT();
|
||||
|
||||
list.add(t1);
|
||||
list.add(t2);
|
||||
list.add(t1);
|
||||
list.add(t3);
|
||||
|
||||
assertThat(list.lastIndexOf(t1)).isEqualTo(2);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user