DATAREDIS-694 - Add support for TOUCH.

We now support TOUCH for both Lettuce and Jedis in imperative and reactive (Lettuce only) KeyCommands.

Original pull request: #284.
This commit is contained in:
Christoph Strobl
2017-10-05 14:27:09 +02:00
committed by Mark Paluch
parent 5e77dee4dc
commit 8a640a29b6
13 changed files with 236 additions and 4 deletions

View File

@@ -1214,6 +1214,15 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco
return convertAndReturn(delegate.type(key), identityConverter);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisKeyCommands#touch(byte[][])
*/
@Override
public Long touch(byte[]... keys) {
return convertAndReturn(delegate.touch(keys), identityConverter);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisTxCommands#unwatch()
@@ -2505,6 +2514,16 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco
return type(serialize(key));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.StringRedisConnection#touch(java.lang.String[])
*/
@Nullable
@Override
public Long touch(String... keys) {
return touch(serializeMulti(keys));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.StringRedisConnection#zAdd(java.lang.String, double, java.lang.String)

View File

@@ -75,6 +75,13 @@ public interface DefaultedRedisConnection extends RedisConnection {
return keyCommands().type(pattern);
}
/** @deprecated in favor of {@link RedisConnection#keyCommands()}. */
@Override
@Deprecated
default Long touch(byte[]... keys) {
return keyCommands().touch(keys);
}
/** @deprecated in favor of {@link RedisConnection#keyCommands()}. */
@Override
@Deprecated

View File

@@ -21,6 +21,7 @@ import reactor.core.publisher.Mono;
import java.nio.ByteBuffer;
import java.time.Duration;
import java.time.Instant;
import java.util.Collection;
import java.util.List;
import org.reactivestreams.Publisher;
@@ -87,6 +88,28 @@ public interface ReactiveKeyCommands {
*/
Flux<CommandResponse<KeyCommand, DataType>> type(Publisher<KeyCommand> keys);
/**
* Alter the last access time of given {@code key(s)}.
*
* @param keys must not be {@literal null}.
* @return {@link Mono} emitting the number of keys touched.
* @see <a href="http://redis.io/commands/touch">Redis Documentation: TOUCH</a>
* @since 2.1
*/
default Mono<Long> touch(Collection<ByteBuffer> keys) {
return touch(Mono.just(keys)).next().map(NumericResponse::getOutput);
}
/**
* Alter the last access time of given {@code key(s)}.
*
* @param keys must not be {@literal null}.
* @return
* @see <a href="http://redis.io/commands/touch">Redis Documentation: TOUCH</a>
* @since 2.1
*/
Flux<NumericResponse<Collection<ByteBuffer>, Long>> touch(Publisher<Collection<ByteBuffer>> keys);
/**
* Find all keys matching the given {@literal pattern}.
*

View File

@@ -80,6 +80,17 @@ public interface RedisKeyCommands {
@Nullable
DataType type(byte[] key);
/**
* Alter the last access time of given {@code key(s)}.
*
* @param keys must not be {@literal null}.
* @return {@literal null} when used in pipeline / transaction.
* @see <a href="http://redis.io/commands/touch">Redis Documentation: TOUCH</a>
* @since 2.1
*/
@Nullable
Long touch(byte[]... keys);
/**
* Find all keys matching the given {@code pattern}.
*

View File

@@ -123,6 +123,17 @@ public interface StringRedisConnection extends RedisConnection {
*/
DataType type(String key);
/**
* Alter the last access time of given {@code key(s)}.
*
* @param keys must not be {@literal null}.
* @return {@literal null} when used in pipeline / transaction.
* @see <a href="http://redis.io/commands/touch">Redis Documentation: TOUCH</a>
* @since 2.1
*/
@Nullable
Long touch(String... keys);
/**
* Find all keys matching the given {@code pattern}.
*

View File

@@ -176,6 +176,37 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection {
return commandArgs;
}
/**
* Execute the given command for the {@code key} provided potentially appending args. <br />
* This method, other than {@link #execute(String, byte[]...)}, dispatches the command to the {@code key} serving
* master node.
*
* <pre>
* <code>
* // SET foo bar EX 10 NX
* execute("SET", "foo".getBytes(), asBinaryList("bar", "EX", 10, "NX")
* </code>
* </pre>
*
* @param command must not be {@literal null}.
* @param keys must not be {@literal null}.
* @param args must not be {@literal null}.
* @return command result as delivered by the underlying Redis driver. Can be {@literal null}.
* @since 2.1
*/
@Nullable
public <T> List<T> execute(String command, Collection<byte[]> keys, Collection<byte[]> args) {
Assert.notNull(command, "Command must not be null!");
Assert.notNull(keys, "Key must not be null!");
Assert.notNull(args, "Args must not be null!");
return clusterCommandExecutor.executeMultiKeyCommand((JedisMultiKeyClusterCommandCallback<T>) (client, key) -> {
return JedisClientUtils.execute(command, new byte[][] { key }, args.toArray(new byte[args.size()][]),
() -> client);
}, keys).resultsAsList();
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisConnection#geoCommands()
@@ -829,8 +860,7 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection {
PropertyAccessor accessor = new DirectFieldAccessFallbackBeanWrapper(cluster);
this.connectionHandler = accessor.isReadableProperty("connectionHandler")
? (JedisClusterConnectionHandler) accessor.getPropertyValue("connectionHandler")
: null;
? (JedisClusterConnectionHandler) accessor.getPropertyValue("connectionHandler") : null;
} else {
this.connectionHandler = null;
}

View File

@@ -20,6 +20,7 @@ import redis.clients.jedis.BinaryJedis;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -97,6 +98,20 @@ class JedisClusterKeyCommands implements RedisKeyCommands {
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisKeyCommands#touch(byte[][])
*/
@Nullable
@Override
public Long touch(byte[]... keys) {
Assert.notNull(keys, "Keys must not be null!");
return connection.<Long> execute("TOUCH", Arrays.asList(keys), Collections.emptyList()).stream()
.mapToLong(val -> val).sum();
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisKeyCommands#keys(byte[])

View File

@@ -146,6 +146,19 @@ class JedisKeyCommands implements RedisKeyCommands {
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisKeyCommands#touch(byte[][])
*/
@Nullable
@Override
public Long touch(byte[]... keys) {
Assert.notNull(keys, "Keys must not be null!");
return Long.class.cast(connection.execute("TOUCH", keys));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisKeyCommands#keys(byte[])

View File

@@ -150,6 +150,30 @@ class LettuceKeyCommands implements RedisKeyCommands {
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisKeyCommands#touch(byte[][])
*/
@Override
public Long touch(byte[]... keys) {
Assert.notNull(keys, "Keys must not be null!");
try {
if (isPipelined()) {
pipeline(connection.newLettuceResult(getAsyncConnection().touch(keys)));
return null;
}
if (isQueueing()) {
transaction(connection.newLettuceTxResult(getConnection().touch(keys)));
return null;
}
return getConnection().touch(keys);
} catch (Exception ex) {
throw convertLettuceAccessException(ex);
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisKeyCommands#keys(byte[])

View File

@@ -20,6 +20,7 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
@@ -86,6 +87,22 @@ class LettuceReactiveKeyCommands implements ReactiveKeyCommands {
}));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.ReactiveRedisConnection.ReactiveKeyCommands#touch(org.reactivestreams.Publisher)
*/
@Override
public Flux<NumericResponse<Collection<ByteBuffer>, Long>> touch(Publisher<Collection<ByteBuffer>> keysCollection) {
return connection.execute(cmd -> Flux.from(keysCollection).concatMap((keys) -> {
Assert.notEmpty(keys, "Keys must not be null!");
return cmd.touch(keys.toArray(new ByteBuffer[keys.size()]))
.map((value) -> new NumericResponse<>(keys, value));
}));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.ReactiveRedisConnection.ReactiveKeyCommands#keys(org.reactivestreams.Publisher)