DATAREDIS-693 - Polishing.
Add Template methods for unlink(…). Align unlink with del/mDel methods on reactive API using concatMap to retain order and provide batching/streaming. Reword Javadoc. Extend tests. Replace blocking calls with StepVerifier in LettuceReactiveKeyCommandsTests. Original pull request: #294.
This commit is contained in:
@@ -264,31 +264,6 @@ public interface ReactiveKeyCommands {
|
||||
*/
|
||||
Flux<NumericResponse<KeyCommand, Long>> del(Publisher<KeyCommand> keys);
|
||||
|
||||
/**
|
||||
* Unlink {@literal key}.
|
||||
*
|
||||
* @param keys must not be {@literal null}.
|
||||
* @return
|
||||
* @see <a href="http://redis.io/commands/unlink">Redis Documentation: UNLINK</a>
|
||||
* @since 2.1
|
||||
*/
|
||||
default Mono<Long> unlink(List<ByteBuffer> keys) {
|
||||
|
||||
Assert.notNull(keys, "Key must not be null!");
|
||||
|
||||
return unlink(Mono.just(keys)).next().map(NumericResponse::getOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink {@literal keys}.
|
||||
*
|
||||
* @param keys must not be {@literal null}.
|
||||
* @return {@link Flux} of {@link NumericResponse} holding the {@literal key} removed along with the deletion result.
|
||||
* @see <a href="http://redis.io/commands/unlink">Redis Documentation: UNLINK</a>
|
||||
* @since 2.1
|
||||
*/
|
||||
Flux<NumericResponse<List<ByteBuffer>, Long>> unlink(Publisher<List<ByteBuffer>> keys);
|
||||
|
||||
/**
|
||||
* Delete multiple {@literal keys} one in one batch.
|
||||
*
|
||||
@@ -312,6 +287,60 @@ public interface ReactiveKeyCommands {
|
||||
*/
|
||||
Flux<NumericResponse<List<ByteBuffer>, Long>> mDel(Publisher<List<ByteBuffer>> keys);
|
||||
|
||||
/**
|
||||
* Unlink the {@code key} from the keyspace. Unlike with {@link #del(ByteBuffer)} the actual memory reclaiming here
|
||||
* happens asynchronously.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @return
|
||||
* @see <a href="http://redis.io/commands/unlink">Redis Documentation: UNLINK</a>
|
||||
* @since 2.1
|
||||
*/
|
||||
default Mono<Long> unlink(ByteBuffer key) {
|
||||
|
||||
Assert.notNull(key, "Keys must not be null!");
|
||||
|
||||
return unlink(Mono.just(key).map(KeyCommand::new)).next().map(NumericResponse::getOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink the {@code key} from the keyspace. Unlike with {@link #del(ByteBuffer)} the actual memory reclaiming here
|
||||
* happens asynchronously.
|
||||
*
|
||||
* @param keys must not be {@literal null}.
|
||||
* @return {@link Flux} of {@link NumericResponse} holding the {@literal key} removed along with the unlink result.
|
||||
* @see <a href="http://redis.io/commands/unlink">Redis Documentation: UNLINK</a>
|
||||
* @since 2.1
|
||||
*/
|
||||
Flux<NumericResponse<KeyCommand, Long>> unlink(Publisher<KeyCommand> keys);
|
||||
|
||||
/**
|
||||
* Unlink the {@code keys} from the keyspace. Unlike with {@link #mDel(List)} the actual memory reclaiming here
|
||||
* happens asynchronously.
|
||||
*
|
||||
* @param keys must not be {@literal null}.
|
||||
* @return
|
||||
* @see <a href="http://redis.io/commands/unlink">Redis Documentation: UNLINK</a>
|
||||
* @since 2.1
|
||||
*/
|
||||
default Mono<Long> mUnlink(List<ByteBuffer> keys) {
|
||||
|
||||
Assert.notNull(keys, "Keys must not be null!");
|
||||
|
||||
return mUnlink(Mono.just(keys)).next().map(NumericResponse::getOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink the {@code keys} from the keyspace. Unlike with {@link #mDel(Publisher)} the actual memory reclaiming here
|
||||
* happens asynchronously.
|
||||
*
|
||||
* @param keys must not be {@literal null}.
|
||||
* @return {@link Flux} of {@link NumericResponse} holding the {@literal key} removed along with the deletion result.
|
||||
* @see <a href="http://redis.io/commands/unlink">Redis Documentation: UNLINK</a>
|
||||
* @since 2.1
|
||||
*/
|
||||
Flux<NumericResponse<List<ByteBuffer>, Long>> mUnlink(Publisher<List<ByteBuffer>> keys);
|
||||
|
||||
/**
|
||||
* {@code EXPIRE}/{@code PEXPIRE} command parameters.
|
||||
*
|
||||
|
||||
@@ -71,8 +71,8 @@ public interface RedisKeyCommands {
|
||||
Long del(byte[]... keys);
|
||||
|
||||
/**
|
||||
* Unlinks the {@code keys} from the keyspace. Unlike with {@link #del(byte[]...)} the actual removal here happens
|
||||
* asynchronously.
|
||||
* Unlink the {@code keys} from the keyspace. Unlike with {@link #del(byte[]...)} the actual memory reclaiming here
|
||||
* happens asynchronously.
|
||||
*
|
||||
* @param keys must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
|
||||
@@ -114,8 +114,8 @@ public interface StringRedisConnection extends RedisConnection {
|
||||
Long del(String... keys);
|
||||
|
||||
/**
|
||||
* Unlinks the {@code keys} from the keyspace. Unlike with {@link #del(byte[]...)} the actual removal here happens
|
||||
* asynchronously.
|
||||
* Unlink the {@code keys} from the keyspace. Unlike with {@link #del(String...)} the actual memory reclaiming here
|
||||
* happens asynchronously.
|
||||
*
|
||||
* @param keys must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
|
||||
@@ -22,7 +22,6 @@ import reactor.core.publisher.Mono;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.springframework.data.redis.connection.DataType;
|
||||
@@ -175,22 +174,6 @@ class LettuceReactiveKeyCommands implements ReactiveKeyCommands {
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveRedisConnection.ReactiveKeyCommands#unlink(org.reactivestreams.Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<NumericResponse<List<ByteBuffer>, Long>> unlink(Publisher<List<ByteBuffer>> keysCollection) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(keysCollection).flatMap((keys) -> {
|
||||
|
||||
Assert.notEmpty(keys, "Keys must not be null!");
|
||||
|
||||
return cmd.unlink(keys.stream().collect(Collectors.toList()).toArray(new ByteBuffer[keys.size()]))
|
||||
.map((value) -> new NumericResponse<>(keys, value));
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveRedisConnection.ReactiveKeyCommands#mDel(org.reactivestreams.Publisher)
|
||||
@@ -202,11 +185,41 @@ class LettuceReactiveKeyCommands implements ReactiveKeyCommands {
|
||||
|
||||
Assert.notEmpty(keys, "Keys must not be null!");
|
||||
|
||||
return cmd.del(keys.stream().collect(Collectors.toList()).toArray(new ByteBuffer[keys.size()]))
|
||||
return cmd.del(keys.toArray(new ByteBuffer[keys.size()]))
|
||||
.map((value) -> new NumericResponse<>(keys, value));
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveRedisConnection.ReactiveKeyCommands#unlink(org.reactivestreams.Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<NumericResponse<KeyCommand, Long>> unlink(Publisher<KeyCommand> commands) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(commands).concatMap((command) -> {
|
||||
|
||||
Assert.notNull(command.getKey(), "Key must not be null!");
|
||||
|
||||
return cmd.unlink(command.getKey()).map((value) -> new NumericResponse<>(command, value));
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveRedisConnection.ReactiveKeyCommands#mUnlink(org.reactivestreams.Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<NumericResponse<List<ByteBuffer>, Long>> mUnlink(Publisher<List<ByteBuffer>> keysCollection) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(keysCollection).concatMap((keys) -> {
|
||||
|
||||
Assert.notEmpty(keys, "Keys must not be null!");
|
||||
|
||||
return cmd.unlink(keys.toArray(new ByteBuffer[keys.size()])).map((value) -> new NumericResponse<>(keys, value));
|
||||
}));
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveKeyCommands#expire(org.reactivestreams.Publisher)
|
||||
*/
|
||||
|
||||
@@ -132,6 +132,28 @@ public interface ReactiveRedisOperations<K, V> {
|
||||
*/
|
||||
Mono<Long> delete(Publisher<K> keys);
|
||||
|
||||
/**
|
||||
* Unlink the {@code key} from the keyspace. Unlike with {@link #delete(Object[])} the actual memory reclaiming here
|
||||
* happens asynchronously.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @return The number of keys that were removed. {@literal null} when used in pipeline / transaction.
|
||||
* @see <a href="http://redis.io/commands/unlink">Redis Documentation: UNLINK</a>
|
||||
* @since 2.1
|
||||
*/
|
||||
Mono<Long> unlink(K... key);
|
||||
|
||||
/**
|
||||
* Unlink the {@code keys} from the keyspace. Unlike with {@link #delete(Publisher)} the actual memory reclaiming here
|
||||
* happens asynchronously.
|
||||
*
|
||||
* @param keys must not be {@literal null}.
|
||||
* @return The number of keys that were removed. {@literal null} when used in pipeline / transaction.
|
||||
* @see <a href="http://redis.io/commands/unlink">Redis Documentation: UNLINK</a>
|
||||
* @since 2.1
|
||||
*/
|
||||
Mono<Long> unlink(Publisher<K> keys);
|
||||
|
||||
/**
|
||||
* Set time to live for given {@code key}.
|
||||
*
|
||||
|
||||
@@ -304,6 +304,40 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
|
||||
.map(CommandResponse::getOutput));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveRedisOperations#unlink(java.lang.Object[])
|
||||
*/
|
||||
@Override
|
||||
@SafeVarargs
|
||||
public final Mono<Long> unlink(K... keys) {
|
||||
|
||||
Assert.notNull(keys, "Keys must not be null!");
|
||||
Assert.notEmpty(keys, "Keys must not be empty!");
|
||||
Assert.noNullElements(keys, "Keys must not contain null elements!");
|
||||
|
||||
if (keys.length == 1) {
|
||||
return createMono(connection -> connection.keyCommands().unlink(rawKey(keys[0])));
|
||||
}
|
||||
|
||||
Mono<List<ByteBuffer>> listOfKeys = Flux.fromArray(keys).map(this::rawKey).collectList();
|
||||
return createMono(connection -> listOfKeys.flatMap(rawKeys -> connection.keyCommands().mUnlink(rawKeys)));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveRedisOperations#unlink(org.reactivestreams.Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Mono<Long> unlink(Publisher<K> keys) {
|
||||
|
||||
Assert.notNull(keys, "Keys must not be null!");
|
||||
|
||||
return createMono(connection -> connection.keyCommands() //
|
||||
.unlink(Flux.from(keys).map(this::rawKey).map(KeyCommand::new)) //
|
||||
.map(CommandResponse::getOutput));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveRedisOperations#expire(java.lang.Object, java.time.Duration)
|
||||
|
||||
@@ -194,6 +194,30 @@ public interface RedisOperations<K, V> {
|
||||
@Nullable
|
||||
Long delete(Collection<K> keys);
|
||||
|
||||
/**
|
||||
* Unlink the {@code key} from the keyspace. Unlike with {@link #delete(Object)} the actual memory reclaiming here
|
||||
* happens asynchronously.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @return The number of keys that were removed. {@literal null} when used in pipeline / transaction.
|
||||
* @see <a href="http://redis.io/commands/unlink">Redis Documentation: UNLINK</a>
|
||||
* @since 2.1
|
||||
*/
|
||||
@Nullable
|
||||
Boolean unlink(K key);
|
||||
|
||||
/**
|
||||
* Unlink the {@code keys} from the keyspace. Unlike with {@link #delete(Collection)} the actual memory reclaiming
|
||||
* here happens asynchronously.
|
||||
*
|
||||
* @param keys must not be {@literal null}.
|
||||
* @return The number of keys that were removed. {@literal null} when used in pipeline / transaction.
|
||||
* @see <a href="http://redis.io/commands/unlink">Redis Documentation: UNLINK</a>
|
||||
* @since 2.1
|
||||
*/
|
||||
@Nullable
|
||||
Long unlink(Collection<K> keys);
|
||||
|
||||
/**
|
||||
* Determine the type stored at {@code key}.
|
||||
*
|
||||
|
||||
@@ -727,6 +727,36 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
|
||||
return execute(connection -> connection.del(rawKeys), true);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.RedisOperations#unlink(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Boolean unlink(K key) {
|
||||
|
||||
byte[] rawKey = rawKey(key);
|
||||
|
||||
Long result = execute(connection -> connection.unlink(rawKey), true);
|
||||
|
||||
return result != null && result.intValue() == 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.RedisOperations#unlink(java.util.Collection)
|
||||
*/
|
||||
@Override
|
||||
public Long unlink(Collection<K> keys) {
|
||||
|
||||
if (CollectionUtils.isEmpty(keys)) {
|
||||
return 0L;
|
||||
}
|
||||
|
||||
byte[][] rawKeys = rawKeys(keys);
|
||||
|
||||
return execute(connection -> connection.unlink(rawKeys), true);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.RedisOperations#hasKey(java.lang.Object)
|
||||
|
||||
Reference in New Issue
Block a user