diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index 80ccf0be6..d34879cef 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -9,7 +9,9 @@ New and noteworthy in the latest releases. * Upgrade to Java 8. * Removed support for SRP and JRedis drivers. * Upgrade to `Lettuce` 5.0. -* Reactive connection support using https://github.com/mp911de/lettuce[mp911de/lettuce] +* Reactive connection support using https://github.com/lettuce-io/lettuce-core[lettuce-io/lettuce-core]. +* Introduce Redis feature-specific interfaces for `RedisConnection`. + [[new-in-1.8.0]] == New in Spring Data Redis 1.8 @@ -30,7 +32,7 @@ New and noteworthy in the latest releases. * Support for Spring Data Repository abstractions (see <>). [[new-in-1-6-0]] -== New in Spring Data Redis 1.6 +== New in Spring Data Redis 1.6 * The `Lettuce` Redis driver switched from https://github.com/wg/lettuce[wg/lettuce] to https://github.com/mp911de/lettuce[mp911de/lettuce]. * Support for `ZRANGEBYLEX`. @@ -39,7 +41,7 @@ New and noteworthy in the latest releases. * Generic Jackson2 `RedisSerializer` making use of Jackson's polymorphic deserialization. [[new-in-1-5-0]] -== New in Spring Data Redis 1.5 +== New in Spring Data Redis 1.5 * Add support for Redis HyperLogLog commands `PFADD`, `PFCOUNT` and `PFMERGE`. * Configurable `JavaType` lookup for Jackson based `RedisSerializers`. diff --git a/src/main/java/org/springframework/data/redis/connection/ClusterCommandExecutor.java b/src/main/java/org/springframework/data/redis/connection/ClusterCommandExecutor.java index f320d8bcf..38e80a94f 100644 --- a/src/main/java/org/springframework/data/redis/connection/ClusterCommandExecutor.java +++ b/src/main/java/org/springframework/data/redis/connection/ClusterCommandExecutor.java @@ -15,21 +15,8 @@ */ package org.springframework.data.redis.connection; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Random; -import java.util.Set; -import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -215,13 +202,7 @@ public class ClusterCommandExecutor implements DisposableBean { Map>> futures = new LinkedHashMap>>(); for (final RedisClusterNode node : resolvedRedisClusterNodes) { - futures.put(new NodeExecution(node), executor.submit(new Callable>() { - - @Override - public NodeResult call() throws Exception { - return executeCommandOnSingleNode(callback, node); - } - })); + futures.put(new NodeExecution(node), executor.submit(() -> executeCommandOnSingleNode(callback, node))); } return collectResults(futures); @@ -310,13 +291,8 @@ public class ClusterCommandExecutor implements DisposableBean { if (entry.getKey().isMaster()) { for (final byte[] key : entry.getValue()) { - futures.put(new NodeExecution(entry.getKey(), key), executor.submit(new Callable>() { - - @Override - public NodeResult call() throws Exception { - return executeMultiKeyCommandOnSingleNode(cmd, entry.getKey(), key); - } - })); + futures.put(new NodeExecution(entry.getKey(), key), + executor.submit(() -> executeMultiKeyCommandOnSingleNode(cmd, entry.getKey(), key))); } } } diff --git a/src/main/java/org/springframework/data/redis/connection/DefaultedRedisClusterConnection.java b/src/main/java/org/springframework/data/redis/connection/DefaultedRedisClusterConnection.java index 9695324bf..3312ee205 100644 --- a/src/main/java/org/springframework/data/redis/connection/DefaultedRedisClusterConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/DefaultedRedisClusterConnection.java @@ -15,10 +15,120 @@ */ package org.springframework.data.redis.connection; +import java.util.List; +import java.util.Properties; + +import org.springframework.data.redis.core.types.RedisClientInfo; + /** * @author Christoph Strobl + * @author Mark Paluch * @since 2.0 */ public interface DefaultedRedisClusterConnection extends RedisClusterConnection, DefaultedRedisConnection { + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void bgReWriteAof(RedisClusterNode node) { + serverCommands().bgReWriteAof(node); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void bgSave(RedisClusterNode node) { + serverCommands().bgSave(node); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default Long lastSave(RedisClusterNode node) { + return serverCommands().lastSave(node); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void save(RedisClusterNode node) { + serverCommands().save(node); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default Long dbSize(RedisClusterNode node) { + return serverCommands().dbSize(node); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void flushDb(RedisClusterNode node) { + serverCommands().flushDb(node); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void flushAll(RedisClusterNode node) { + serverCommands().flushAll(node); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default Properties info(RedisClusterNode node) { + return serverCommands().info(node); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default Properties info(RedisClusterNode node, String section) { + return serverCommands().info(node, section); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void shutdown(RedisClusterNode node) { + serverCommands().shutdown(node); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default List getConfig(RedisClusterNode node, String pattern) { + return serverCommands().getConfig(node, pattern); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void setConfig(RedisClusterNode node, String param, String value) { + serverCommands().setConfig(node, param, value); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void resetConfigStats(RedisClusterNode node) { + serverCommands().resetConfigStats(node); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default Long time(RedisClusterNode node) { + return serverCommands().time(node); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default List getClientList(RedisClusterNode node) { + return serverCommands().getClientList(node); + } } diff --git a/src/main/java/org/springframework/data/redis/connection/DefaultedRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/DefaultedRedisConnection.java index 4a558cffe..0d286e16c 100644 --- a/src/main/java/org/springframework/data/redis/connection/DefaultedRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/DefaultedRedisConnection.java @@ -18,6 +18,7 @@ package org.springframework.data.redis.connection; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Properties; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -29,12 +30,16 @@ import org.springframework.data.geo.Point; import org.springframework.data.redis.core.Cursor; import org.springframework.data.redis.core.ScanOptions; import org.springframework.data.redis.core.types.Expiration; +import org.springframework.data.redis.core.types.RedisClientInfo; /** - * {@link DefaultedRedisConnection} provides method delegates to {@code Redis*Command} interfaces accessible via {@link RedisConnection}. - * This allows us to maintain backwards compatibility while moving the actual implementation and stay in sync with {@link ReactiveRedisConnection}. - * Going forward the {@link RedisCommands} extension is likely to be removed from {@link RedisConnection}. + * {@link DefaultedRedisConnection} provides method delegates to {@code Redis*Command} interfaces accessible via + * {@link RedisConnection}. This allows us to maintain backwards compatibility while moving the actual implementation + * and stay in sync with {@link ReactiveRedisConnection}. Going forward the {@link RedisCommands} extension is likely to + * be removed from {@link RedisConnection}. + * * @author Christoph Strobl + * @author Mark Paluch * @since 2.0 */ public interface DefaultedRedisConnection extends RedisConnection { @@ -1012,4 +1017,225 @@ public interface DefaultedRedisConnection extends RedisConnection { default void pfMerge(byte[] destinationKey, byte[]... sourceKeys) { hyperLogLogCommands().pfMerge(destinationKey, sourceKeys); } + + // SERVER COMMANDS + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void bgWriteAof() { + serverCommands().bgWriteAof(); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void bgReWriteAof() { + serverCommands().bgReWriteAof(); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void bgSave() { + serverCommands().bgSave(); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default Long lastSave() { + return serverCommands().lastSave(); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void save() { + serverCommands().save(); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default Long dbSize() { + return serverCommands().dbSize(); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void flushDb() { + serverCommands().flushDb(); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void flushAll() { + serverCommands().flushAll(); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default Properties info() { + return serverCommands().info(); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default Properties info(String section) { + return serverCommands().info(section); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void shutdown() { + serverCommands().shutdown(); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void shutdown(ShutdownOption option) { + serverCommands().shutdown(option); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default List getConfig(String pattern) { + return serverCommands().getConfig(pattern); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void setConfig(String param, String value) { + serverCommands().setConfig(param, value); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void resetConfigStats() { + serverCommands().resetConfigStats(); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default Long time() { + return serverCommands().time(); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void killClient(String host, int port) { + serverCommands().killClient(host, port); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void setClientName(byte[] name) { + serverCommands().setClientName(name); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default String getClientName() { + return serverCommands().getClientName(); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default List getClientList() { + return serverCommands().getClientList(); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void slaveOf(String host, int port) { + serverCommands().slaveOf(host, port); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void slaveOfNoOne() { + serverCommands().slaveOfNoOne(); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option) { + serverCommands().migrate(key, target, dbIndex, option); + } + + /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ + @Override + @Deprecated + default void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option, long timeout) { + serverCommands().migrate(key, target, dbIndex, option, timeout); + } + + // SCRIPTING COMMANDS + + /** @deprecated in favor of {@link RedisConnection#scriptingCommands()}. */ + @Override + @Deprecated + default void scriptFlush() { + scriptingCommands().scriptFlush(); + } + + /** @deprecated in favor of {@link RedisConnection#scriptingCommands()}. */ + @Override + @Deprecated + default void scriptKill() { + scriptingCommands().scriptKill(); + } + + /** @deprecated in favor of {@link RedisConnection#scriptingCommands()}. */ + @Override + @Deprecated + default String scriptLoad(byte[] script) { + return scriptingCommands().scriptLoad(script); + } + + /** @deprecated in favor of {@link RedisConnection#scriptingCommands()}. */ + @Override + @Deprecated + default List scriptExists(String... scriptShas) { + return scriptingCommands().scriptExists(scriptShas); + } + + /** @deprecated in favor of {@link RedisConnection#scriptingCommands()}. */ + @Override + @Deprecated + default T eval(byte[] script, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { + return scriptingCommands().eval(script, returnType, numKeys, keysAndArgs); + } + + /** @deprecated in favor of {@link RedisConnection#scriptingCommands()}. */ + @Override + @Deprecated + default T evalSha(String scriptSha, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { + return scriptingCommands().evalSha(scriptSha, returnType, numKeys, keysAndArgs); + } + + /** @deprecated in favor of {@link RedisConnection#scriptingCommands()}. */ + @Override + @Deprecated + default T evalSha(byte[] scriptSha, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { + return scriptingCommands().evalSha(scriptSha, returnType, numKeys, keysAndArgs); + } } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisClusterConnection.java b/src/main/java/org/springframework/data/redis/connection/RedisClusterConnection.java index 894f77823..765268fe3 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisClusterConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisClusterConnection.java @@ -15,23 +15,19 @@ */ package org.springframework.data.redis.connection; -import java.util.List; -import java.util.Properties; import java.util.Set; -import org.springframework.data.redis.core.types.RedisClientInfo; - /** * {@link RedisClusterConnection} allows sending commands to dedicated nodes within the cluster. A * {@link RedisClusterNode} can be obtained from {@link #clusterGetNodes()} or it can be constructed using either * {@link RedisClusterNode#getHost() host} and {@link RedisClusterNode#getPort()} or the {@link RedisClusterNode#getId() * node Id}. - * + * * @author Christoph Strobl * @author Mark Paluch * @since 1.7 */ -public interface RedisClusterConnection extends RedisConnection, RedisClusterCommands { +public interface RedisClusterConnection extends RedisConnection, RedisClusterCommands, RedisClusterServerCommands { /** * @param node must not be {@literal null}. @@ -40,65 +36,6 @@ public interface RedisClusterConnection extends RedisConnection, RedisClusterCom */ String ping(RedisClusterNode node); - /** - * @param node must not be {@literal null}. - * @see RedisServerCommands#bgReWriteAof() - */ - void bgReWriteAof(RedisClusterNode node); - - /** - * @param node must not be {@literal null}. - * @see RedisServerCommands#bgSave() - */ - void bgSave(RedisClusterNode node); - - /** - * @param node must not be {@literal null}. - * @return - * @see RedisServerCommands#lastSave() - */ - Long lastSave(RedisClusterNode node); - - /** - * @param node must not be {@literal null}. - * @see RedisServerCommands#save() - */ - void save(RedisClusterNode node); - - /** - * @param node must not be {@literal null}. - * @return - * @see RedisServerCommands#dbSize() - */ - Long dbSize(RedisClusterNode node); - - /** - * @param node must not be {@literal null}. - * @see RedisServerCommands#flushDb() - */ - void flushDb(RedisClusterNode node); - - /** - * @param node must not be {@literal null}. - * @see RedisServerCommands#flushAll() - */ - void flushAll(RedisClusterNode node); - - /** - * @param node must not be {@literal null}. - * @return - * @see RedisServerCommands#info() - */ - Properties info(RedisClusterNode node); - - /** - * @param node must not be {@literal null}. - * @param section - * @return - * @see RedisServerCommands#info(String) - */ - Properties info(RedisClusterNode node, String section); - /** * @param node must not be {@literal null}. * @param pattern must not be {@literal null}. @@ -115,45 +52,12 @@ public interface RedisClusterConnection extends RedisConnection, RedisClusterCom byte[] randomKey(RedisClusterNode node); /** - * @param node must not be {@literal null}. - * @see RedisServerCommands#shutdown() + * Get {@link RedisClusterServerCommands}. + * + * @return never {@literal null}. + * @since 2.0 */ - void shutdown(RedisClusterNode node); - - /** - * @param node must not be {@literal null}. - * @param pattern - * @return - * @see RedisServerCommands#getConfig(String) - */ - List getConfig(RedisClusterNode node, String pattern); - - /** - * @param node must not be {@literal null}. - * @param param - * @param value - * @see RedisServerCommands#setConfig(String, String) - */ - void setConfig(RedisClusterNode node, String param, String value); - - /** - * @param node must not be {@literal null}. - * @see RedisServerCommands#resetConfigStats() - */ - void resetConfigStats(RedisClusterNode node); - - /** - * @param node must not be {@literal null}. - * @return - * @see RedisServerCommands#time() - */ - Long time(RedisClusterNode node); - - /** - * @param node must not be {@literal null}. - * @return - * @see RedisServerCommands#getClientList() - */ - public List getClientList(RedisClusterNode node); - + default RedisClusterServerCommands serverCommands() { + return this; + } } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisClusterServerCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisClusterServerCommands.java new file mode 100644 index 000000000..7c5c1b698 --- /dev/null +++ b/src/main/java/org/springframework/data/redis/connection/RedisClusterServerCommands.java @@ -0,0 +1,129 @@ +/* + * Copyright 2017 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 java.util.List; +import java.util.Properties; + +import org.springframework.data.redis.core.types.RedisClientInfo; + +/** + * @author Mark Paluch + * @since 2.0 + */ +public interface RedisClusterServerCommands extends RedisServerCommands { + + /** + * @param node must not be {@literal null}. + * @see RedisServerCommands#bgReWriteAof() + */ + void bgReWriteAof(RedisClusterNode node); + + /** + * @param node must not be {@literal null}. + * @see RedisServerCommands#bgSave() + */ + void bgSave(RedisClusterNode node); + + /** + * @param node must not be {@literal null}. + * @return + * @see RedisServerCommands#lastSave() + */ + Long lastSave(RedisClusterNode node); + + /** + * @param node must not be {@literal null}. + * @see RedisServerCommands#save() + */ + void save(RedisClusterNode node); + + /** + * @param node must not be {@literal null}. + * @return + * @see RedisServerCommands#dbSize() + */ + Long dbSize(RedisClusterNode node); + + /** + * @param node must not be {@literal null}. + * @see RedisServerCommands#flushDb() + */ + void flushDb(RedisClusterNode node); + + /** + * @param node must not be {@literal null}. + * @see RedisServerCommands#flushAll() + */ + void flushAll(RedisClusterNode node); + + /** + * @param node must not be {@literal null}. + * @return + * @see RedisServerCommands#info() + */ + Properties info(RedisClusterNode node); + + /** + * @param node must not be {@literal null}. + * @param section + * @return + * @see RedisServerCommands#info(String) + */ + Properties info(RedisClusterNode node, String section); + + /** + * @param node must not be {@literal null}. + * @see RedisServerCommands#shutdown() + */ + void shutdown(RedisClusterNode node); + + /** + * @param node must not be {@literal null}. + * @param pattern + * @return + * @see RedisServerCommands#getConfig(String) + */ + List getConfig(RedisClusterNode node, String pattern); + + /** + * @param node must not be {@literal null}. + * @param param + * @param value + * @see RedisServerCommands#setConfig(String, String) + */ + void setConfig(RedisClusterNode node, String param, String value); + + /** + * @param node must not be {@literal null}. + * @see RedisServerCommands#resetConfigStats() + */ + void resetConfigStats(RedisClusterNode node); + + /** + * @param node must not be {@literal null}. + * @return + * @see RedisServerCommands#time() + */ + Long time(RedisClusterNode node); + + /** + * @param node must not be {@literal null}. + * @return + * @see RedisServerCommands#getClientList() + */ + List getClientList(RedisClusterNode node); +} diff --git a/src/main/java/org/springframework/data/redis/connection/RedisConnection.java b/src/main/java/org/springframework/data/redis/connection/RedisConnection.java index 148b067e9..e4dda08c6 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisConnection.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.redis.connection; import java.util.List; @@ -24,9 +23,10 @@ import org.springframework.dao.DataAccessException; * A connection to a Redis server. Acts as an common abstraction across various Redis client libraries (or drivers). * Additionally performs exception translation between the underlying Redis client library and Spring DAO exceptions. * The methods follow as much as possible the Redis names and conventions. - * + * * @author Costin Leau * @author Christoph Strobl + * @author Mark Paluch */ public interface RedisConnection extends RedisCommands { @@ -34,6 +34,7 @@ public interface RedisConnection extends RedisCommands { * Get {@link RedisGeoCommands}. * * @return never {@literal null}. + * @since 2.0 */ default RedisGeoCommands geoCommands() { return this; @@ -53,6 +54,7 @@ public interface RedisConnection extends RedisCommands { * Get {@link RedisHyperLogLogCommands}. * * @return never {@literal null}. + * @since 2.0 */ default RedisHyperLogLogCommands hyperLogLogCommands() { return this; @@ -88,6 +90,26 @@ public interface RedisConnection extends RedisCommands { return this; } + /** + * Get {@link RedisScriptingCommands}. + * + * @return never {@literal null}. + * @since 2.0 + */ + default RedisScriptingCommands scriptingCommands() { + return this; + } + + /** + * Get {@link RedisServerCommands}. + * + * @return never {@literal null}. + * @since 2.0 + */ + default RedisServerCommands serverCommands() { + return this; + } + /** * Get {@link RedisStringCommands}. * @@ -110,21 +132,21 @@ public interface RedisConnection extends RedisCommands { /** * Closes (or quits) the connection. - * + * * @throws DataAccessException */ void close() throws DataAccessException; /** * Indicates whether the underlying connection is closed or not. - * + * * @return true if the connection is closed, false otherwise. */ boolean isClosed(); /** * Returns the native connection (the underlying library/driver object). - * + * * @return underlying, native object */ Object getNativeConnection(); @@ -133,14 +155,14 @@ public interface RedisConnection extends RedisCommands { * Indicates whether the connection is in "queue"(or "MULTI") mode or not. When queueing, all commands are postponed * until EXEC or DISCARD commands are issued. Since in queueing no results are returned, the connection will return * NULL on all operations that interact with the data. - * + * * @return true if the connection is in queue/MULTI mode, false otherwise */ boolean isQueueing(); /** * Indicates whether the connection is currently pipelined or not. - * + * * @return true if the connection is pipelined, false otherwise * @see #openPipeline() * @see #isQueueing() @@ -158,7 +180,7 @@ public interface RedisConnection extends RedisCommands { *

* Consider doing some performance testing before using this feature since in many cases the performance benefits are * minimal yet the impact on usage are not. - * + * * @see #multi() */ void openPipeline(); @@ -166,7 +188,7 @@ public interface RedisConnection extends RedisCommands { /** * Executes the commands in the pipeline and returns their result. If the connection is not pipelined, an empty * collection is returned. - * + * * @throws RedisPipelineException if the pipeline contains any incorrect/invalid statements * @return the result of the executed commands. */ diff --git a/src/main/java/org/springframework/data/redis/connection/RedisServerCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisServerCommands.java index fe9e3f269..e9c5d9cee 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisServerCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisServerCommands.java @@ -1,12 +1,12 @@ /* * Copyright 2011-2017 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. @@ -22,7 +22,7 @@ import org.springframework.data.redis.core.types.RedisClientInfo; /** * Server-specific commands supported by Redis. - * + * * @author Costin Leau * @author Christoph Strobl * @author Thomas Darimont @@ -43,12 +43,14 @@ public interface RedisServerCommands { /** * Start an {@literal Append Only File} rewrite process on server. - * + * * @deprecated As of 1.3, use {@link #bgReWriteAof}. * @see Redis Documentation: BGREWRITEAOF */ @Deprecated - void bgWriteAof(); + default void bgWriteAof() { + bgReWriteAof(); + } /** * Start an {@literal Append Only File} rewrite process on server. @@ -110,7 +112,7 @@ public interface RedisServerCommands { *
  • replication
  • * *

    - * + * * @return * @see Redis Documentation: INFO */ @@ -167,7 +169,7 @@ public interface RedisServerCommands { /** * Request server timestamp using {@code TIME} command. - * + * * @return current server time in milliseconds. * @since 1.1 * @see Redis Documentation: TIME @@ -176,7 +178,7 @@ public interface RedisServerCommands { /** * Closes a given client connection identified by {@literal host:port}. - * + * * @param host of connection to close. * @param port of connection to close * @since 1.3 @@ -186,7 +188,7 @@ public interface RedisServerCommands { /** * Assign given name to current connection. - * + * * @param name * @since 1.3 * @see Redis Documentation: CLIENT SETNAME @@ -232,7 +234,7 @@ public interface RedisServerCommands { /** * Atomically transfer a key from a source Redis instance to a destination Redis instance. On success the key is * deleted from the original instance and is guaranteed to exist in the target instance. - * + * * @param key must not be {@literal null}. * @param target must not be {@literal null}. * @param dbIndex diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterConnection.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterConnection.java index b8ffb96ae..608bd9d52 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterConnection.java @@ -15,20 +15,18 @@ */ package org.springframework.data.redis.connection.jedis; +import redis.clients.jedis.BinaryJedis; import redis.clients.jedis.BinaryJedisPubSub; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisCluster; import redis.clients.jedis.JedisPool; -import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Properties; import java.util.Set; import org.springframework.beans.DirectFieldAccessor; @@ -37,37 +35,13 @@ import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.redis.ClusterStateFailureException; import org.springframework.data.redis.ExceptionTranslationStrategy; import org.springframework.data.redis.PassThroughExceptionTranslationStrategy; -import org.springframework.data.redis.connection.ClusterCommandExecutor; +import org.springframework.data.redis.connection.*; import org.springframework.data.redis.connection.ClusterCommandExecutor.ClusterCommandCallback; import org.springframework.data.redis.connection.ClusterCommandExecutor.MultiKeyClusterCommandCallback; import org.springframework.data.redis.connection.ClusterCommandExecutor.NodeResult; -import org.springframework.data.redis.connection.ClusterInfo; -import org.springframework.data.redis.connection.ClusterNodeResourceProvider; -import org.springframework.data.redis.connection.ClusterTopology; -import org.springframework.data.redis.connection.ClusterTopologyProvider; -import org.springframework.data.redis.connection.DefaultedRedisClusterConnection; -import org.springframework.data.redis.connection.MessageListener; -import org.springframework.data.redis.connection.RedisClusterConnection; -import org.springframework.data.redis.connection.RedisClusterNode; import org.springframework.data.redis.connection.RedisClusterNode.SlotRange; -import org.springframework.data.redis.connection.RedisGeoCommands; -import org.springframework.data.redis.connection.RedisHashCommands; -import org.springframework.data.redis.connection.RedisHyperLogLogCommands; -import org.springframework.data.redis.connection.RedisKeyCommands; -import org.springframework.data.redis.connection.RedisListCommands; -import org.springframework.data.redis.connection.RedisNode; -import org.springframework.data.redis.connection.RedisPipelineException; -import org.springframework.data.redis.connection.RedisSentinelConnection; -import org.springframework.data.redis.connection.RedisSetCommands; -import org.springframework.data.redis.connection.RedisStringCommands; -import org.springframework.data.redis.connection.RedisSubscribedConnectionException; -import org.springframework.data.redis.connection.RedisZSetCommands; -import org.springframework.data.redis.connection.ReturnType; -import org.springframework.data.redis.connection.Subscription; import org.springframework.data.redis.connection.convert.Converters; -import org.springframework.data.redis.core.types.RedisClientInfo; import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; /** * {@link RedisClusterConnection} implementation on top of {@link JedisCluster}.
    @@ -95,7 +69,7 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { /** * Create new {@link JedisClusterConnection} utilizing native connections via {@link JedisCluster}. - * + * * @param cluster must not be {@literal null}. */ public JedisClusterConnection(JedisCluster cluster) { @@ -147,46 +121,96 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { throw new UnsupportedOperationException("Execute is currently not supported in cluster mode."); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#geoCommands() + */ @Override public RedisGeoCommands geoCommands() { return new JedisClusterGeoCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#hashCommands() + */ @Override public RedisHashCommands hashCommands() { return new JedisClusterHashCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#hyperLogLogCommands() + */ @Override public RedisHyperLogLogCommands hyperLogLogCommands() { return new JedisClusterHyperLogLogCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#keyCommands() + */ @Override public RedisKeyCommands keyCommands() { return doGetKeyCommands(); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#stringCommands() + */ @Override public RedisStringCommands stringCommands() { return new JedisClusterStringCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#listCommands() + */ @Override public RedisListCommands listCommands() { return new JedisClusterListCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#setCommands() + */ @Override public RedisSetCommands setCommands() { return new JedisClusterSetCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#zSetCommands() + */ @Override public RedisZSetCommands zSetCommands() { return new JedisClusterZSetCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterConnection#serverCommands() + */ + @Override + public RedisClusterServerCommands serverCommands() { + return new JedisClusterServerCommands(this); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#scriptingCommands() + */ + @Override + public RedisScriptingCommands scriptingCommands() { + return JedisClusterScriptingCommands.INSTANCE; + } + private JedisClusterKeyCommands doGetKeyCommands() { return new JedisClusterKeyCommands(this); } @@ -342,13 +366,9 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { @Override public String ping() { - return !clusterCommandExecutor.executeCommandOnAllNodes(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.ping(); - } - }).resultsAsList().isEmpty() ? "PONG" : null; + return !clusterCommandExecutor + .executeCommandOnAllNodes((JedisClusterCommandCallback) BinaryJedis::ping).resultsAsList() + .isEmpty() ? "PONG" : null; } @@ -359,717 +379,8 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { @Override public String ping(RedisClusterNode node) { - return clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.ping(); - } - }, node).getValue(); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#bgWriteAof() - */ - @Override - public void bgWriteAof() { - - clusterCommandExecutor.executeCommandOnAllNodes(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.bgrewriteaof(); - } - }); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#bgReWriteAof(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public void bgReWriteAof(RedisClusterNode node) { - - clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.bgrewriteaof(); - } - }, node); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#bgReWriteAof() - */ - @Override - public void bgReWriteAof() { - - clusterCommandExecutor.executeCommandOnAllNodes(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.bgrewriteaof(); - } - }); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#bgSave() - */ - @Override - public void bgSave() { - - clusterCommandExecutor.executeCommandOnAllNodes(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.bgsave(); - } - }); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#bgSave(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public void bgSave(RedisClusterNode node) { - - clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.bgsave(); - } - }, node); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#lastSave() - */ - @Override - public Long lastSave() { - - List result = new ArrayList( - clusterCommandExecutor.executeCommandOnAllNodes(new JedisClusterCommandCallback() { - - @Override - public Long doInCluster(Jedis client) { - return client.lastsave(); - } - }).resultsAsList()); - - if (CollectionUtils.isEmpty(result)) { - return null; - } - - Collections.sort(result, Collections.reverseOrder()); - return result.get(0); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#lastSave(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public Long lastSave(RedisClusterNode node) { - - return clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public Long doInCluster(Jedis client) { - return client.lastsave(); - } - }, node).getValue(); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#save() - */ - @Override - public void save() { - - clusterCommandExecutor.executeCommandOnAllNodes(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.save(); - } - }); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#save(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public void save(RedisClusterNode node) { - - clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.save(); - } - }, node); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#dbSize() - */ - @Override - public Long dbSize() { - - Collection dbSizes = clusterCommandExecutor.executeCommandOnAllNodes(new JedisClusterCommandCallback() { - - @Override - public Long doInCluster(Jedis client) { - return client.dbSize(); - } - }).resultsAsList(); - - if (CollectionUtils.isEmpty(dbSizes)) { - return 0L; - } - - Long size = 0L; - for (Long value : dbSizes) { - size += value; - } - return size; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#dbSize(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public Long dbSize(RedisClusterNode node) { - - return clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public Long doInCluster(Jedis client) { - return client.dbSize(); - } - }, node).getValue(); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#flushDb() - */ - @Override - public void flushDb() { - - clusterCommandExecutor.executeCommandOnAllNodes(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.flushDB(); - } - }); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#flushDb(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public void flushDb(RedisClusterNode node) { - - clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.flushDB(); - } - }, node); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#flushAll() - */ - @Override - public void flushAll() { - - clusterCommandExecutor.executeCommandOnAllNodes(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.flushAll(); - } - }); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#flushAll(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public void flushAll(RedisClusterNode node) { - - clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.flushAll(); - } - }, node); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#info() - */ - @Override - public Properties info() { - - Properties infos = new Properties(); - - List> nodeResults = clusterCommandExecutor - .executeCommandOnAllNodes(new JedisClusterCommandCallback() { - - @Override - public Properties doInCluster(Jedis client) { - return JedisConverters.toProperties(client.info()); - } - }).getResults(); - - for (NodeResult nodePorperties : nodeResults) { - for (Entry entry : nodePorperties.getValue().entrySet()) { - infos.put(nodePorperties.getNode().asString() + "." + entry.getKey(), entry.getValue()); - } - } - - return infos; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#info(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public Properties info(RedisClusterNode node) { - - return JedisConverters - .toProperties(clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.info(); - } - }, node).getValue()); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#info(java.lang.String) - */ - @Override - public Properties info(final String section) { - - Properties infos = new Properties(); - - List> nodeResults = clusterCommandExecutor - .executeCommandOnAllNodes(new JedisClusterCommandCallback() { - - @Override - public Properties doInCluster(Jedis client) { - return JedisConverters.toProperties(client.info(section)); - } - }).getResults(); - - for (NodeResult nodePorperties : nodeResults) { - for (Entry entry : nodePorperties.getValue().entrySet()) { - infos.put(nodePorperties.getNode().asString() + "." + entry.getKey(), entry.getValue()); - } - } - - return infos; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#info(org.springframework.data.redis.connection.RedisClusterNode, java.lang.String) - */ - @Override - public Properties info(RedisClusterNode node, final String section) { - - return JedisConverters - .toProperties(clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.info(section); - } - }, node).getValue()); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#shutdown() - */ - @Override - public void shutdown() { - - clusterCommandExecutor.executeCommandOnAllNodes(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.shutdown(); - } - }); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#shutdown(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public void shutdown(RedisClusterNode node) { - - clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.shutdown(); - } - }, node); - - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#shutdown(org.springframework.data.redis.connection.RedisServerCommands.ShutdownOption) - */ - @Override - public void shutdown(ShutdownOption option) { - - if (option == null) { - shutdown(); - return; - } - - throw new IllegalArgumentException("Shutdown with options is not supported for jedis."); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#getConfig(java.lang.String) - */ - @Override - public List getConfig(final String pattern) { - - List>> mapResult = clusterCommandExecutor - .executeCommandOnAllNodes(new JedisClusterCommandCallback>() { - - @Override - public List doInCluster(Jedis client) { - return client.configGet(pattern); - } - }).getResults(); - - List result = new ArrayList(); - for (NodeResult> entry : mapResult) { - - String prefix = entry.getNode().asString(); - int i = 0; - for (String value : entry.getValue()) { - result.add((i++ % 2 == 0 ? (prefix + ".") : "") + value); - } - } - - return result; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#getConfig(org.springframework.data.redis.connection.RedisClusterNode, java.lang.String) - */ - @Override - public List getConfig(RedisClusterNode node, final String pattern) { - - return clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback>() { - - @Override - public List doInCluster(Jedis client) { - return client.configGet(pattern); - } - }, node).getValue(); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#setConfig(java.lang.String, java.lang.String) - */ - @Override - public void setConfig(final String param, final String value) { - - clusterCommandExecutor.executeCommandOnAllNodes(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.configSet(param, value); - } - }); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#setConfig(org.springframework.data.redis.connection.RedisClusterNode, java.lang.String, java.lang.String) - */ - @Override - public void setConfig(RedisClusterNode node, final String param, final String value) { - - clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.configSet(param, value); - } - }, node); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#resetConfigStats() - */ - @Override - public void resetConfigStats() { - - clusterCommandExecutor.executeCommandOnAllNodes(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.configResetStat(); - } - }); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#resetConfigStats(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public void resetConfigStats(RedisClusterNode node) { - - clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.configResetStat(); - } - }, node); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#time() - */ - @Override - public Long time() { - - return convertListOfStringToTime( - clusterCommandExecutor.executeCommandOnArbitraryNode(new JedisClusterCommandCallback>() { - - @Override - public List doInCluster(Jedis client) { - return client.time(); - } - }).getValue()); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#time(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public Long time(RedisClusterNode node) { - - return convertListOfStringToTime( - clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback>() { - - @Override - public List doInCluster(Jedis client) { - return client.time(); - } - }, node).getValue()); - } - - private Long convertListOfStringToTime(List serverTimeInformation) { - - Assert.notEmpty(serverTimeInformation, "Received invalid result from server. Expected 2 items in collection."); - Assert.isTrue(serverTimeInformation.size() == 2, - "Received invalid number of arguments from redis server. Expected 2 received " + serverTimeInformation.size()); - - return Converters.toTimeMillis(serverTimeInformation.get(0), serverTimeInformation.get(1)); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#killClient(java.lang.String, int) - */ - @Override - public void killClient(String host, int port) { - - final String hostAndPort = String.format("%s:%s", host, port); - - clusterCommandExecutor.executeCommandOnAllNodes(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.clientKill(hostAndPort); - } - }); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#setClientName(byte[]) - */ - @Override - public void setClientName(byte[] name) { - throw new InvalidDataAccessApiUsageException("CLIENT SETNAME is not supported in cluster environment."); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#getClientName() - */ - @Override - public String getClientName() { - throw new InvalidDataAccessApiUsageException("CLIENT GETNAME is not supported in cluster environment."); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#getClientList() - */ - @Override - public List getClientList() { - - Collection map = clusterCommandExecutor.executeCommandOnAllNodes(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.clientList(); - } - }).resultsAsList(); - - ArrayList result = new ArrayList(); - for (String infos : map) { - result.addAll(JedisConverters.toListOfRedisClientInformation(infos)); - } - return result; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#getClientList(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public List getClientList(RedisClusterNode node) { - - return JedisConverters.toListOfRedisClientInformation( - clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.clientList(); - } - }, node).getValue()); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#slaveOf(java.lang.String, int) - */ - @Override - public void slaveOf(String host, int port) { - throw new InvalidDataAccessApiUsageException( - "SlaveOf is not supported in cluster environment. Please use CLUSTER REPLICATE."); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#slaveOfNoOne() - */ - @Override - public void slaveOfNoOne() { - throw new InvalidDataAccessApiUsageException( - "SlaveOf is not supported in cluster environment. Please use CLUSTER REPLICATE."); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptFlush() - */ - @Override - public void scriptFlush() { - throw new InvalidDataAccessApiUsageException("ScriptFlush is not supported in cluster environment."); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptKill() - */ - @Override - public void scriptKill() { - throw new InvalidDataAccessApiUsageException("ScriptKill is not supported in cluster environment."); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptLoad(byte[]) - */ - @Override - public String scriptLoad(byte[] script) { - throw new InvalidDataAccessApiUsageException("ScriptLoad is not supported in cluster environment."); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptExists(java.lang.String[]) - */ - @Override - public List scriptExists(String... scriptShas) { - throw new InvalidDataAccessApiUsageException("ScriptExists is not supported in cluster environment."); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisScriptingCommands#eval(byte[], org.springframework.data.redis.connection.ReturnType, int, byte[][]) - */ - @Override - public T eval(byte[] script, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { - throw new InvalidDataAccessApiUsageException("Eval is not supported in cluster environment."); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisScriptingCommands#evalSha(java.lang.String, org.springframework.data.redis.connection.ReturnType, int, byte[][]) - */ - @Override - public T evalSha(String scriptSha, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { - throw new InvalidDataAccessApiUsageException("EvalSha is not supported in cluster environment."); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisScriptingCommands#evalSha(byte[], org.springframework.data.redis.connection.ReturnType, int, byte[][]) - */ - @Override - public T evalSha(byte[] scriptSha, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { - throw new InvalidDataAccessApiUsageException("EvalSha is not supported in cluster environment."); + return clusterCommandExecutor + .executeCommandOnSingleNode((JedisClusterCommandCallback) BinaryJedis::ping, node).getValue(); } /* @@ -1089,24 +400,20 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { final RedisClusterNode nodeToUse = topologyProvider.getTopology().lookup(node); final String nodeId = nodeToUse.getId(); - clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { + clusterCommandExecutor.executeCommandOnSingleNode((JedisClusterCommandCallback) client -> { - @Override - public String doInCluster(Jedis client) { - - switch (mode) { - case IMPORTING: - return client.clusterSetSlotImporting(slot, nodeId); - case MIGRATING: - return client.clusterSetSlotMigrating(slot, nodeId); - case STABLE: - return client.clusterSetSlotStable(slot); - case NODE: - return client.clusterSetSlotNode(slot, nodeId); - } - - throw new IllegalArgumentException(String.format("Unknown AddSlots mode '%s'.", mode)); + switch (mode) { + case IMPORTING: + return client.clusterSetSlotImporting(slot, nodeId); + case MIGRATING: + return client.clusterSetSlotMigrating(slot, nodeId); + case STABLE: + return client.clusterSetSlotStable(slot); + case NODE: + return client.clusterSetSlotNode(slot, nodeId); } + + throw new IllegalArgumentException(String.format("Unknown AddSlots mode '%s'.", mode)); }, node); } @@ -1120,14 +427,11 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { RedisClusterNode node = clusterGetNodeForSlot(slot); - clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback>() { - - @Override - public List doInCluster(Jedis client) { - return JedisConverters.stringListToByteList() - .convert(client.clusterGetKeysInSlot(slot, count != null ? count.intValue() : Integer.MAX_VALUE)); - } - }, node); + clusterCommandExecutor + .executeCommandOnSingleNode( + (JedisClusterCommandCallback>) client -> JedisConverters.stringListToByteList() + .convert(client.clusterGetKeysInSlot(slot, count != null ? count.intValue() : Integer.MAX_VALUE)), + node); return null; } @@ -1138,14 +442,8 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { @Override public void clusterAddSlots(RedisClusterNode node, final int... slots) { - clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - - return client.clusterAddSlots(slots); - } - }, node); + clusterCommandExecutor.executeCommandOnSingleNode( + (JedisClusterCommandCallback) client -> client.clusterAddSlots(slots), node); } @@ -1170,14 +468,8 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { RedisClusterNode node = clusterGetNodeForSlot(slot); - return clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public Long doInCluster(Jedis client) { - - return client.clusterCountKeysInSlot(slot); - } - }, node).getValue(); + return clusterCommandExecutor.executeCommandOnSingleNode( + (JedisClusterCommandCallback) client -> client.clusterCountKeysInSlot(slot), node).getValue(); } @@ -1188,13 +480,8 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { @Override public void clusterDeleteSlots(RedisClusterNode node, final int... slots) { - clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.clusterDelSlots(slots); - } - }, node); + clusterCommandExecutor.executeCommandOnSingleNode( + (JedisClusterCommandCallback) client -> client.clusterDelSlots(slots), node); } @@ -1217,18 +504,12 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { @Override public void clusterForget(final RedisClusterNode node) { - Set nodes = new LinkedHashSet( - topologyProvider.getTopology().getActiveMasterNodes()); + Set nodes = new LinkedHashSet<>(topologyProvider.getTopology().getActiveMasterNodes()); final RedisClusterNode nodeToRemove = topologyProvider.getTopology().lookup(node); nodes.remove(nodeToRemove); - clusterCommandExecutor.executeCommandAsyncOnNodes(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.clusterForget(node.getId()); - } - }, nodes); + clusterCommandExecutor.executeCommandAsyncOnNodes( + (JedisClusterCommandCallback) client -> client.clusterForget(node.getId()), nodes); } /* @@ -1242,14 +523,8 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { Assert.hasText(node.getHost(), "Node to meet cluster must have a host!"); Assert.isTrue(node.getPort() > 0, "Node to meet cluster must have a port greater 0!"); - clusterCommandExecutor.executeCommandOnAllNodes(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - - return client.clusterMeet(node.getHost(), node.getPort()); - } - }); + clusterCommandExecutor.executeCommandOnAllNodes( + (JedisClusterCommandCallback) client -> client.clusterMeet(node.getHost(), node.getPort())); } /* @@ -1261,14 +536,8 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { final RedisClusterNode masterNode = topologyProvider.getTopology().lookup(master); - clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - - return client.clusterReplicate(masterNode.getId()); - } - }, slave); + clusterCommandExecutor.executeCommandOnSingleNode( + (JedisClusterCommandCallback) client -> client.clusterReplicate(masterNode.getId()), slave); } @@ -1279,13 +548,8 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { @Override public Integer clusterGetSlotForKey(final byte[] key) { - return clusterCommandExecutor.executeCommandOnArbitraryNode(new JedisClusterCommandCallback() { - - @Override - public Integer doInCluster(Jedis client) { - return client.clusterKeySlot(JedisConverters.toString(key)).intValue(); - } - }).getValue(); + return clusterCommandExecutor.executeCommandOnArbitraryNode((JedisClusterCommandCallback) client -> client + .clusterKeySlot(JedisConverters.toString(key)).intValue()).getValue(); } /* @@ -1325,13 +589,10 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { final RedisClusterNode nodeToUse = topologyProvider.getTopology().lookup(master); return JedisConverters.toSetOfRedisClusterNodes( - clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback>() { - - @Override - public List doInCluster(Jedis client) { - return client.clusterSlaves(nodeToUse.getId()); - } - }, master).getValue()); + clusterCommandExecutor + .executeCommandOnSingleNode( + (JedisClusterCommandCallback>) client -> client.clusterSlaves(nodeToUse.getId()), master) + .getValue()); } /* @@ -1342,18 +603,14 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { public Map> clusterGetMasterSlaveMap() { List>> nodeResults = clusterCommandExecutor - .executeCommandAsyncOnNodes(new JedisClusterCommandCallback>() { + .executeCommandAsyncOnNodes((JedisClusterCommandCallback>) client -> { - @Override - public Set doInCluster(Jedis client) { - - // TODO: remove client.eval as soon as Jedis offers support for myid - return JedisConverters.toSetOfRedisClusterNodes( - client.clusterSlaves((String) client.eval("return redis.call('cluster', 'myid')", 0))); - } + // TODO: remove client.eval as soon as Jedis offers support for myid + return JedisConverters.toSetOfRedisClusterNodes( + client.clusterSlaves((String) client.eval("return redis.call('cluster', 'myid')", 0))); }, topologyProvider.getTopology().getActiveMasterNodes()).getResults(); - Map> result = new LinkedHashMap>(); + Map> result = new LinkedHashMap<>(); for (NodeResult> nodeResult : nodeResults) { result.put(nodeResult.getNode(), nodeResult.getValue()); @@ -1379,43 +636,9 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { public ClusterInfo clusterGetClusterInfo() { return new ClusterInfo(JedisConverters - .toProperties(clusterCommandExecutor.executeCommandOnArbitraryNode(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.clusterInfo(); - } - }).getValue())); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption) - */ - @Override - public void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option) { - migrate(key, target, dbIndex, option, Long.MAX_VALUE); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption, long) - */ - @Override - public void migrate(final byte[] key, final RedisNode target, final int dbIndex, final MigrateOption option, - final long timeout) { - - final int timeoutToUse = timeout <= Integer.MAX_VALUE ? (int) timeout : Integer.MAX_VALUE; - - RedisClusterNode node = topologyProvider.getTopology().lookup(target.getHost(), target.getPort()); - - clusterCommandExecutor.executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.migrate(JedisConverters.toBytes(target.getHost()), target.getPort(), key, dbIndex, timeoutToUse); - } - }, node); + .toProperties(clusterCommandExecutor + .executeCommandOnArbitraryNode((JedisClusterCommandCallback) Jedis::clusterInfo) + .getValue())); } /* @@ -1607,7 +830,7 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { return cached; } - Map errors = new LinkedHashMap(); + Map errors = new LinkedHashMap<>(); for (Entry entry : cluster.getClusterNodes().entrySet()) { diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterGeoCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterGeoCommands.java index 5a631d6fb..d81390e45 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterGeoCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterGeoCommands.java @@ -72,7 +72,7 @@ class JedisClusterGeoCommands implements RedisGeoCommands { Assert.notNull(key, "Key must not be null!"); Assert.notNull(memberCoordinateMap, "MemberCoordinateMap must not be null!"); - Map redisGeoCoordinateMap = new HashMap(); + Map redisGeoCoordinateMap = new HashMap<>(); for (byte[] mapKey : memberCoordinateMap.keySet()) { redisGeoCoordinateMap.put(mapKey, JedisConverters.toGeoCoordinate(memberCoordinateMap.get(mapKey))); } @@ -94,7 +94,7 @@ class JedisClusterGeoCommands implements RedisGeoCommands { Assert.notNull(key, "Key must not be null!"); Assert.notNull(locations, "Locations must not be null!"); - Map redisGeoCoordinateMap = new HashMap(); + Map redisGeoCoordinateMap = new HashMap<>(); for (GeoLocation location : locations) { redisGeoCoordinateMap.put(location.getName(), JedisConverters.toGeoCoordinate(location.getPoint())); } diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterHashCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterHashCommands.java index 7c68c18da..66842439e 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterHashCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterHashCommands.java @@ -203,7 +203,7 @@ class JedisClusterHashCommands implements RedisHashCommands { public List hVals(byte[] key) { try { - return new ArrayList(connection.getCluster().hvals(key)); + return new ArrayList<>(connection.getCluster().hvals(key)); } catch (Exception ex) { throw convertJedisAccessException(ex); } diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterKeyCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterKeyCommands.java index fe100fee7..f9dc098e3 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterKeyCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterKeyCommands.java @@ -15,15 +15,13 @@ */ package org.springframework.data.redis.connection.jedis; -import redis.clients.jedis.Jedis; - import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; -import java.util.Random; import java.util.Set; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import org.springframework.dao.DataAccessException; @@ -71,14 +69,10 @@ class JedisClusterKeyCommands implements RedisKeyCommands { } } - return Long.valueOf( - connection.getClusterCommandExecutor().executeMuliKeyCommand(new JedisMultiKeyClusterCommandCallback() { - - @Override - public Long doInCluster(Jedis client, byte[] key) { - return client.del(key); - } - }, Arrays.asList(keys)).resultsAsList().size()); + return (long) connection.getClusterCommandExecutor() + .executeMuliKeyCommand((JedisMultiKeyClusterCommandCallback) (client, key) -> client.del(key), + Arrays.asList(keys)) + .resultsAsList().size(); } /* @@ -105,15 +99,10 @@ class JedisClusterKeyCommands implements RedisKeyCommands { Assert.notNull(pattern, "Pattern must not be null!"); Collection> keysPerNode = connection.getClusterCommandExecutor() - .executeCommandOnAllNodes(new JedisClusterCommandCallback>() { + .executeCommandOnAllNodes((JedisClusterCommandCallback>) client -> client.keys(pattern)) + .resultsAsList(); - @Override - public Set doInCluster(Jedis client) { - return client.keys(pattern); - } - }).resultsAsList(); - - Set keys = new HashSet(); + Set keys = new HashSet<>(); for (Set keySet : keysPerNode) { keys.addAll(keySet); } @@ -129,13 +118,8 @@ class JedisClusterKeyCommands implements RedisKeyCommands { Assert.notNull(pattern, "Pattern must not be null!"); return connection.getClusterCommandExecutor() - .executeCommandOnSingleNode(new JedisClusterCommandCallback>() { - - @Override - public Set doInCluster(Jedis client) { - return client.keys(pattern); - } - }, node).getValue(); + .executeCommandOnSingleNode((JedisClusterCommandCallback>) client -> client.keys(pattern), node) + .getValue(); } /* @@ -144,7 +128,7 @@ class JedisClusterKeyCommands implements RedisKeyCommands { */ @Override public Cursor scan(ScanOptions options) { - throw new InvalidDataAccessApiUsageException("Scan is not supported accros multiple nodes within a cluster"); + throw new InvalidDataAccessApiUsageException("Scan is not supported across multiple nodes within a cluster"); } /* @@ -154,16 +138,16 @@ class JedisClusterKeyCommands implements RedisKeyCommands { @Override public byte[] randomKey() { - List nodes = new ArrayList( + List nodes = new ArrayList<>( connection.getTopologyProvider().getTopology().getActiveMasterNodes()); - Set inspectedNodes = new HashSet(nodes.size()); + Set inspectedNodes = new HashSet<>(nodes.size()); do { - RedisClusterNode node = nodes.get(new Random().nextInt(nodes.size())); + RedisClusterNode node = nodes.get(ThreadLocalRandom.current().nextInt(nodes.size())); while (inspectedNodes.contains(node)) { - node = nodes.get(new Random().nextInt(nodes.size())); + node = nodes.get(ThreadLocalRandom.current().nextInt(nodes.size())); } inspectedNodes.add(node); byte[] key = randomKey(node); @@ -182,13 +166,9 @@ class JedisClusterKeyCommands implements RedisKeyCommands { */ public byte[] randomKey(RedisClusterNode node) { - return connection.getClusterCommandExecutor().executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public byte[] doInCluster(Jedis client) { - return client.randomBinaryKey(); - } - }, node).getValue(); + return connection.getClusterCommandExecutor() + .executeCommandOnSingleNode((JedisClusterCommandCallback) client -> client.randomBinaryKey(), node) + .getValue(); } /* @@ -361,13 +341,10 @@ class JedisClusterKeyCommands implements RedisKeyCommands { @Override public Long pTtl(final byte[] key) { - return connection.getClusterCommandExecutor().executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public Long doInCluster(Jedis client) { - return client.pttl(key); - } - }, connection.getTopologyProvider().getTopology().getKeyServingMasterNode(key)).getValue(); + return connection.getClusterCommandExecutor() + .executeCommandOnSingleNode((JedisClusterCommandCallback) client -> client.pttl(key), + connection.getTopologyProvider().getTopology().getKeyServingMasterNode(key)) + .getValue(); } /* @@ -377,13 +354,11 @@ class JedisClusterKeyCommands implements RedisKeyCommands { @Override public Long pTtl(final byte[] key, final TimeUnit timeUnit) { - return connection.getClusterCommandExecutor().executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public Long doInCluster(Jedis client) { - return Converters.millisecondsToTimeUnit(client.pttl(key), timeUnit); - } - }, connection.getTopologyProvider().getTopology().getKeyServingMasterNode(key)).getValue(); + return connection.getClusterCommandExecutor() + .executeCommandOnSingleNode( + (JedisClusterCommandCallback) client -> Converters.millisecondsToTimeUnit(client.pttl(key), timeUnit), + connection.getTopologyProvider().getTopology().getKeyServingMasterNode(key)) + .getValue(); } /* @@ -393,13 +368,10 @@ class JedisClusterKeyCommands implements RedisKeyCommands { @Override public byte[] dump(final byte[] key) { - return connection.getClusterCommandExecutor().executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public byte[] doInCluster(Jedis client) { - return client.dump(key); - } - }, connection.getTopologyProvider().getTopology().getKeyServingMasterNode(key)).getValue(); + return connection.getClusterCommandExecutor() + .executeCommandOnSingleNode((JedisClusterCommandCallback) client -> client.dump(key), + connection.getTopologyProvider().getTopology().getKeyServingMasterNode(key)) + .getValue(); } /* @@ -413,13 +385,9 @@ class JedisClusterKeyCommands implements RedisKeyCommands { throw new UnsupportedOperationException("Jedis does not support ttlInMillis exceeding Integer.MAX_VALUE."); } - connection.getClusterCommandExecutor().executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.restore(key, Long.valueOf(ttlInMillis).intValue(), serializedValue); - } - }, connection.clusterGetNodeForKey(key)); + connection.getClusterCommandExecutor() + .executeCommandOnSingleNode((JedisClusterCommandCallback) client -> client.restore(key, + Long.valueOf(ttlInMillis).intValue(), serializedValue), connection.clusterGetNodeForKey(key)); } /* diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterListCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterListCommands.java index bec9869ac..9db7bb404 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterListCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterListCommands.java @@ -15,8 +15,6 @@ */ package org.springframework.data.redis.connection.jedis; -import redis.clients.jedis.Jedis; - import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -237,13 +235,10 @@ class JedisClusterListCommands implements RedisListCommands { } return connection.getClusterCommandExecutor() - .executeMuliKeyCommand(new JedisMultiKeyClusterCommandCallback>() { - - @Override - public List doInCluster(Jedis client, byte[] key) { - return client.blpop(timeout, key); - } - }, Arrays.asList(keys)).getFirstNonNullNotEmptyOrDefault(Collections. emptyList()); + .executeMuliKeyCommand( + (JedisMultiKeyClusterCommandCallback>) (client, key) -> client.blpop(timeout, key), + Arrays.asList(keys)) + .getFirstNonNullNotEmptyOrDefault(Collections. emptyList()); } /* @@ -254,13 +249,10 @@ class JedisClusterListCommands implements RedisListCommands { public List bRPop(final int timeout, byte[]... keys) { return connection.getClusterCommandExecutor() - .executeMuliKeyCommand(new JedisMultiKeyClusterCommandCallback>() { - - @Override - public List doInCluster(Jedis client, byte[] key) { - return client.brpop(timeout, key); - } - }, Arrays.asList(keys)).getFirstNonNullNotEmptyOrDefault(Collections. emptyList()); + .executeMuliKeyCommand( + (JedisMultiKeyClusterCommandCallback>) (client, key) -> client.brpop(timeout, key), + Arrays.asList(keys)) + .getFirstNonNullNotEmptyOrDefault(Collections. emptyList()); } /* diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterScriptingCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterScriptingCommands.java new file mode 100644 index 000000000..4f774660d --- /dev/null +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterScriptingCommands.java @@ -0,0 +1,94 @@ +/* + * Copyright 2017 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.jedis; + +import java.util.List; + +import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.data.redis.connection.RedisScriptingCommands; +import org.springframework.data.redis.connection.ReturnType; + +/** + * @author Mark Paluch + * @since 2.0 + */ +enum JedisClusterScriptingCommands implements RedisScriptingCommands { + + INSTANCE; + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptFlush() + */ + @Override + public void scriptFlush() { + throw new InvalidDataAccessApiUsageException("ScriptFlush is not supported in cluster environment."); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptKill() + */ + @Override + public void scriptKill() { + throw new InvalidDataAccessApiUsageException("ScriptKill is not supported in cluster environment."); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptLoad(byte[]) + */ + @Override + public String scriptLoad(byte[] script) { + throw new InvalidDataAccessApiUsageException("ScriptLoad is not supported in cluster environment."); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptExists(java.lang.String[]) + */ + @Override + public List scriptExists(String... scriptShas) { + throw new InvalidDataAccessApiUsageException("ScriptExists is not supported in cluster environment."); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#eval(byte[], org.springframework.data.redis.connection.ReturnType, int, byte[][]) + */ + @Override + public T eval(byte[] script, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { + throw new InvalidDataAccessApiUsageException("Eval is not supported in cluster environment."); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#evalSha(java.lang.String, org.springframework.data.redis.connection.ReturnType, int, byte[][]) + */ + @Override + public T evalSha(String scriptSha, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { + throw new InvalidDataAccessApiUsageException("EvalSha is not supported in cluster environment."); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#evalSha(byte[], org.springframework.data.redis.connection.ReturnType, int, byte[][]) + */ + @Override + public T evalSha(byte[] scriptSha, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { + throw new InvalidDataAccessApiUsageException("EvalSha is not supported in cluster environment."); + } +} diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterServerCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterServerCommands.java new file mode 100644 index 000000000..48c73caba --- /dev/null +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterServerCommands.java @@ -0,0 +1,515 @@ +/* + * Copyright 2017 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.jedis; + +import redis.clients.jedis.BinaryJedis; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map.Entry; +import java.util.Properties; + +import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.data.redis.connection.ClusterCommandExecutor.MulitNodeResult; +import org.springframework.data.redis.connection.ClusterCommandExecutor.NodeResult; +import org.springframework.data.redis.connection.RedisClusterNode; +import org.springframework.data.redis.connection.RedisClusterServerCommands; +import org.springframework.data.redis.connection.RedisNode; +import org.springframework.data.redis.connection.convert.Converters; +import org.springframework.data.redis.connection.jedis.JedisClusterConnection.JedisClusterCommandCallback; +import org.springframework.data.redis.core.types.RedisClientInfo; +import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; + +/** + * @author Mark Paluch + * @since 2.0 + */ +class JedisClusterServerCommands implements RedisClusterServerCommands { + + private final JedisClusterConnection connection; + + public JedisClusterServerCommands(JedisClusterConnection connection) { + this.connection = connection; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#bgReWriteAof(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public void bgReWriteAof(RedisClusterNode node) { + executeCommandOnSingleNode(BinaryJedis::bgrewriteaof, node); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#bgReWriteAof() + */ + @Override + public void bgReWriteAof() { + connection.getClusterCommandExecutor() + .executeCommandOnAllNodes((JedisClusterCommandCallback) BinaryJedis::bgrewriteaof); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#bgSave() + */ + @Override + public void bgSave() { + connection.getClusterCommandExecutor() + .executeCommandOnAllNodes((JedisClusterCommandCallback) BinaryJedis::bgsave); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#bgSave(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public void bgSave(RedisClusterNode node) { + executeCommandOnSingleNode(BinaryJedis::bgsave, node); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#lastSave() + */ + @Override + public Long lastSave() { + + List result = new ArrayList<>(executeCommandOnAllNodes(BinaryJedis::lastsave).resultsAsList()); + + if (CollectionUtils.isEmpty(result)) { + return null; + } + + Collections.sort(result, Collections.reverseOrder()); + return result.get(0); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#lastSave(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public Long lastSave(RedisClusterNode node) { + return executeCommandOnSingleNode(BinaryJedis::lastsave, node).getValue(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#save() + */ + @Override + public void save() { + executeCommandOnAllNodes(BinaryJedis::save); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#save(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public void save(RedisClusterNode node) { + executeCommandOnSingleNode(BinaryJedis::save, node); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#dbSize() + */ + @Override + public Long dbSize() { + + Collection dbSizes = executeCommandOnAllNodes(BinaryJedis::dbSize).resultsAsList(); + + if (CollectionUtils.isEmpty(dbSizes)) { + return 0L; + } + + Long size = 0L; + for (Long value : dbSizes) { + size += value; + } + return size; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#dbSize(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public Long dbSize(RedisClusterNode node) { + return executeCommandOnSingleNode(BinaryJedis::dbSize, node).getValue(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#flushDb() + */ + @Override + public void flushDb() { + executeCommandOnAllNodes(BinaryJedis::flushDB); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#flushDb(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public void flushDb(RedisClusterNode node) { + executeCommandOnSingleNode(BinaryJedis::flushDB, node); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#flushAll() + */ + @Override + public void flushAll() { + connection.getClusterCommandExecutor() + .executeCommandOnAllNodes((JedisClusterCommandCallback) BinaryJedis::flushAll); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#flushAll(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public void flushAll(RedisClusterNode node) { + executeCommandOnSingleNode(BinaryJedis::flushAll, node); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#info() + */ + @Override + public Properties info() { + + Properties infos = new Properties(); + + List> nodeResults = connection.getClusterCommandExecutor() + .executeCommandOnAllNodes( + (JedisClusterCommandCallback) client -> JedisConverters.toProperties(client.info())) + .getResults(); + + for (NodeResult nodeProperties : nodeResults) { + for (Entry entry : nodeProperties.getValue().entrySet()) { + infos.put(nodeProperties.getNode().asString() + "." + entry.getKey(), entry.getValue()); + } + } + + return infos; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#info(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public Properties info(RedisClusterNode node) { + return JedisConverters.toProperties(executeCommandOnSingleNode(BinaryJedis::info, node).getValue()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#info(java.lang.String) + */ + @Override + public Properties info(final String section) { + + Properties infos = new Properties(); + + List> nodeResults = connection.getClusterCommandExecutor() + .executeCommandOnAllNodes( + (JedisClusterCommandCallback) client -> JedisConverters.toProperties(client.info(section))) + .getResults(); + + for (NodeResult nodeProperties : nodeResults) { + for (Entry entry : nodeProperties.getValue().entrySet()) { + infos.put(nodeProperties.getNode().asString() + "." + entry.getKey(), entry.getValue()); + } + } + + return infos; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#info(org.springframework.data.redis.connection.RedisClusterNode, java.lang.String) + */ + @Override + public Properties info(RedisClusterNode node, final String section) { + + return JedisConverters.toProperties(executeCommandOnSingleNode(client -> client.info(section), node).getValue()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#shutdown() + */ + @Override + public void shutdown() { + connection.getClusterCommandExecutor() + .executeCommandOnAllNodes((JedisClusterCommandCallback) BinaryJedis::shutdown); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#shutdown(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public void shutdown(RedisClusterNode node) { + executeCommandOnSingleNode(BinaryJedis::shutdown, node); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#shutdown(org.springframework.data.redis.connection.RedisServerCommands.ShutdownOption) + */ + @Override + public void shutdown(ShutdownOption option) { + + if (option == null) { + shutdown(); + return; + } + + throw new IllegalArgumentException("Shutdown with options is not supported for jedis."); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#getConfig(java.lang.String) + */ + @Override + public List getConfig(final String pattern) { + + List>> mapResult = connection.getClusterCommandExecutor() + .executeCommandOnAllNodes((JedisClusterCommandCallback>) client -> client.configGet(pattern)) + .getResults(); + + List result = new ArrayList<>(); + for (NodeResult> entry : mapResult) { + + String prefix = entry.getNode().asString(); + int i = 0; + for (String value : entry.getValue()) { + result.add((i++ % 2 == 0 ? (prefix + ".") : "") + value); + } + } + + return result; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#getConfig(org.springframework.data.redis.connection.RedisClusterNode, java.lang.String) + */ + @Override + public List getConfig(RedisClusterNode node, final String pattern) { + + return connection.getClusterCommandExecutor().executeCommandOnSingleNode( + (JedisClusterCommandCallback>) client -> client.configGet(pattern), node).getValue(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#setConfig(java.lang.String, java.lang.String) + */ + @Override + public void setConfig(final String param, final String value) { + + connection.getClusterCommandExecutor() + .executeCommandOnAllNodes((JedisClusterCommandCallback) client -> client.configSet(param, value)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#setConfig(org.springframework.data.redis.connection.RedisClusterNode, java.lang.String, java.lang.String) + */ + @Override + public void setConfig(RedisClusterNode node, final String param, final String value) { + + executeCommandOnSingleNode(client -> client.configSet(param, value), node); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#resetConfigStats() + */ + @Override + public void resetConfigStats() { + connection.getClusterCommandExecutor() + .executeCommandOnAllNodes((JedisClusterCommandCallback) BinaryJedis::configResetStat); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#resetConfigStats(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public void resetConfigStats(RedisClusterNode node) { + executeCommandOnSingleNode(BinaryJedis::configResetStat, node); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#time() + */ + @Override + public Long time() { + + return convertListOfStringToTime(connection.getClusterCommandExecutor() + .executeCommandOnArbitraryNode((JedisClusterCommandCallback>) BinaryJedis::time).getValue()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#time(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public Long time(RedisClusterNode node) { + + return convertListOfStringToTime(connection.getClusterCommandExecutor() + .executeCommandOnSingleNode((JedisClusterCommandCallback>) BinaryJedis::time, node).getValue()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#killClient(java.lang.String, int) + */ + @Override + public void killClient(String host, int port) { + + final String hostAndPort = String.format("%s:%s", host, port); + + connection.getClusterCommandExecutor() + .executeCommandOnAllNodes((JedisClusterCommandCallback) client -> client.clientKill(hostAndPort)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#setClientName(byte[]) + */ + @Override + public void setClientName(byte[] name) { + throw new InvalidDataAccessApiUsageException("CLIENT SETNAME is not supported in cluster environment."); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#getClientName() + */ + @Override + public String getClientName() { + throw new InvalidDataAccessApiUsageException("CLIENT GETNAME is not supported in cluster environment."); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#getClientList() + */ + @Override + public List getClientList() { + + Collection map = connection.getClusterCommandExecutor() + .executeCommandOnAllNodes((JedisClusterCommandCallback) BinaryJedis::clientList).resultsAsList(); + + ArrayList result = new ArrayList<>(); + for (String infos : map) { + result.addAll(JedisConverters.toListOfRedisClientInformation(infos)); + } + return result; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#getClientList(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public List getClientList(RedisClusterNode node) { + + return JedisConverters + .toListOfRedisClientInformation(executeCommandOnSingleNode(BinaryJedis::clientList, node).getValue()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#slaveOf(java.lang.String, int) + */ + @Override + public void slaveOf(String host, int port) { + throw new InvalidDataAccessApiUsageException( + "SlaveOf is not supported in cluster environment. Please use CLUSTER REPLICATE."); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#slaveOfNoOne() + */ + @Override + public void slaveOfNoOne() { + throw new InvalidDataAccessApiUsageException( + "SlaveOf is not supported in cluster environment. Please use CLUSTER REPLICATE."); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption) + */ + @Override + public void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option) { + migrate(key, target, dbIndex, option, Long.MAX_VALUE); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption, long) + */ + @Override + public void migrate(final byte[] key, final RedisNode target, final int dbIndex, final MigrateOption option, + final long timeout) { + + final int timeoutToUse = timeout <= Integer.MAX_VALUE ? (int) timeout : Integer.MAX_VALUE; + + RedisClusterNode node = connection.getTopologyProvider().getTopology().lookup(target.getHost(), target.getPort()); + + executeCommandOnSingleNode(client -> client.migrate(JedisConverters.toBytes(target.getHost()), target.getPort(), + key, dbIndex, timeoutToUse), node); + } + + private Long convertListOfStringToTime(List serverTimeInformation) { + + Assert.notEmpty(serverTimeInformation, "Received invalid result from server. Expected 2 items in collection."); + Assert.isTrue(serverTimeInformation.size() == 2, + "Received invalid number of arguments from redis server. Expected 2 received " + serverTimeInformation.size()); + + return Converters.toTimeMillis(serverTimeInformation.get(0), serverTimeInformation.get(1)); + } + + private NodeResult executeCommandOnSingleNode(JedisClusterCommandCallback cmd, RedisClusterNode node) { + return connection.getClusterCommandExecutor().executeCommandOnSingleNode(cmd, node); + } + + private MulitNodeResult executeCommandOnAllNodes(JedisClusterCommandCallback cmd) { + return connection.getClusterCommandExecutor().executeCommandOnAllNodes(cmd); + } +} diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterStringCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterStringCommands.java index fc0179b5e..ddc64a41e 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterStringCommands.java @@ -15,8 +15,6 @@ */ package org.springframework.data.redis.connection.jedis; -import redis.clients.jedis.Jedis; - import java.util.Arrays; import java.util.List; import java.util.Map; @@ -87,13 +85,9 @@ class JedisClusterStringCommands implements RedisStringCommands { } return connection.getClusterCommandExecutor() - .executeMuliKeyCommand(new JedisMultiKeyClusterCommandCallback() { - - @Override - public byte[] doInCluster(Jedis client, byte[] key) { - return client.get(key); - } - }, Arrays.asList(keys)).resultsAsListSortBy(keys); + .executeMuliKeyCommand((JedisMultiKeyClusterCommandCallback) (client, key) -> client.get(key), + Arrays.asList(keys)) + .resultsAsListSortBy(keys); } /* @@ -196,13 +190,9 @@ class JedisClusterStringCommands implements RedisStringCommands { throw new IllegalArgumentException("Milliseconds have cannot exceed Integer.MAX_VALUE!"); } - connection.getClusterCommandExecutor().executeCommandOnSingleNode(new JedisClusterCommandCallback() { - - @Override - public String doInCluster(Jedis client) { - return client.psetex(key, milliseconds, value); - } - }, connection.getTopologyProvider().getTopology().getKeyServingMasterNode(key)); + connection.getClusterCommandExecutor().executeCommandOnSingleNode( + (JedisClusterCommandCallback) client -> client.psetex(key, milliseconds, value), + connection.getTopologyProvider().getTopology().getKeyServingMasterNode(key)); } /* diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterZSetCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterZSetCommands.java index 841937bc2..731deaddb 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterZSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterZSetCommands.java @@ -635,7 +635,7 @@ class JedisClusterZSetCommands implements RedisZSetCommands { redis.clients.jedis.ScanResult result = connection.getCluster().zscan(key, JedisConverters.toBytes(cursorId), params); - return new ScanIteration(Long.valueOf(result.getStringCursor()), + return new ScanIteration<>(Long.valueOf(result.getStringCursor()), JedisConverters.tuplesToTuples().convert(result.getResult())); } }.open(); diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java index cee87697b..e18a7f214 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java @@ -1,12 +1,12 @@ /* * Copyright 2011-2017 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. @@ -35,7 +35,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; -import java.util.Properties; import java.util.Queue; import org.springframework.core.convert.converter.Converter; @@ -44,24 +43,8 @@ import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.redis.ExceptionTranslationStrategy; import org.springframework.data.redis.FallbackExceptionTranslationStrategy; import org.springframework.data.redis.RedisConnectionFailureException; -import org.springframework.data.redis.connection.AbstractRedisConnection; -import org.springframework.data.redis.connection.FutureResult; -import org.springframework.data.redis.connection.MessageListener; -import org.springframework.data.redis.connection.RedisGeoCommands; -import org.springframework.data.redis.connection.RedisHashCommands; -import org.springframework.data.redis.connection.RedisHyperLogLogCommands; -import org.springframework.data.redis.connection.RedisKeyCommands; -import org.springframework.data.redis.connection.RedisListCommands; -import org.springframework.data.redis.connection.RedisNode; -import org.springframework.data.redis.connection.RedisPipelineException; -import org.springframework.data.redis.connection.RedisSetCommands; -import org.springframework.data.redis.connection.RedisStringCommands; -import org.springframework.data.redis.connection.RedisSubscribedConnectionException; -import org.springframework.data.redis.connection.RedisZSetCommands; -import org.springframework.data.redis.connection.ReturnType; -import org.springframework.data.redis.connection.Subscription; +import org.springframework.data.redis.connection.*; import org.springframework.data.redis.connection.convert.TransactionResultConverter; -import org.springframework.data.redis.core.types.RedisClientInfo; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.CollectionUtils; @@ -89,8 +72,6 @@ public class JedisConnection extends AbstractRedisConnection { private static final Method SEND_COMMAND; private static final Method GET_RESPONSE; - private static final String SHUTDOWN_SCRIPT = "return redis.call('SHUTDOWN','%s')"; - private static final ExceptionTranslationStrategy EXCEPTION_TRANSLATION = new FallbackExceptionTranslationStrategy( JedisConverters.exceptionConverter()); @@ -130,8 +111,8 @@ public class JedisConnection extends AbstractRedisConnection { private final int dbIndex; private final String clientName; private boolean convertPipelineAndTxResults = true; - private List>> pipelinedResults = new ArrayList>>(); - private Queue>> txResults = new LinkedList>>(); + private List>> pipelinedResults = new ArrayList<>(); + private Queue>> txResults = new LinkedList<>(); class JedisResult extends FutureResult> { public JedisResult(Response resultHolder, Converter converter) { @@ -224,7 +205,7 @@ public class JedisConnection extends AbstractRedisConnection { return exception; } - + /* * (non-Javadoc) * @see org.springframework.data.redis.connection.RedisConnection#keyCommands() @@ -288,6 +269,24 @@ public class JedisConnection extends AbstractRedisConnection { return new JedisGeoCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#scriptingCommands() + */ + @Override + public RedisScriptingCommands scriptingCommands() { + return new JedisScriptingCommands(this); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#serverCommands() + */ + @Override + public RedisServerCommands serverCommands() { + return new JedisServerCommands(this); + } + /* * (non-Javadoc) * @see org.springframework.data.redis.connection.RedisConnection#hyperLogLogCommands() @@ -305,7 +304,7 @@ public class JedisConnection extends AbstractRedisConnection { public Object execute(String command, byte[]... args) { Assert.hasText(command, "a valid command needs to be specified"); try { - List mArgs = new ArrayList(); + List mArgs = new ArrayList<>(); if (!ObjectUtils.isEmpty(args)) { Collections.addAll(mArgs, args); } @@ -467,7 +466,7 @@ public class JedisConnection extends AbstractRedisConnection { } private List convertPipelineResults() { - List results = new ArrayList(); + List results = new ArrayList<>(); pipeline.sync(); Exception cause = null; for (FutureResult> result : pipelinedResults) { @@ -507,300 +506,6 @@ public class JedisConnection extends AbstractRedisConnection { txResults.add(result); } - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#dbSize() - */ - @Override - public Long dbSize() { - try { - if (isPipelined()) { - pipeline(new JedisResult(pipeline.dbSize())); - return null; - } - if (isQueueing()) { - transaction(new JedisResult(transaction.dbSize())); - return null; - } - return jedis.dbSize(); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#flushDb() - */ - @Override - public void flushDb() { - try { - if (isPipelined()) { - pipeline(new JedisStatusResult(pipeline.flushDB())); - return; - } - if (isQueueing()) { - transaction(new JedisStatusResult(transaction.flushDB())); - return; - } - jedis.flushDB(); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#flushAll() - */ - @Override - public void flushAll() { - try { - if (isPipelined()) { - pipeline(new JedisStatusResult(pipeline.flushAll())); - return; - } - if (isQueueing()) { - transaction(new JedisResult(transaction.flushAll())); - return; - } - jedis.flushAll(); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#bgSave() - */ - @Override - public void bgSave() { - try { - if (isPipelined()) { - pipeline(new JedisStatusResult(pipeline.bgsave())); - return; - } - if (isQueueing()) { - transaction(new JedisStatusResult(transaction.bgsave())); - return; - } - jedis.bgsave(); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#bgReWriteAof() - */ - @Override - public void bgReWriteAof() { - try { - if (isPipelined()) { - pipeline(new JedisStatusResult(pipeline.bgrewriteaof())); - return; - } - if (isQueueing()) { - transaction(new JedisStatusResult(transaction.bgrewriteaof())); - return; - } - jedis.bgrewriteaof(); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /** - * @deprecated As of 1.3, use {@link #bgReWriteAof}. - */ - @Deprecated - public void bgWriteAof() { - bgReWriteAof(); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#save() - */ - @Override - public void save() { - try { - if (isPipelined()) { - pipeline(new JedisStatusResult(pipeline.save())); - return; - } - if (isQueueing()) { - transaction(new JedisStatusResult(transaction.save())); - return; - } - jedis.save(); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#getConfig(java.lang.String) - */ - @Override - public List getConfig(String param) { - try { - if (isPipelined()) { - pipeline(new JedisResult(pipeline.configGet(param))); - return null; - } - if (isQueueing()) { - transaction(new JedisResult(transaction.configGet(param))); - return null; - } - return jedis.configGet(param); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#info() - */ - @Override - public Properties info() { - try { - if (isPipelined()) { - pipeline(new JedisResult(pipeline.info(), JedisConverters.stringToProps())); - return null; - } - if (isQueueing()) { - transaction(new JedisResult(transaction.info(), JedisConverters.stringToProps())); - return null; - } - return JedisConverters.toProperties(jedis.info()); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#info(java.lang.String) - */ - @Override - public Properties info(String section) { - if (isPipelined()) { - throw new UnsupportedOperationException(); - } - if (isQueueing()) { - throw new UnsupportedOperationException(); - } - try { - return JedisConverters.toProperties(jedis.info(section)); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#lastSave() - */ - @Override - public Long lastSave() { - try { - if (isPipelined()) { - pipeline(new JedisResult(pipeline.lastsave())); - return null; - } - if (isQueueing()) { - transaction(new JedisResult(transaction.lastsave())); - return null; - } - return jedis.lastsave(); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#setConfig(java.lang.String, java.lang.String) - */ - @Override - public void setConfig(String param, String value) { - try { - if (isPipelined()) { - pipeline(new JedisStatusResult(pipeline.configSet(param, value))); - return; - } - if (isQueueing()) { - transaction(new JedisStatusResult(transaction.configSet(param, value))); - return; - } - jedis.configSet(param, value); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#resetConfigStats() - */ - @Override - public void resetConfigStats() { - try { - if (isPipelined()) { - pipeline(new JedisStatusResult(pipeline.configResetStat())); - return; - } - if (isQueueing()) { - transaction(new JedisStatusResult(transaction.configResetStat())); - return; - } - jedis.configResetStat(); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#shutdown() - */ - @Override - public void shutdown() { - try { - if (isPipelined()) { - pipeline(new JedisStatusResult(pipeline.shutdown())); - return; - } - if (isQueueing()) { - transaction(new JedisStatusResult(transaction.shutdown())); - return; - } - jedis.shutdown(); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#shutdown(org.springframework.data.redis.connection.RedisServerCommands.ShutdownOption) - */ - @Override - public void shutdown(ShutdownOption option) { - - if (option == null) { - shutdown(); - return; - } - - eval(String.format(SHUTDOWN_SCRIPT, option.name()).getBytes(), ReturnType.STATUS, 0); - } - /* * (non-Javadoc) * @see org.springframework.data.redis.connection.RedisConnectionCommands#echo(byte[]) @@ -871,8 +576,8 @@ public class JedisConnection extends AbstractRedisConnection { public List exec() { try { if (isPipelined()) { - pipeline(new JedisResult(pipeline.exec(), new TransactionResultConverter>( - new LinkedList>>(txResults), JedisConverters.exceptionConverter()))); + pipeline(new JedisResult(pipeline.exec(), + new TransactionResultConverter<>(new LinkedList<>(txResults), JedisConverters.exceptionConverter()))); return null; } @@ -881,8 +586,7 @@ public class JedisConnection extends AbstractRedisConnection { } List results = transaction.exec(); return convertPipelineAndTxResults && !CollectionUtils.isEmpty(results) - ? new TransactionResultConverter>(txResults, JedisConverters.exceptionConverter()) - .convert(results) + ? new TransactionResultConverter<>(txResults, JedisConverters.exceptionConverter()).convert(results) : results; } catch (Exception ex) { throw convertJedisAccessException(ex); @@ -904,7 +608,6 @@ public class JedisConnection extends AbstractRedisConnection { return jedis; } - JedisResult newJedisResult(Response response) { return new JedisResult(response); } @@ -1093,253 +796,6 @@ public class JedisConnection extends AbstractRedisConnection { } } - // - // Scripting commands - // - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptFlush() - */ - @Override - public void scriptFlush() { - if (isQueueing()) { - throw new UnsupportedOperationException(); - } - if (isPipelined()) { - throw new UnsupportedOperationException(); - } - try { - jedis.scriptFlush(); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptKill() - */ - @Override - public void scriptKill() { - if (isQueueing()) { - throw new UnsupportedOperationException(); - } - if (isPipelined()) { - throw new UnsupportedOperationException(); - } - try { - jedis.scriptKill(); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptLoad(byte[]) - */ - @Override - public String scriptLoad(byte[] script) { - if (isQueueing()) { - throw new UnsupportedOperationException(); - } - if (isPipelined()) { - throw new UnsupportedOperationException(); - } - try { - return JedisConverters.toString(jedis.scriptLoad(script)); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptExists(java.lang.String[]) - */ - @Override - public List scriptExists(String... scriptSha1) { - if (isQueueing()) { - throw new UnsupportedOperationException(); - } - if (isPipelined()) { - throw new UnsupportedOperationException(); - } - try { - return jedis.scriptExists(scriptSha1); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisScriptingCommands#eval(byte[], org.springframework.data.redis.connection.ReturnType, int, byte[][]) - */ - @Override - @SuppressWarnings("unchecked") - public T eval(byte[] script, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { - if (isQueueing()) { - throw new UnsupportedOperationException(); - } - if (isPipelined()) { - throw new UnsupportedOperationException(); - } - try { - return (T) new JedisScriptReturnConverter(returnType) - .convert(jedis.eval(script, JedisConverters.toBytes(numKeys), keysAndArgs)); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisScriptingCommands#evalSha(java.lang.String, org.springframework.data.redis.connection.ReturnType, int, byte[][]) - */ - @Override - public T evalSha(String scriptSha1, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { - return evalSha(JedisConverters.toBytes(scriptSha1), returnType, numKeys, keysAndArgs); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisScriptingCommands#evalSha(byte[], org.springframework.data.redis.connection.ReturnType, int, byte[][]) - */ - @Override - @SuppressWarnings("unchecked") - public T evalSha(byte[] scriptSha1, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { - - if (isQueueing()) { - throw new UnsupportedOperationException(); - } - if (isPipelined()) { - throw new UnsupportedOperationException(); - } - try { - return (T) new JedisScriptReturnConverter(returnType).convert(jedis.evalsha(scriptSha1, numKeys, keysAndArgs)); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#time() - */ - @Override - public Long time() { - - try { - - if (isPipelined()) { - pipeline(new JedisResult(pipeline.time(), JedisConverters.toTimeConverter())); - return null; - } - - if (isQueueing()) { - transaction(new JedisResult(transaction.time(), JedisConverters.toTimeConverter())); - return null; - } - return JedisConverters.toTimeConverter().convert(jedis.time()); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#killClient(byte[]) - */ - @Override - public void killClient(String host, int port) { - - Assert.hasText(host, "Host for 'CLIENT KILL' must not be 'null' or 'empty'."); - - if (isQueueing() || isPipelined()) { - throw new UnsupportedOperationException("'CLIENT KILL' is not supported in transaction / pipline mode."); - } - - try { - this.jedis.clientKill(String.format("%s:%s", host, port)); - } catch (Exception e) { - throw convertJedisAccessException(e); - } - } - - /* - * @see org.springframework.data.redis.connection.RedisServerCommands#slaveOf(java.lang.String, int) - */ - @Override - public void slaveOf(String host, int port) { - - Assert.hasText(host, "Host must not be null for 'SLAVEOF' command."); - if (isQueueing() || isPipelined()) { - throw new UnsupportedOperationException("'SLAVEOF' cannot be called in pipline / transaction mode."); - } - try { - this.jedis.slaveof(host, port); - } catch (Exception e) { - throw convertJedisAccessException(e); - } - } - - /* - * @see org.springframework.data.redis.connection.RedisServerCommands#setClientName(java.lang.String) - */ - @Override - public void setClientName(byte[] name) { - - if (isPipelined() || isQueueing()) { - throw new UnsupportedOperationException("'CLIENT SETNAME' is not suppored in transacton / pipeline mode."); - } - - jedis.clientSetname(name); - } - - /* - * @see org.springframework.data.redis.connection.RedisServerCommands#getClientName() - */ - @Override - public String getClientName() { - - if (isPipelined() || isQueueing()) { - throw new UnsupportedOperationException(); - } - - return jedis.clientGetname(); - } - - /* - * @see org.springframework.data.redis.connection.RedisServerCommands#getClientName() - */ - @Override - public List getClientList() { - - if (isQueueing() || isPipelined()) { - throw new UnsupportedOperationException("'CLIENT LIST' is not supported in in pipeline / multi mode."); - } - return JedisConverters.toListOfRedisClientInformation(this.jedis.clientList()); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#slaveOfNoOne() - */ - @Override - public void slaveOfNoOne() { - - if (isQueueing() || isPipelined()) { - throw new UnsupportedOperationException("'SLAVEOF' cannot be called in pipline / transaction mode."); - } - try { - this.jedis.slaveofNoOne(); - } catch (Exception e) { - throw convertJedisAccessException(e); - } - } - /** * Specifies if pipelined results should be converted to the expected data type. If false, results of * {@link #closePipeline()} and {@link #exec()} will be of the type returned by the Jedis driver @@ -1396,41 +852,4 @@ public class JedisConnection extends AbstractRedisConnection { return jedis; } - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption) - */ - @Override - public void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option) { - migrate(key, target, dbIndex, option, Long.MAX_VALUE); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption, long) - */ - @Override - public void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option, long timeout) { - - final int timeoutToUse = timeout <= Integer.MAX_VALUE ? (int) timeout : Integer.MAX_VALUE; - - try { - if (isPipelined()) { - - pipeline(new JedisResult( - pipeline.migrate(JedisConverters.toBytes(target.getHost()), target.getPort(), key, dbIndex, timeoutToUse))); - return; - } - if (isQueueing()) { - transaction(new JedisResult(transaction.migrate(JedisConverters.toBytes(target.getHost()), target.getPort(), - key, dbIndex, timeoutToUse))); - return; - } - jedis.migrate(JedisConverters.toBytes(target.getHost()), target.getPort(), key, dbIndex, timeoutToUse); - } catch (Exception ex) { - throw convertJedisAccessException(ex); - } - - } - } diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java index 1a0a1d74b..023f281e0 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java @@ -58,7 +58,7 @@ import org.springframework.util.StringUtils; /** * Connection factory creating Jedis based connections. - * + * * @author Costin Leau * @author Thomas Darimont * @author Christoph Strobl @@ -118,7 +118,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Constructs a new JedisConnectionFactory instance. Will override the other connection parameters passed * to the factory. - * + * * @param shardInfo shard information */ public JedisConnectionFactory(JedisShardInfo shardInfo) { @@ -127,7 +127,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Constructs a new JedisConnectionFactory instance using the given pool configuration. - * + * * @param poolConfig pool configuration */ public JedisConnectionFactory(JedisPoolConfig poolConfig) { @@ -137,7 +137,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Constructs a new {@link JedisConnectionFactory} instance using the given {@link JedisPoolConfig} applied to * {@link JedisSentinelPool}. - * + * * @param sentinelConfig * @since 1.4 */ @@ -148,7 +148,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Constructs a new {@link JedisConnectionFactory} instance using the given {@link JedisPoolConfig} applied to * {@link JedisSentinelPool}. - * + * * @param sentinelConfig * @param poolConfig pool configuration. Defaulted to new instance if {@literal null}. * @since 1.4 @@ -161,7 +161,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Constructs a new {@link JedisConnectionFactory} instance using the given {@link RedisClusterConfiguration} applied * to create a {@link JedisCluster}. - * + * * @param clusterConfig * @since 1.7 */ @@ -172,7 +172,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Constructs a new {@link JedisConnectionFactory} instance using the given {@link RedisClusterConfiguration} applied * to create a {@link JedisCluster}. - * + * * @param clusterConfig * @since 1.7 */ @@ -184,7 +184,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Returns a Jedis instance to be used as a Redis connection. The instance can be newly created or retrieved from a * pool. - * + * * @return Jedis instance ready for wrapping into a {@link RedisConnection}. */ protected Jedis fetchJedisConnector() { @@ -208,7 +208,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Post process a newly retrieved connection. Useful for decorating or executing initialization commands on a new * connection. This implementation simply returns the connection. - * + * * @param connection * @return processed connection */ @@ -252,7 +252,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Creates {@link JedisSentinelPool}. - * + * * @param config * @return * @since 1.4 @@ -265,7 +265,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Creates {@link JedisPool}. - * + * * @return * @since 1.4 */ @@ -286,7 +286,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Creates {@link JedisCluster} for given {@link RedisClusterConfiguration} and {@link GenericObjectPoolConfig}. - * + * * @param clusterConfig must not be {@literal null}. * @param poolConfig can be {@literal null}. * @return @@ -296,7 +296,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, Assert.notNull(clusterConfig, "Cluster configuration must not be null!"); - Set hostAndPort = new HashSet(); + Set hostAndPort = new HashSet<>(); for (RedisNode node : clusterConfig.getClusterNodes()) { hostAndPort.add(new HostAndPort(node.getHost(), node.getPort())); } @@ -365,7 +365,6 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, return new JedisClusterConnection(cluster, clusterCommandExecutor); } - /* * (non-Javadoc) * @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException) @@ -376,7 +375,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Returns the Redis hostName. - * + * * @return the hostName. */ public String getHostName() { @@ -385,7 +384,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Sets the Redis hostName. - * + * * @param hostName the hostName to set. */ public void setHostName(String hostName) { @@ -414,7 +413,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Returns the password used for authenticating with the Redis server. - * + * * @return password for authentication. */ public String getPassword() { @@ -423,7 +422,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Sets the password used for authenticating with the Redis server. - * + * * @param password the password to set. */ public void setPassword(String password) { @@ -432,7 +431,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Returns the port used to connect to the Redis instance. - * + * * @return the Redis port. */ public int getPort() { @@ -441,7 +440,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Sets the port used to connect to the Redis instance. - * + * * @param port the Redis port. */ public void setPort(int port) { @@ -450,7 +449,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Returns the shardInfo. - * + * * @return the shardInfo. */ public JedisShardInfo getShardInfo() { @@ -459,7 +458,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Sets the shard info for this factory. - * + * * @param shardInfo the shardInfo to set. */ public void setShardInfo(JedisShardInfo shardInfo) { @@ -468,7 +467,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Returns the timeout. - * + * * @return the timeout. */ public int getTimeout() { @@ -486,7 +485,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Indicates the use of a connection pool. - * + * * @return the use of connection pooling. */ public boolean getUsePool() { @@ -495,7 +494,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Turns on or off the use of connection pooling. - * + * * @param usePool the usePool to set. */ public void setUsePool(boolean usePool) { @@ -504,7 +503,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Returns the poolConfig. - * + * * @return the poolConfig */ public JedisPoolConfig getPoolConfig() { @@ -513,7 +512,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Sets the pool configuration for this factory. - * + * * @param poolConfig the poolConfig to set. */ public void setPoolConfig(JedisPoolConfig poolConfig) { @@ -522,7 +521,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Returns the index of the database. - * + * * @return the database index. */ public int getDatabase() { @@ -531,7 +530,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, /** * Sets the index of the database used by this connection factory. Default is 0. - * + * * @param index database index. */ public void setDatabase(int index) { @@ -563,7 +562,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, * Specifies if pipelined results should be converted to the expected data type. If false, results of * {@link JedisConnection#closePipeline()} and {@link JedisConnection#exec()} will be of the type returned by the * Jedis driver. - * + * * @return Whether or not to convert pipeline and tx results. */ public boolean getConvertPipelineAndTxResults() { @@ -574,7 +573,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, * Specifies if pipelined results should be converted to the expected data type. If false, results of * {@link JedisConnection#closePipeline()} and {@link JedisConnection#exec()} will be of the type returned by the * Jedis driver. - * + * * @param convertPipelineAndTxResults Whether or not to convert pipeline and tx results. */ public void setConvertPipelineAndTxResults(boolean convertPipelineAndTxResults) { @@ -626,7 +625,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, return Collections.emptySet(); } - Set convertedNodes = new LinkedHashSet(nodes.size()); + Set convertedNodes = new LinkedHashSet<>(nodes.size()); for (RedisNode node : nodes) { if (node != null) { convertedNodes.add(node.asString()); diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConverters.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConverters.java index 3ca3774fb..bef0ca162 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConverters.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConverters.java @@ -15,6 +15,16 @@ */ package org.springframework.data.redis.connection.jedis; +import redis.clients.jedis.BinaryClient.LIST_POSITION; +import redis.clients.jedis.BitOP; +import redis.clients.jedis.GeoCoordinate; +import redis.clients.jedis.GeoRadiusResponse; +import redis.clients.jedis.GeoUnit; +import redis.clients.jedis.ScanParams; +import redis.clients.jedis.SortingParams; +import redis.clients.jedis.params.geo.GeoRadiusParam; +import redis.clients.util.SafeEncoder; + import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; @@ -60,19 +70,9 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; -import redis.clients.jedis.BinaryClient.LIST_POSITION; -import redis.clients.jedis.BitOP; -import redis.clients.jedis.GeoCoordinate; -import redis.clients.jedis.GeoRadiusResponse; -import redis.clients.jedis.GeoUnit; -import redis.clients.jedis.ScanParams; -import redis.clients.jedis.SortingParams; -import redis.clients.jedis.params.geo.GeoRadiusParam; -import redis.clients.util.SafeEncoder; - /** * Jedis type converters. - * + * * @author Jennifer Hickey * @author Christoph Strobl * @author Thomas Darimont @@ -118,24 +118,24 @@ abstract public class JedisConverters extends Converters { return source == null ? null : SafeEncoder.encode(source); } }; - BYTES_LIST_TO_STRING_LIST_CONVERTER = new ListConverter(BYTES_TO_STRING_CONVERTER); + BYTES_LIST_TO_STRING_LIST_CONVERTER = new ListConverter<>(BYTES_TO_STRING_CONVERTER); STRING_TO_BYTES = new Converter() { public byte[] convert(String source) { return source == null ? null : SafeEncoder.encode(source); } }; - STRING_LIST_TO_BYTE_LIST = new ListConverter(STRING_TO_BYTES); - STRING_SET_TO_BYTE_SET = new SetConverter(STRING_TO_BYTES); - STRING_MAP_TO_BYTE_MAP = new MapConverter(STRING_TO_BYTES); + STRING_LIST_TO_BYTE_LIST = new ListConverter<>(STRING_TO_BYTES); + STRING_SET_TO_BYTE_SET = new SetConverter<>(STRING_TO_BYTES); + STRING_MAP_TO_BYTE_MAP = new MapConverter<>(STRING_TO_BYTES); TUPLE_CONVERTER = new Converter() { public Tuple convert(redis.clients.jedis.Tuple source) { return source != null ? new DefaultTuple(source.getBinaryElement(), source.getScore()) : null; } }; - TUPLE_SET_TO_TUPLE_SET = new SetConverter(TUPLE_CONVERTER); - TUPLE_LIST_TO_TUPLE_LIST_CONVERTER = new ListConverter(TUPLE_CONVERTER); + TUPLE_SET_TO_TUPLE_SET = new SetConverter<>(TUPLE_CONVERTER); + TUPLE_LIST_TO_TUPLE_LIST_CONVERTER = new ListConverter<>(TUPLE_CONVERTER); PLUS_BYTES = toBytes("+"); MINUS_BYTES = toBytes("-"); POSITIVE_INFINITY_BYTES = toBytes("+inf"); @@ -214,8 +214,7 @@ abstract public class JedisConverters extends Converters { return geoCoordinate != null ? new Point(geoCoordinate.getLongitude(), geoCoordinate.getLatitude()) : null; } }; - LIST_GEO_COORDINATE_TO_POINT_CONVERTER = new ListConverter( - GEO_COORDINATE_TO_POINT_CONVERTER); + LIST_GEO_COORDINATE_TO_POINT_CONVERTER = new ListConverter<>(GEO_COORDINATE_TO_POINT_CONVERTER); } public static Converter stringToBytes() { @@ -224,7 +223,7 @@ abstract public class JedisConverters extends Converters { /** * {@link ListConverter} converting jedis {@link redis.clients.jedis.Tuple} to {@link Tuple}. - * + * * @return * @since 1.4 */ @@ -322,7 +321,7 @@ abstract public class JedisConverters extends Converters { return Collections.emptyList(); } - List sentinels = new ArrayList(); + List sentinels = new ArrayList<>(); for (Map info : source) { sentinels.add(RedisServer.newServerFrom(Converters.toProperties(info))); } @@ -394,7 +393,7 @@ abstract public class JedisConverters extends Converters { /** * Converts a given {@link Boundary} to its binary representation suitable for {@literal ZRANGEBY*} commands, despite * {@literal ZRANGEBYLEX}. - * + * * @param boundary * @param defaultValue * @return @@ -411,7 +410,7 @@ abstract public class JedisConverters extends Converters { /** * Converts a given {@link Boundary} to its binary representation suitable for ZRANGEBYLEX command. - * + * * @param boundary * @return * @since 1.6 @@ -433,7 +432,7 @@ abstract public class JedisConverters extends Converters { *
    {@link TimeUnit#MILLISECONDS}
    *
    {@code PX}
    * - * + * * @param expiration * @return * @since 1.7 @@ -452,7 +451,7 @@ abstract public class JedisConverters extends Converters { *
    {@link SetOption#SET_IF_PRESENT}
    *
    {@code XX}
    * - * + * * @param option * @return * @since 1.7 @@ -537,7 +536,7 @@ abstract public class JedisConverters extends Converters { /** * Get a {@link Converter} capable of converting {@link GeoRadiusResponse} into {@link GeoResults}. - * + * * @param metric * @return * @since 1.8 @@ -549,7 +548,7 @@ abstract public class JedisConverters extends Converters { /** * Convert {@link Metric} into {@link GeoUnit}. - * + * * @param metric * @return * @since 1.8 @@ -563,7 +562,7 @@ abstract public class JedisConverters extends Converters { /** * Convert {@link Point} into {@link GeoCoordinate}. - * + * * @param source * @return * @since 1.8 @@ -574,7 +573,7 @@ abstract public class JedisConverters extends Converters { /** * Convert {@link GeoRadiusCommandArgs} into {@link GeoRadiusParam}. - * + * * @param source * @return * @since 1.8 @@ -642,7 +641,7 @@ abstract public class JedisConverters extends Converters { @Override public GeoResults> convert(List source) { - List>> results = new ArrayList>>(source.size()); + List>> results = new ArrayList<>(source.size()); Converter>> converter = GeoResultConverterFactory.INSTANCE .forMetric(metric); @@ -650,7 +649,7 @@ abstract public class JedisConverters extends Converters { results.add(converter.convert(result)); } - return new GeoResults>(results, metric); + return new GeoResults<>(results, metric); } } } @@ -681,7 +680,7 @@ abstract public class JedisConverters extends Converters { Point point = GEO_COORDINATE_TO_POINT_CONVERTER.convert(source.getCoordinate()); - return new GeoResult>(new GeoLocation(source.getMember(), point), + return new GeoResult<>(new GeoLocation<>(source.getMember(), point), new Distance(source.getDistance(), metric)); } } diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisGeoCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisGeoCommands.java index 3fc834120..42696413d 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisGeoCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisGeoCommands.java @@ -83,7 +83,7 @@ class JedisGeoCommands implements RedisGeoCommands { Assert.notNull(key, "Key must not be null!"); Assert.notNull(memberCoordinateMap, "MemberCoordinateMap must not be null!"); - Map redisGeoCoordinateMap = new HashMap(); + Map redisGeoCoordinateMap = new HashMap<>(); for (byte[] mapKey : memberCoordinateMap.keySet()) { redisGeoCoordinateMap.put(mapKey, JedisConverters.toGeoCoordinate(memberCoordinateMap.get(mapKey))); @@ -115,7 +115,7 @@ class JedisGeoCommands implements RedisGeoCommands { Assert.notNull(key, "Key must not be null!"); Assert.notNull(locations, "Locations must not be null!"); - Map redisGeoCoordinateMap = new HashMap(); + Map redisGeoCoordinateMap = new HashMap<>(); for (GeoLocation location : locations) { redisGeoCoordinateMap.put(location.getName(), JedisConverters.toGeoCoordinate(location.getPoint())); diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisHashCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisHashCommands.java index 5981b95ac..9f46406f6 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisHashCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisHashCommands.java @@ -90,7 +90,6 @@ class JedisHashCommands implements RedisHashCommands { } } - /* * (non-Javadoc) * @see org.springframework.data.redis.connection.RedisHashCommands#hDel(byte[], byte[][]) diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisKeyCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisKeyCommands.java index c6bee6e01..e0fb740ed 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisKeyCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisKeyCommands.java @@ -161,7 +161,7 @@ class JedisKeyCommands implements RedisKeyCommands { ScanParams params = JedisConverters.toScanParams(options); redis.clients.jedis.ScanResult result = connection.getJedis().scan(Long.toString(cursorId), params); - return new ScanIteration(Long.valueOf(result.getStringCursor()), + return new ScanIteration<>(Long.valueOf(result.getStringCursor()), JedisConverters.stringListToByteList().convert(result.getResult())); } diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisScriptReturnConverter.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisScriptReturnConverter.java index 237f2bdf8..570472624 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisScriptReturnConverter.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisScriptReturnConverter.java @@ -15,14 +15,14 @@ */ package org.springframework.data.redis.connection.jedis; +import redis.clients.util.SafeEncoder; + import java.util.ArrayList; import java.util.List; import org.springframework.core.convert.converter.Converter; import org.springframework.data.redis.connection.ReturnType; -import redis.clients.util.SafeEncoder; - /** * Converts the value returned by Jedis script eval to the expected {@link ReturnType} * @@ -54,7 +54,7 @@ public class JedisScriptReturnConverter implements Converter { } if (returnType == ReturnType.MULTI) { List resultList = (List) result; - List convertedResults = new ArrayList(); + List convertedResults = new ArrayList<>(); for (Object res : resultList) { if (res instanceof String) { // evalsha converts byte[] to String. Convert back for diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisScriptingCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisScriptingCommands.java new file mode 100644 index 000000000..5f3fd3656 --- /dev/null +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisScriptingCommands.java @@ -0,0 +1,174 @@ +/* + * Copyright 2017 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.jedis; + +import java.util.List; + +import org.springframework.data.redis.connection.RedisScriptingCommands; +import org.springframework.data.redis.connection.ReturnType; + +/** + * @author Mark Paluch + * @since 2.0 + */ +class JedisScriptingCommands implements RedisScriptingCommands { + + private final JedisConnection connection; + + public JedisScriptingCommands(JedisConnection connection) { + this.connection = connection; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptFlush() + */ + @Override + public void scriptFlush() { + if (isQueueing()) { + throw new UnsupportedOperationException(); + } + if (isPipelined()) { + throw new UnsupportedOperationException(); + } + try { + connection.getJedis().scriptFlush(); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptKill() + */ + @Override + public void scriptKill() { + if (isQueueing()) { + throw new UnsupportedOperationException(); + } + if (isPipelined()) { + throw new UnsupportedOperationException(); + } + try { + connection.getJedis().scriptKill(); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptLoad(byte[]) + */ + @Override + public String scriptLoad(byte[] script) { + if (isQueueing()) { + throw new UnsupportedOperationException(); + } + if (isPipelined()) { + throw new UnsupportedOperationException(); + } + try { + return JedisConverters.toString(connection.getJedis().scriptLoad(script)); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptExists(java.lang.String[]) + */ + @Override + public List scriptExists(String... scriptSha1) { + if (isQueueing()) { + throw new UnsupportedOperationException(); + } + if (isPipelined()) { + throw new UnsupportedOperationException(); + } + try { + return connection.getJedis().scriptExists(scriptSha1); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#eval(byte[], org.springframework.data.redis.connection.ReturnType, int, byte[][]) + */ + @Override + @SuppressWarnings("unchecked") + public T eval(byte[] script, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { + if (isQueueing()) { + throw new UnsupportedOperationException(); + } + if (isPipelined()) { + throw new UnsupportedOperationException(); + } + try { + return (T) new JedisScriptReturnConverter(returnType) + .convert(connection.getJedis().eval(script, JedisConverters.toBytes(numKeys), keysAndArgs)); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#evalSha(java.lang.String, org.springframework.data.redis.connection.ReturnType, int, byte[][]) + */ + @Override + public T evalSha(String scriptSha1, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { + return evalSha(JedisConverters.toBytes(scriptSha1), returnType, numKeys, keysAndArgs); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#evalSha(byte[], org.springframework.data.redis.connection.ReturnType, int, byte[][]) + */ + @Override + @SuppressWarnings("unchecked") + public T evalSha(byte[] scriptSha1, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { + + if (isQueueing()) { + throw new UnsupportedOperationException(); + } + if (isPipelined()) { + throw new UnsupportedOperationException(); + } + try { + return (T) new JedisScriptReturnConverter(returnType) + .convert(connection.getJedis().evalsha(scriptSha1, numKeys, keysAndArgs)); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + private boolean isPipelined() { + return connection.isPipelined(); + } + + private boolean isQueueing() { + return connection.isQueueing(); + } + + private RuntimeException convertJedisAccessException(Exception ex) { + return connection.convertJedisAccessException(ex); + } +} diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisServerCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisServerCommands.java new file mode 100644 index 000000000..8b83afe5a --- /dev/null +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisServerCommands.java @@ -0,0 +1,505 @@ +/* + * Copyright 2017 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.jedis; + +import java.util.List; +import java.util.Properties; + +import org.springframework.data.redis.connection.RedisNode; +import org.springframework.data.redis.connection.RedisServerCommands; +import org.springframework.data.redis.connection.ReturnType; +import org.springframework.data.redis.connection.jedis.JedisConnection.JedisResult; +import org.springframework.data.redis.core.types.RedisClientInfo; +import org.springframework.util.Assert; + +/** + * @author Mark Paluch + * @since 2.0 + */ +class JedisServerCommands implements RedisServerCommands { + + private static final String SHUTDOWN_SCRIPT = "return redis.call('SHUTDOWN','%s')"; + + private final JedisConnection connection; + + public JedisServerCommands(JedisConnection connection) { + this.connection = connection; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#bgReWriteAof() + */ + @Override + public void bgReWriteAof() { + try { + if (isPipelined()) { + pipeline(connection.newStatusResult(connection.getPipeline().bgrewriteaof())); + return; + } + if (isQueueing()) { + transaction(connection.newStatusResult(connection.getTransaction().bgrewriteaof())); + return; + } + connection.getJedis().bgrewriteaof(); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#bgSave() + */ + @Override + public void bgSave() { + try { + if (isPipelined()) { + pipeline(connection.newStatusResult(connection.getPipeline().bgsave())); + return; + } + if (isQueueing()) { + transaction(connection.newStatusResult(connection.getTransaction().bgsave())); + return; + } + connection.getJedis().bgsave(); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#lastSave() + */ + @Override + public Long lastSave() { + try { + if (isPipelined()) { + pipeline(connection.newJedisResult(connection.getPipeline().lastsave())); + return null; + } + if (isQueueing()) { + transaction(connection.newJedisResult(connection.getTransaction().lastsave())); + return null; + } + return connection.getJedis().lastsave(); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#save() + */ + @Override + public void save() { + try { + if (isPipelined()) { + pipeline(connection.newStatusResult(connection.getPipeline().save())); + return; + } + if (isQueueing()) { + transaction(connection.newStatusResult(connection.getTransaction().save())); + return; + } + connection.getJedis().save(); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#dbSize() + */ + @Override + public Long dbSize() { + try { + if (isPipelined()) { + pipeline(connection.newJedisResult(connection.getPipeline().dbSize())); + return null; + } + if (isQueueing()) { + transaction(connection.newJedisResult(connection.getTransaction().dbSize())); + return null; + } + return connection.getJedis().dbSize(); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#flushDb() + */ + @Override + public void flushDb() { + try { + if (isPipelined()) { + pipeline(connection.newStatusResult(connection.getPipeline().flushDB())); + return; + } + if (isQueueing()) { + transaction(connection.newStatusResult(connection.getTransaction().flushDB())); + return; + } + connection.getJedis().flushDB(); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#flushAll() + */ + @Override + public void flushAll() { + try { + if (isPipelined()) { + pipeline(connection.newStatusResult(connection.getPipeline().flushAll())); + return; + } + if (isQueueing()) { + transaction(connection.newJedisResult(connection.getTransaction().flushAll())); + return; + } + connection.getJedis().flushAll(); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#info() + */ + @Override + public Properties info() { + try { + if (isPipelined()) { + pipeline(connection.newJedisResult(connection.getPipeline().info(), JedisConverters.stringToProps())); + return null; + } + if (isQueueing()) { + transaction(connection.newJedisResult(connection.getTransaction().info(), JedisConverters.stringToProps())); + return null; + } + return JedisConverters.toProperties(connection.getJedis().info()); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#info(java.lang.String) + */ + @Override + public Properties info(String section) { + if (isPipelined()) { + throw new UnsupportedOperationException(); + } + if (isQueueing()) { + throw new UnsupportedOperationException(); + } + try { + return JedisConverters.toProperties(connection.getJedis().info(section)); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#shutdown() + */ + @Override + public void shutdown() { + try { + if (isPipelined()) { + pipeline(connection.newStatusResult(connection.getPipeline().shutdown())); + return; + } + if (isQueueing()) { + transaction(connection.newStatusResult(connection.getTransaction().shutdown())); + return; + } + connection.getJedis().shutdown(); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#shutdown(org.springframework.data.redis.connection.RedisServerCommands.ShutdownOption) + */ + @Override + public void shutdown(ShutdownOption option) { + + if (option == null) { + shutdown(); + return; + } + + connection.eval(String.format(SHUTDOWN_SCRIPT, option.name()).getBytes(), ReturnType.STATUS, 0); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#getConfig(java.lang.String) + */ + @Override + public List getConfig(String param) { + try { + if (isPipelined()) { + pipeline(connection.newJedisResult(connection.getPipeline().configGet(param))); + return null; + } + if (isQueueing()) { + transaction(connection.newJedisResult(connection.getTransaction().configGet(param))); + return null; + } + return connection.getJedis().configGet(param); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#setConfig(java.lang.String, java.lang.String) + */ + @Override + public void setConfig(String param, String value) { + try { + if (isPipelined()) { + pipeline(connection.newStatusResult(connection.getPipeline().configSet(param, value))); + return; + } + if (isQueueing()) { + transaction(connection.newStatusResult(connection.getTransaction().configSet(param, value))); + return; + } + connection.getJedis().configSet(param, value); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#resetConfigStats() + */ + @Override + public void resetConfigStats() { + try { + if (isPipelined()) { + pipeline(connection.newStatusResult(connection.getPipeline().configResetStat())); + return; + } + if (isQueueing()) { + transaction(connection.newStatusResult(connection.getTransaction().configResetStat())); + return; + } + connection.getJedis().configResetStat(); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#time() + */ + @Override + public Long time() { + + try { + + if (isPipelined()) { + pipeline(connection.newJedisResult(connection.getPipeline().time(), JedisConverters.toTimeConverter())); + return null; + } + + if (isQueueing()) { + transaction(connection.newJedisResult(connection.getTransaction().time(), JedisConverters.toTimeConverter())); + return null; + } + return JedisConverters.toTimeConverter().convert(connection.getJedis().time()); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#killClient(java.lang.String, int) + */ + @Override + public void killClient(String host, int port) { + + Assert.hasText(host, "Host for 'CLIENT KILL' must not be 'null' or 'empty'."); + + if (isQueueing() || isPipelined()) { + throw new UnsupportedOperationException("'CLIENT KILL' is not supported in transaction / pipline mode."); + } + + try { + this.connection.getJedis().clientKill(String.format("%s:%s", host, port)); + } catch (Exception e) { + throw convertJedisAccessException(e); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#setClientName(byte[]) + */ + @Override + public void setClientName(byte[] name) { + + if (isPipelined() || isQueueing()) { + throw new UnsupportedOperationException("'CLIENT SETNAME' is not suppored in transacton / pipeline mode."); + } + + connection.getJedis().clientSetname(name); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#getClientName() + */ + @Override + public String getClientName() { + + if (isPipelined() || isQueueing()) { + throw new UnsupportedOperationException(); + } + + return connection.getJedis().clientGetname(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#getClientList() + */ + @Override + public List getClientList() { + + if (isQueueing() || isPipelined()) { + throw new UnsupportedOperationException("'CLIENT LIST' is not supported in in pipeline / multi mode."); + } + return JedisConverters.toListOfRedisClientInformation(this.connection.getJedis().clientList()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#slaveOf(java.lang.String, int) + */ + @Override + public void slaveOf(String host, int port) { + + Assert.hasText(host, "Host must not be null for 'SLAVEOF' command."); + if (isQueueing() || isPipelined()) { + throw new UnsupportedOperationException("'SLAVEOF' cannot be called in pipline / transaction mode."); + } + try { + this.connection.getJedis().slaveof(host, port); + } catch (Exception e) { + throw convertJedisAccessException(e); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#slaveOfNoOne() + */ + @Override + public void slaveOfNoOne() { + + if (isQueueing() || isPipelined()) { + throw new UnsupportedOperationException("'SLAVEOF' cannot be called in pipline / transaction mode."); + } + try { + this.connection.getJedis().slaveofNoOne(); + } catch (Exception e) { + throw convertJedisAccessException(e); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption) + */ + @Override + public void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option) { + migrate(key, target, dbIndex, option, Long.MAX_VALUE); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption, long) + */ + @Override + public void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option, long timeout) { + + final int timeoutToUse = timeout <= Integer.MAX_VALUE ? (int) timeout : Integer.MAX_VALUE; + + try { + if (isPipelined()) { + + pipeline(connection.newJedisResult(connection.getPipeline().migrate(JedisConverters.toBytes(target.getHost()), + target.getPort(), key, dbIndex, timeoutToUse))); + return; + } + if (isQueueing()) { + transaction(connection.newJedisResult(connection.getTransaction() + .migrate(JedisConverters.toBytes(target.getHost()), target.getPort(), key, dbIndex, timeoutToUse))); + return; + } + connection.getJedis().migrate(JedisConverters.toBytes(target.getHost()), target.getPort(), key, dbIndex, + timeoutToUse); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + + } + + private boolean isPipelined() { + return connection.isPipelined(); + } + + private void pipeline(JedisResult result) { + connection.pipeline(result); + } + + private boolean isQueueing() { + return connection.isQueueing(); + } + + private void transaction(JedisResult result) { + connection.transaction(result); + } + + private RuntimeException convertJedisAccessException(Exception ex) { + return connection.convertJedisAccessException(ex); + } +} diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisSetCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisSetCommands.java index 07408341f..c1f0403a0 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisSetCommands.java @@ -15,6 +15,8 @@ */ package org.springframework.data.redis.connection.jedis; +import redis.clients.jedis.ScanParams; + import java.util.List; import java.util.Set; @@ -24,7 +26,6 @@ import org.springframework.data.redis.core.Cursor; import org.springframework.data.redis.core.KeyBoundCursor; import org.springframework.data.redis.core.ScanIteration; import org.springframework.data.redis.core.ScanOptions; -import redis.clients.jedis.ScanParams; /** * @author Christoph Strobl @@ -214,11 +215,13 @@ class JedisSetCommands implements RedisSetCommands { public Boolean sMove(byte[] srcKey, byte[] destKey, byte[] value) { try { if (isPipelined()) { - pipeline(connection.newJedisResult(connection.getPipeline().smove(srcKey, destKey, value), JedisConverters.longToBoolean())); + pipeline(connection.newJedisResult(connection.getPipeline().smove(srcKey, destKey, value), + JedisConverters.longToBoolean())); return null; } if (isQueueing()) { - transaction(connection.newJedisResult(connection.getTransaction().smove(srcKey, destKey, value), JedisConverters.longToBoolean())); + transaction(connection.newJedisResult(connection.getTransaction().smove(srcKey, destKey, value), + JedisConverters.longToBoolean())); return null; } return JedisConverters.toBoolean(connection.getJedis().smove(srcKey, destKey, value)); @@ -387,7 +390,8 @@ class JedisSetCommands implements RedisSetCommands { ScanParams params = JedisConverters.toScanParams(options); - redis.clients.jedis.ScanResult result = connection.getJedis().sscan(key, JedisConverters.toBytes(cursorId), params); + redis.clients.jedis.ScanResult result = connection.getJedis().sscan(key, + JedisConverters.toBytes(cursorId), params); return new ScanIteration<>(Long.valueOf(result.getStringCursor()), result.getResult()); } diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisStringCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisStringCommands.java index 6e95f4903..9adffca78 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisStringCommands.java @@ -77,7 +77,6 @@ class JedisStringCommands implements RedisStringCommands { @Override public List mGet(byte[]... keys) { - try { if (isPipelined()) { pipeline(connection.newJedisResult(connection.getPipeline().mget(keys))); @@ -164,7 +163,8 @@ class JedisStringCommands implements RedisStringCommands { "Expiration.expirationTime must be less than Integer.MAX_VALUE for pipeline in Jedis."); } - pipeline(connection.newStatusResult(connection.getPipeline().set(key, value, nxxx, expx, (int) expiration.getExpirationTime()))); + pipeline(connection.newStatusResult( + connection.getPipeline().set(key, value, nxxx, expx, (int) expiration.getExpirationTime()))); return; } if (isQueueing()) { @@ -174,8 +174,8 @@ class JedisStringCommands implements RedisStringCommands { "Expiration.expirationTime must be less than Integer.MAX_VALUE for transactions in Jedis."); } - transaction( - connection.newStatusResult(connection.getTransaction().set(key, value, nxxx, expx, (int) expiration.getExpirationTime()))); + transaction(connection.newStatusResult( + connection.getTransaction().set(key, value, nxxx, expx, (int) expiration.getExpirationTime()))); return; } @@ -188,18 +188,18 @@ class JedisStringCommands implements RedisStringCommands { } } - - @Override public Boolean setNX(byte[] key, byte[] value) { try { if (isPipelined()) { - pipeline(connection.newJedisResult(connection.getPipeline().setnx(key, value), JedisConverters.longToBoolean())); + pipeline( + connection.newJedisResult(connection.getPipeline().setnx(key, value), JedisConverters.longToBoolean())); return null; } if (isQueueing()) { - transaction(connection.newJedisResult(connection.getTransaction().setnx(key, value), JedisConverters.longToBoolean())); + transaction( + connection.newJedisResult(connection.getTransaction().setnx(key, value), JedisConverters.longToBoolean())); return null; } return JedisConverters.toBoolean(connection.getJedis().setnx(key, value)); @@ -271,13 +271,13 @@ class JedisStringCommands implements RedisStringCommands { try { if (isPipelined()) { - pipeline( - connection.newJedisResult(connection.getPipeline().msetnx(JedisConverters.toByteArrays(tuples)), JedisConverters.longToBoolean())); + pipeline(connection.newJedisResult(connection.getPipeline().msetnx(JedisConverters.toByteArrays(tuples)), + JedisConverters.longToBoolean())); return null; } if (isQueueing()) { - transaction( - connection.newJedisResult(connection.getTransaction().msetnx(JedisConverters.toByteArrays(tuples)), JedisConverters.longToBoolean())); + transaction(connection.newJedisResult(connection.getTransaction().msetnx(JedisConverters.toByteArrays(tuples)), + JedisConverters.longToBoolean())); return null; } return JedisConverters.toBoolean(connection.getJedis().msetnx(JedisConverters.toByteArrays(tuples))); @@ -406,11 +406,13 @@ class JedisStringCommands implements RedisStringCommands { try { if (isPipelined()) { - pipeline(connection.newJedisResult(connection.getPipeline().substr(key, (int) start, (int) end), JedisConverters.stringToBytes())); + pipeline(connection.newJedisResult(connection.getPipeline().substr(key, (int) start, (int) end), + JedisConverters.stringToBytes())); return null; } if (isQueueing()) { - transaction(connection.newJedisResult(connection.getTransaction().substr(key, (int) start, (int) end), JedisConverters.stringToBytes())); + transaction(connection.newJedisResult(connection.getTransaction().substr(key, (int) start, (int) end), + JedisConverters.stringToBytes())); return null; } return connection.getJedis().substr(key, (int) start, (int) end); @@ -472,7 +474,8 @@ class JedisStringCommands implements RedisStringCommands { return null; } if (isQueueing()) { - transaction(connection.newJedisResult(connection.getTransaction().setbit(key, offset, JedisConverters.toBit(value)))); + transaction( + connection.newJedisResult(connection.getTransaction().setbit(key, offset, JedisConverters.toBit(value)))); return null; } return connection.getJedis().setbit(key, offset, JedisConverters.toBit(value)); @@ -521,17 +524,18 @@ class JedisStringCommands implements RedisStringCommands { @Override public Long bitOp(BitOperation op, byte[] destination, byte[]... keys) { - if (op == BitOperation.NOT && keys.length > 1) { throw new UnsupportedOperationException("Bitop NOT should only be performed against one key"); } try { if (isPipelined()) { - pipeline(connection.newJedisResult(connection.getPipeline().bitop(JedisConverters.toBitOp(op), destination, keys))); + pipeline( + connection.newJedisResult(connection.getPipeline().bitop(JedisConverters.toBitOp(op), destination, keys))); return null; } if (isQueueing()) { - transaction(connection.newJedisResult(connection.getTransaction().bitop(JedisConverters.toBitOp(op), destination, keys))); + transaction(connection + .newJedisResult(connection.getTransaction().bitop(JedisConverters.toBitOp(op), destination, keys))); return null; } return connection.getJedis().bitop(JedisConverters.toBitOp(op), destination, keys); diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisUtils.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisUtils.java index 2f4820919..edcea0c96 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisUtils.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisUtils.java @@ -16,6 +16,15 @@ package org.springframework.data.redis.connection.jedis; +import redis.clients.jedis.BinaryClient.LIST_POSITION; +import redis.clients.jedis.BinaryJedisPubSub; +import redis.clients.jedis.Protocol; +import redis.clients.jedis.SortingParams; +import redis.clients.jedis.exceptions.JedisConnectionException; +import redis.clients.jedis.exceptions.JedisDataException; +import redis.clients.jedis.exceptions.JedisException; +import redis.clients.util.SafeEncoder; + import java.io.IOException; import java.io.StringReader; import java.net.UnknownHostException; @@ -34,23 +43,14 @@ import org.springframework.data.redis.RedisConnectionFailureException; import org.springframework.data.redis.RedisSystemException; import org.springframework.data.redis.connection.DefaultTuple; import org.springframework.data.redis.connection.MessageListener; -import org.springframework.data.redis.connection.ReturnType; import org.springframework.data.redis.connection.RedisListCommands.Position; import org.springframework.data.redis.connection.RedisZSetCommands.Tuple; +import org.springframework.data.redis.connection.ReturnType; import org.springframework.data.redis.connection.SortParameters; import org.springframework.data.redis.connection.SortParameters.Order; import org.springframework.data.redis.connection.SortParameters.Range; import org.springframework.util.Assert; -import redis.clients.jedis.BinaryClient.LIST_POSITION; -import redis.clients.jedis.BinaryJedisPubSub; -import redis.clients.jedis.Protocol; -import redis.clients.jedis.SortingParams; -import redis.clients.jedis.exceptions.JedisConnectionException; -import redis.clients.jedis.exceptions.JedisDataException; -import redis.clients.jedis.exceptions.JedisException; -import redis.clients.util.SafeEncoder; - /** * Helper class featuring methods for Jedis connection handling, providing support for exception translation. Deprecated * in favor of {@link JedisConverters} @@ -126,7 +126,7 @@ public abstract class JedisUtils { */ @Deprecated static Set convertJedisTuple(Set tuples) { - Set value = new LinkedHashSet(tuples.size()); + Set value = new LinkedHashSet<>(tuples.size()); for (redis.clients.jedis.Tuple tuple : tuples) { value.add(new DefaultTuple(tuple.getBinaryElement(), tuple.getScore())); } @@ -150,7 +150,7 @@ public abstract class JedisUtils { */ @Deprecated static Map convert(String[] fields, String[] values) { - Map result = new LinkedHashMap(fields.length); + Map result = new LinkedHashMap<>(fields.length); for (int i = 0; i < values.length; i++) { result.put(fields[i], values[i]); @@ -256,7 +256,7 @@ public abstract class JedisUtils { } static byte[][] bXPopArgs(int timeout, byte[]... keys) { - final List args = new ArrayList(); + final List args = new ArrayList<>(); for (final byte[] arg : keys) { args.add(arg); } @@ -298,7 +298,7 @@ public abstract class JedisUtils { } if (returnType == ReturnType.MULTI) { List resultList = (List) result; - List convertedResults = new ArrayList(); + List convertedResults = new ArrayList<>(); for (Object res : resultList) { if (res instanceof String) { // evalsha converts byte[] to String. Convert back for consistency diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisZSetCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisZSetCommands.java index 6174a2cf2..165b9fa2b 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisZSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisZSetCommands.java @@ -811,7 +811,7 @@ class JedisZSetCommands implements RedisZSetCommands { private Map zAddArgs(Set tuples) { Map args = new LinkedHashMap<>(tuples.size(), 1); - Set scores = new HashSet(tuples.size(), 1); + Set scores = new HashSet<>(tuples.size(), 1); boolean isAtLeastJedis24 = JedisVersionUtil.atLeastJedis24(); diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettucePool.java b/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettucePool.java index d227e61f5..dec889bf9 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettucePool.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettucePool.java @@ -36,7 +36,7 @@ import org.springframework.util.StringUtils; /** * Default implementation of {@link LettucePool}. - * + * * @author Jennifer Hickey * @author Christoph Strobl * @author Mark Paluch @@ -62,7 +62,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { /** * Uses the {@link Config} and {@link RedisClient} defaults for configuring the connection pool - * + * * @param hostName The Redis host * @param port The Redis port */ @@ -84,7 +84,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { /** * Uses the {@link RedisClient} defaults for configuring the connection pool - * + * * @param hostName The Redis host * @param port The Redis port * @param poolConfig The pool {@link GenericObjectPoolConfig} @@ -117,8 +117,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { } client.setDefaultTimeout(timeout, TimeUnit.MILLISECONDS); - this.internalPool = new GenericObjectPool>(new LettuceFactory(client, dbIndex), - poolConfig); + this.internalPool = new GenericObjectPool<>(new LettuceFactory(client, dbIndex), poolConfig); } /** @@ -220,7 +219,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { /** * Returns the index of the database. - * + * * @return Returns the database index */ public int getDatabase() { @@ -229,7 +228,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { /** * Sets the index of the database used by this connection pool. Default is 0. - * + * * @param index database index */ public void setDatabase(int index) { @@ -239,7 +238,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { /** * Returns the password used for authenticating with the Redis server. - * + * * @return password for authentication */ public String getPassword() { @@ -248,7 +247,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { /** * Sets the password used for authenticating with the Redis server. - * + * * @param password the password to set */ public void setPassword(String password) { @@ -257,7 +256,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { /** * Returns the current host. - * + * * @return the host */ public String getHostName() { @@ -266,7 +265,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { /** * Sets the host. - * + * * @param host the host to set */ public void setHostName(String host) { @@ -275,7 +274,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { /** * Returns the current port. - * + * * @return the port */ public int getPort() { @@ -284,7 +283,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { /** * Sets the port. - * + * * @param port the port to set */ public void setPort(int port) { @@ -293,7 +292,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { /** * Returns the connection timeout (in milliseconds). - * + * * @return connection timeout */ public long getTimeout() { @@ -302,7 +301,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { /** * Sets the connection timeout (in milliseconds). - * + * * @param timeout connection timeout */ public void setTimeout(long timeout) { @@ -311,7 +310,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { /** * Get the {@link ClientResources} to reuse infrastructure. - * + * * @return {@literal null} if not set. * @since 1.7 */ @@ -322,7 +321,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { /** * Sets the {@link ClientResources} to reuse the client infrastructure.
    * Set to {@literal null} to not share resources. - * + * * @param clientResources can be {@literal null}. * @since 1.7 */ @@ -399,7 +398,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { */ @Override public PooledObject> wrap(StatefulConnection obj) { - return new DefaultPooledObject>(obj); + return new DefaultPooledObject<>(obj); } } } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnection.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnection.java index 5a62a28f9..0e96928f0 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnection.java @@ -17,6 +17,7 @@ package org.springframework.data.redis.connection.lettuce; import io.lettuce.core.RedisException; import io.lettuce.core.api.StatefulConnection; +import io.lettuce.core.api.sync.BaseRedisCommands; import io.lettuce.core.cluster.RedisClusterClient; import io.lettuce.core.cluster.SlotHash; import io.lettuce.core.cluster.api.StatefulRedisClusterConnection; @@ -31,8 +32,6 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; import java.util.Set; import org.springframework.beans.DirectFieldAccessor; @@ -40,28 +39,13 @@ import org.springframework.beans.factory.DisposableBean; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.redis.ExceptionTranslationStrategy; import org.springframework.data.redis.PassThroughExceptionTranslationStrategy; -import org.springframework.data.redis.connection.ClusterCommandExecutor; +import org.springframework.data.redis.connection.*; import org.springframework.data.redis.connection.ClusterCommandExecutor.ClusterCommandCallback; import org.springframework.data.redis.connection.ClusterCommandExecutor.MultiKeyClusterCommandCallback; import org.springframework.data.redis.connection.ClusterCommandExecutor.NodeResult; -import org.springframework.data.redis.connection.ClusterInfo; -import org.springframework.data.redis.connection.ClusterNodeResourceProvider; -import org.springframework.data.redis.connection.ClusterTopology; -import org.springframework.data.redis.connection.ClusterTopologyProvider; -import org.springframework.data.redis.connection.RedisClusterNode; import org.springframework.data.redis.connection.RedisClusterNode.SlotRange; -import org.springframework.data.redis.connection.RedisGeoCommands; -import org.springframework.data.redis.connection.RedisHashCommands; -import org.springframework.data.redis.connection.RedisHyperLogLogCommands; -import org.springframework.data.redis.connection.RedisKeyCommands; -import org.springframework.data.redis.connection.RedisListCommands; -import org.springframework.data.redis.connection.RedisSetCommands; -import org.springframework.data.redis.connection.RedisStringCommands; -import org.springframework.data.redis.connection.RedisZSetCommands; import org.springframework.data.redis.connection.convert.Converters; -import org.springframework.data.redis.core.types.RedisClientInfo; import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; /** @@ -69,8 +53,7 @@ import org.springframework.util.ObjectUtils; * @author Mark Paluch * @since 1.7 */ -public class LettuceClusterConnection extends LettuceConnection - implements org.springframework.data.redis.connection.RedisClusterConnection { +public class LettuceClusterConnection extends LettuceConnection implements DefaultedRedisClusterConnection { static final ExceptionTranslationStrategy exceptionConverter = new PassThroughExceptionTranslationStrategy( new LettuceExceptionConverter()); @@ -82,7 +65,7 @@ public class LettuceClusterConnection extends LettuceConnection /** * Creates new {@link LettuceClusterConnection} using {@link RedisClusterClient}. - * + * * @param clusterClient must not be {@literal null}. */ public LettuceClusterConnection(RedisClusterClient clusterClient) { @@ -116,21 +99,37 @@ public class LettuceClusterConnection extends LettuceConnection clusterCommandExecutor = executor; } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#geoCommands() + */ @Override public RedisGeoCommands geoCommands() { return new LettuceClusterGeoCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#hashCommands() + */ @Override public RedisHashCommands hashCommands() { return new LettuceClusterHashCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#hyperLogLogCommands() + */ @Override public RedisHyperLogLogCommands hyperLogLogCommands() { return new LettuceClusterHyperLogLogCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#keyCommands() + */ @Override public RedisKeyCommands keyCommands() { return doGetClusterKeyCommands(); @@ -140,21 +139,37 @@ public class LettuceClusterConnection extends LettuceConnection return new LettuceClusterKeyCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#listCommands() + */ @Override public RedisListCommands listCommands() { return new LettuceClusterListCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#stringCommands() + */ @Override public RedisStringCommands stringCommands() { return new LettuceClusterStringCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#setCommands() + */ @Override public RedisSetCommands setCommands() { return new LettuceClusterSetCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#zSetCommands() + */ @Override public RedisZSetCommands zSetCommands() { return new LettuceClusterZSetCommands(this); @@ -162,128 +177,11 @@ public class LettuceClusterConnection extends LettuceConnection /* * (non-Javadoc) - * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#flushAll() + * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#serverCommands() */ @Override - public void flushAll() { - - clusterCommandExecutor.executeCommandOnAllNodes(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.flushall(); - } - }); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#flushDb() - */ - @Override - public void flushDb() { - - clusterCommandExecutor.executeCommandOnAllNodes(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.flushdb(); - } - }); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#dbSize() - */ - @Override - public Long dbSize() { - - Collection dbSizes = clusterCommandExecutor - .executeCommandOnAllNodes(new LettuceClusterCommandCallback() { - - @Override - public Long doInCluster(RedisClusterCommands client) { - return client.dbsize(); - } - - }).resultsAsList(); - - if (CollectionUtils.isEmpty(dbSizes)) { - return 0L; - } - - Long size = 0L; - for (Long value : dbSizes) { - size += value; - } - return size; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#info() - */ - @Override - public Properties info() { - - Properties infos = new Properties(); - - List> nodeResults = clusterCommandExecutor - .executeCommandOnAllNodes(new LettuceClusterCommandCallback() { - - @Override - public Properties doInCluster(RedisClusterCommands client) { - return LettuceConverters.toProperties(client.info()); - } - }).getResults(); - - for (NodeResult nodePorperties : nodeResults) { - for (Entry entry : nodePorperties.getValue().entrySet()) { - infos.put(nodePorperties.getNode().asString() + "." + entry.getKey(), entry.getValue()); - } - } - - return infos; - } - - @Override - public Properties info(final String section) { - - Properties infos = new Properties(); - List> nodeResults = clusterCommandExecutor - .executeCommandOnAllNodes(new LettuceClusterCommandCallback() { - - @Override - public Properties doInCluster(RedisClusterCommands client) { - return LettuceConverters.toProperties(client.info(section)); - } - }).getResults(); - - for (NodeResult nodePorperties : nodeResults) { - for (Entry entry : nodePorperties.getValue().entrySet()) { - infos.put(nodePorperties.getNode().asString() + "." + entry.getKey(), entry.getValue()); - } - } - - return infos; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#info(org.springframework.data.redis.connection.RedisClusterNode, java.lang.String) - */ - @Override - public Properties info(RedisClusterNode node, final String section) { - - return LettuceConverters - .toProperties(clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.info(section); - } - }, node).getValue()); + public RedisClusterServerCommands serverCommands() { + return new LettuceClusterServerCommands(this); } /* @@ -298,13 +196,9 @@ public class LettuceClusterConnection extends LettuceConnection final RedisClusterNode nodeToUse = topologyProvider.getTopology().lookup(master); return clusterCommandExecutor - .executeCommandOnSingleNode(new LettuceClusterCommandCallback>() { - - @Override - public Set doInCluster(RedisClusterCommands client) { - return LettuceConverters.toSetOfRedisClusterNodes(client.clusterSlaves(nodeToUse.getId())); - } - }, master).getValue(); + .executeCommandOnSingleNode((LettuceClusterCommandCallback>) client -> LettuceConverters + .toSetOfRedisClusterNodes(client.clusterSlaves(nodeToUse.getId())), master) + .getValue(); } /* @@ -344,13 +238,10 @@ public class LettuceClusterConnection extends LettuceConnection @Override public ClusterInfo clusterGetClusterInfo() { - return clusterCommandExecutor.executeCommandOnArbitraryNode(new LettuceClusterCommandCallback() { - - @Override - public ClusterInfo doInCluster(RedisClusterCommands client) { - return new ClusterInfo(LettuceConverters.toProperties(client.clusterInfo())); - } - }).getValue(); + return clusterCommandExecutor + .executeCommandOnArbitraryNode((LettuceClusterCommandCallback) client -> new ClusterInfo( + LettuceConverters.toProperties(client.clusterInfo()))) + .getValue(); } /* @@ -360,13 +251,8 @@ public class LettuceClusterConnection extends LettuceConnection @Override public void clusterAddSlots(RedisClusterNode node, final int... slots) { - clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.clusterAddSlots(slots); - } - }, node); + clusterCommandExecutor.executeCommandOnSingleNode( + (LettuceClusterCommandCallback) client -> client.clusterAddSlots(slots), node); } @@ -388,14 +274,8 @@ public class LettuceClusterConnection extends LettuceConnection */ @Override public void clusterDeleteSlots(RedisClusterNode node, final int... slots) { - - clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.clusterDelSlots(slots); - } - }, node); + clusterCommandExecutor.executeCommandOnSingleNode( + (LettuceClusterCommandCallback) client -> client.clusterDelSlots(slots), node); } /* @@ -417,18 +297,12 @@ public class LettuceClusterConnection extends LettuceConnection @Override public void clusterForget(final RedisClusterNode node) { - List nodes = new ArrayList(clusterGetNodes()); + List nodes = new ArrayList<>(clusterGetNodes()); final RedisClusterNode nodeToRemove = topologyProvider.getTopology().lookup(node); nodes.remove(nodeToRemove); - this.clusterCommandExecutor.executeCommandAsyncOnNodes(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.clusterForget(nodeToRemove.getId()); - } - - }, nodes); + this.clusterCommandExecutor.executeCommandAsyncOnNodes( + (LettuceClusterCommandCallback) client -> client.clusterForget(nodeToRemove.getId()), nodes); } /* @@ -442,13 +316,8 @@ public class LettuceClusterConnection extends LettuceConnection Assert.hasText(node.getHost(), "Node to meet cluster must have a host!"); Assert.isTrue(node.getPort() > 0, "Node to meet cluster must have a port greater 0!"); - this.clusterCommandExecutor.executeCommandOnAllNodes(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.clusterMeet(node.getHost(), node.getPort()); - } - }); + this.clusterCommandExecutor.executeCommandOnAllNodes( + (LettuceClusterCommandCallback) client -> client.clusterMeet(node.getHost(), node.getPort())); } /* @@ -464,22 +333,18 @@ public class LettuceClusterConnection extends LettuceConnection final RedisClusterNode nodeToUse = topologyProvider.getTopology().lookup(node); final String nodeId = nodeToUse.getId(); - clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - switch (mode) { - case MIGRATING: - return client.clusterSetSlotMigrating(slot, nodeId); - case IMPORTING: - return client.clusterSetSlotImporting(slot, nodeId); - case NODE: - return client.clusterSetSlotNode(slot, nodeId); - case STABLE: - return client.clusterSetSlotStable(slot); - default: - throw new InvalidDataAccessApiUsageException("Invalid import mode for cluster slot: " + slot); - } + clusterCommandExecutor.executeCommandOnSingleNode((LettuceClusterCommandCallback) client -> { + switch (mode) { + case MIGRATING: + return client.clusterSetSlotMigrating(slot, nodeId); + case IMPORTING: + return client.clusterSetSlotImporting(slot, nodeId); + case NODE: + return client.clusterSetSlotNode(slot, nodeId); + case STABLE: + return client.clusterSetSlotStable(slot); + default: + throw new InvalidDataAccessApiUsageException("Invalid import mode for cluster slot: " + slot); } }, node); } @@ -520,13 +385,8 @@ public class LettuceClusterConnection extends LettuceConnection public void clusterReplicate(final RedisClusterNode master, RedisClusterNode slave) { final RedisClusterNode masterNode = topologyProvider.getTopology().lookup(master); - clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.clusterReplicate(masterNode.getId()); - } - }, slave); + clusterCommandExecutor.executeCommandOnSingleNode( + (LettuceClusterCommandCallback) client -> client.clusterReplicate(masterNode.getId()), slave); } /* @@ -536,13 +396,7 @@ public class LettuceClusterConnection extends LettuceConnection @Override public String ping() { Collection ping = clusterCommandExecutor - .executeCommandOnAllNodes(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands connection) { - return connection.ping(); - } - }).resultsAsList(); + .executeCommandOnAllNodes((LettuceClusterCommandCallback) BaseRedisCommands::ping).resultsAsList(); for (String result : ping) { if (!ObjectUtils.nullSafeEquals("PONG", result)) { @@ -560,144 +414,8 @@ public class LettuceClusterConnection extends LettuceConnection @Override public String ping(RedisClusterNode node) { - return clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.ping(); - } - }, node).getValue(); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#bgReWriteAof(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public void bgReWriteAof(RedisClusterNode node) { - - clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.bgrewriteaof(); - } - }, node); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#bgSave(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public void bgSave(RedisClusterNode node) { - - clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.bgsave(); - } - }, node); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#lastSave(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public Long lastSave(RedisClusterNode node) { - - return clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() { - - @Override - public Long doInCluster(RedisClusterCommands client) { - return client.lastsave().getTime(); - } - }, node).getValue(); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#save(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public void save(RedisClusterNode node) { - - clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.save(); - } - }, node); - - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#dbSize(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public Long dbSize(RedisClusterNode node) { - - return clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() { - - @Override - public Long doInCluster(RedisClusterCommands client) { - return client.dbsize(); - } - }, node).getValue(); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#flushDb(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public void flushDb(RedisClusterNode node) { - - clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.flushdb(); - } - }, node); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#flushAll(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public void flushAll(RedisClusterNode node) { - - clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.flushall(); - } - }, node); - - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#info(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public Properties info(RedisClusterNode node) { - - return LettuceConverters - .toProperties(clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.info(); - } - }, node).getValue()); + return clusterCommandExecutor + .executeCommandOnSingleNode((LettuceClusterCommandCallback) BaseRedisCommands::ping, node).getValue(); } /* @@ -713,23 +431,6 @@ public class LettuceClusterConnection extends LettuceConnection return doGetClusterKeyCommands().randomKey(node); } - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#shutdown(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public void shutdown(RedisClusterNode node) { - - clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() { - - @Override - public Void doInCluster(RedisClusterCommands client) { - client.shutdown(true); - return null; - } - }, node); - } - /* * (non-Javadoc) * @see org.springframework.data.redis.connection.RedisConnectionCommands#select(int) @@ -789,200 +490,6 @@ public class LettuceClusterConnection extends LettuceConnection throw new InvalidDataAccessApiUsageException("MULTI is currently not supported in cluster mode."); } - /* - * - * (non-Javadoc) - * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#getConfig(java.lang.String) - */ - @Override - public List getConfig(final String pattern) { - - List>> mapResult = clusterCommandExecutor - .executeCommandOnAllNodes(new LettuceClusterCommandCallback>() { - - @Override - public List doInCluster(RedisClusterCommands client) { - return client.configGet(pattern); - } - }).getResults(); - - List result = new ArrayList(); - for (NodeResult> entry : mapResult) { - - String prefix = entry.getNode().asString(); - int i = 0; - for (String value : entry.getValue()) { - result.add((i++ % 2 == 0 ? (prefix + ".") : "") + value); - } - } - - return result; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#getConfig(org.springframework.data.redis.connection.RedisClusterNode, java.lang.String) - */ - @Override - public List getConfig(RedisClusterNode node, final String pattern) { - - return clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback>() { - - @Override - public List doInCluster(RedisClusterCommands client) { - return client.configGet(pattern); - } - }, node).getValue(); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#setConfig(java.lang.String, java.lang.String) - */ - @Override - public void setConfig(final String param, final String value) { - - clusterCommandExecutor.executeCommandOnAllNodes(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.configSet(param, value); - } - }); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#setConfig(org.springframework.data.redis.connection.RedisClusterNode, java.lang.String, java.lang.String) - */ - @Override - public void setConfig(RedisClusterNode node, final String param, final String value) { - - clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.configSet(param, value); - } - }, node); - - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#resetConfigStats() - */ - @Override - public void resetConfigStats() { - - clusterCommandExecutor.executeCommandOnAllNodes(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.configResetstat(); - } - }); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#resetConfigStats(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public void resetConfigStats(RedisClusterNode node) { - - clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.configResetstat(); - } - }, node); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#time() - */ - @Override - public Long time() { - - return convertListOfStringToTime( - clusterCommandExecutor.executeCommandOnArbitraryNode(new LettuceClusterCommandCallback>() { - - @Override - public List doInCluster(RedisClusterCommands client) { - return client.time(); - } - }).getValue()); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#time(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public Long time(RedisClusterNode node) { - - return convertListOfStringToTime( - clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback>() { - - @Override - public List doInCluster(RedisClusterCommands client) { - return client.time(); - } - }, node).getValue()); - } - - private Long convertListOfStringToTime(List serverTimeInformation) { - - Assert.notEmpty(serverTimeInformation, "Received invalid result from server. Expected 2 items in collection."); - Assert.isTrue(serverTimeInformation.size() == 2, - "Received invalid number of arguments from redis server. Expected 2 received " + serverTimeInformation.size()); - - return Converters.toTimeMillis(LettuceConverters.toString(serverTimeInformation.get(0)), - LettuceConverters.toString(serverTimeInformation.get(1))); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#getClientList() - */ - @Override - public List getClientList() { - - List map = clusterCommandExecutor.executeCommandOnAllNodes(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.clientList(); - } - }).resultsAsList(); - - ArrayList result = new ArrayList(); - for (String infos : map) { - result.addAll(LettuceConverters.toListOfRedisClientInformation(infos)); - } - return result; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisClusterConnection#getClientList(org.springframework.data.redis.connection.RedisClusterNode) - */ - @Override - public List getClientList(RedisClusterNode node) { - - return LettuceConverters.toListOfRedisClientInformation( - clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback() { - - @Override - public String doInCluster(RedisClusterCommands client) { - return client.clientList(); - } - }, node).getValue()); - } - /* * (non-Javadoc) * @see org.springframework.data.redis.connection.RedisClusterCommands#clusterGetMasterSlaveMap() @@ -991,15 +498,13 @@ public class LettuceClusterConnection extends LettuceConnection public Map> clusterGetMasterSlaveMap() { List>> nodeResults = clusterCommandExecutor - .executeCommandAsyncOnNodes(new LettuceClusterCommandCallback>() { + .executeCommandAsyncOnNodes( + (LettuceClusterCommandCallback>) client -> Converters + .toSetOfRedisClusterNodes(client.clusterSlaves(client.clusterMyId())), + topologyProvider.getTopology().getActiveMasterNodes()) + .getResults(); - @Override - public Set doInCluster(RedisClusterCommands client) { - return Converters.toSetOfRedisClusterNodes(client.clusterSlaves(client.clusterMyId())); - } - }, topologyProvider.getTopology().getActiveMasterNodes()).getResults(); - - Map> result = new LinkedHashMap>(); + Map> result = new LinkedHashMap<>(); for (NodeResult> nodeResult : nodeResults) { result.put(nodeResult.getNode(), nodeResult.getValue()); @@ -1114,7 +619,7 @@ public class LettuceClusterConnection extends LettuceConnection @Override public ClusterTopology getTopology() { return new ClusterTopology( - new LinkedHashSet(LettuceConverters.partitionsToClusterNodes(client.getPartitions()))); + new LinkedHashSet<>(LettuceConverters.partitionsToClusterNodes(client.getPartitions()))); } } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterKeyCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterKeyCommands.java index ef18f90a3..cf2b76086 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterKeyCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterKeyCommands.java @@ -15,13 +15,11 @@ */ package org.springframework.data.redis.connection.lettuce; -import io.lettuce.core.cluster.api.sync.RedisClusterCommands; - import java.util.Collection; import java.util.HashSet; import java.util.List; -import java.util.Random; import java.util.Set; +import java.util.concurrent.ThreadLocalRandom; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.redis.connection.ClusterSlotHashUtil; @@ -53,13 +51,13 @@ class LettuceClusterKeyCommands extends LettuceKeyCommands { */ @Override public Cursor scan(long cursorId, ScanOptions options) { - throw new InvalidDataAccessApiUsageException("Scan is not supported accros multiple nodes within a cluster."); + throw new InvalidDataAccessApiUsageException("Scan is not supported across multiple nodes within a cluster."); } /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#randomKey() - */ + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#randomKey() + */ @Override public byte[] randomKey() { @@ -68,10 +66,10 @@ class LettuceClusterKeyCommands extends LettuceKeyCommands { do { - RedisClusterNode node = nodes.get(new Random().nextInt(nodes.size())); + RedisClusterNode node = nodes.get(ThreadLocalRandom.current().nextInt(nodes.size())); while (inspectedNodes.contains(node)) { - node = nodes.get(new Random().nextInt(nodes.size())); + node = nodes.get(ThreadLocalRandom.current().nextInt(nodes.size())); } inspectedNodes.add(node); byte[] key = randomKey(node); @@ -177,13 +175,8 @@ class LettuceClusterKeyCommands extends LettuceKeyCommands { public byte[] randomKey(RedisClusterNode node) { return connection.getClusterCommandExecutor() - .executeCommandOnSingleNode(new LettuceClusterCommandCallback() { - - @Override - public byte[] doInCluster(RedisClusterCommands client) { - return client.randomkey(); - } - }, node).getValue(); + .executeCommandOnSingleNode((LettuceClusterCommandCallback) client -> client.randomkey(), node) + .getValue(); } /* @@ -193,13 +186,8 @@ class LettuceClusterKeyCommands extends LettuceKeyCommands { public Set keys(RedisClusterNode node, final byte[] pattern) { return LettuceConverters.toBytesSet(connection.getClusterCommandExecutor() - .executeCommandOnSingleNode(new LettuceClusterCommandCallback>() { - - @Override - public List doInCluster(RedisClusterCommands client) { - return client.keys(pattern); - } - }, node).getValue()); + .executeCommandOnSingleNode((LettuceClusterCommandCallback>) client -> client.keys(pattern), node) + .getValue()); } /* diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterListCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterListCommands.java index 0bdcd2e09..7abf355b7 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterListCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterListCommands.java @@ -40,9 +40,9 @@ class LettuceClusterListCommands extends LettuceListCommands { } /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#bLPop(int, byte[][]) - */ + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceConnection#bLPop(int, byte[][]) + */ @Override public List bLPop(final int timeout, byte[]... keys) { diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterServerCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterServerCommands.java new file mode 100644 index 000000000..3a79bf9ef --- /dev/null +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterServerCommands.java @@ -0,0 +1,378 @@ +/* + * Copyright 2017 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.lettuce; + +import io.lettuce.core.api.sync.RedisServerCommands; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map.Entry; +import java.util.Properties; + +import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.data.redis.connection.ClusterCommandExecutor.MulitNodeResult; +import org.springframework.data.redis.connection.ClusterCommandExecutor.NodeResult; +import org.springframework.data.redis.connection.RedisClusterNode; +import org.springframework.data.redis.connection.RedisClusterServerCommands; +import org.springframework.data.redis.connection.convert.Converters; +import org.springframework.data.redis.connection.lettuce.LettuceClusterConnection.LettuceClusterCommandCallback; +import org.springframework.data.redis.core.types.RedisClientInfo; +import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; + +/** + * @author Mark Paluch + * @since 2.0 + */ +class LettuceClusterServerCommands extends LettuceServerCommands implements RedisClusterServerCommands { + + private final LettuceClusterConnection connection; + + public LettuceClusterServerCommands(LettuceClusterConnection connection) { + + super(connection); + this.connection = connection; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#bgReWriteAof(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public void bgReWriteAof(RedisClusterNode node) { + executeCommandOnSingleNode(RedisServerCommands::bgrewriteaof, node); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#bgSave(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public void bgSave(RedisClusterNode node) { + executeCommandOnSingleNode(RedisServerCommands::bgsave, node); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#lastSave(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public Long lastSave(RedisClusterNode node) { + return executeCommandOnSingleNode(client -> client.lastsave().getTime(), node).getValue(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#save(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public void save(RedisClusterNode node) { + executeCommandOnSingleNode(RedisServerCommands::save, node); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceServerCommands#dbSize() + */ + @Override + public Long dbSize() { + + Collection dbSizes = executeCommandOnAllNodes(RedisServerCommands::dbsize).resultsAsList(); + + if (CollectionUtils.isEmpty(dbSizes)) { + return 0L; + } + + Long size = 0L; + for (Long value : dbSizes) { + size += value; + } + return size; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#dbSize(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public Long dbSize(RedisClusterNode node) { + return executeCommandOnSingleNode(RedisServerCommands::dbsize, node).getValue(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceServerCommands#flushDb() + */ + @Override + public void flushDb() { + executeCommandOnAllNodes(RedisServerCommands::flushdb); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#flushDb(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public void flushDb(RedisClusterNode node) { + executeCommandOnSingleNode(RedisServerCommands::flushdb, node); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceServerCommands#flushAll() + */ + @Override + public void flushAll() { + executeCommandOnAllNodes(RedisServerCommands::flushall); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#flushAll(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public void flushAll(RedisClusterNode node) { + executeCommandOnSingleNode(RedisServerCommands::flushall, node); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#info(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public Properties info(RedisClusterNode node) { + return LettuceConverters.toProperties(executeCommandOnSingleNode(RedisServerCommands::info, node).getValue()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceServerCommands#info() + */ + @Override + public Properties info() { + + Properties infos = new Properties(); + + List> nodeResults = executeCommandOnAllNodes( + client -> LettuceConverters.toProperties(client.info())).getResults(); + + for (NodeResult nodePorperties : nodeResults) { + for (Entry entry : nodePorperties.getValue().entrySet()) { + infos.put(nodePorperties.getNode().asString() + "." + entry.getKey(), entry.getValue()); + } + } + + return infos; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceServerCommands#info(java.lang.String) + */ + @Override + public Properties info(final String section) { + + Properties infos = new Properties(); + List> nodeResults = executeCommandOnAllNodes( + client -> LettuceConverters.toProperties(client.info(section))).getResults(); + + for (NodeResult nodePorperties : nodeResults) { + for (Entry entry : nodePorperties.getValue().entrySet()) { + infos.put(nodePorperties.getNode().asString() + "." + entry.getKey(), entry.getValue()); + } + } + + return infos; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#info(org.springframework.data.redis.connection.RedisClusterNode, java.lang.String) + */ + @Override + public Properties info(RedisClusterNode node, final String section) { + return LettuceConverters.toProperties(executeCommandOnSingleNode(client -> client.info(section), node).getValue()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#shutdown(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public void shutdown(RedisClusterNode node) { + + executeCommandOnSingleNode((LettuceClusterCommandCallback) client -> { + client.shutdown(true); + return null; + }, node); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceServerCommands#getConfig(java.lang.String) + */ + @Override + public List getConfig(final String pattern) { + + List>> mapResult = executeCommandOnAllNodes(client -> client.configGet(pattern)) + .getResults(); + + List result = new ArrayList<>(); + for (NodeResult> entry : mapResult) { + + String prefix = entry.getNode().asString(); + int i = 0; + for (String value : entry.getValue()) { + result.add((i++ % 2 == 0 ? (prefix + ".") : "") + value); + } + } + + return result; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#getConfig(org.springframework.data.redis.connection.RedisClusterNode, java.lang.String) + */ + @Override + public List getConfig(RedisClusterNode node, final String pattern) { + return executeCommandOnSingleNode(client -> client.configGet(pattern), node).getValue(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceServerCommands#setConfig(java.lang.String, java.lang.String) + */ + @Override + public void setConfig(final String param, final String value) { + executeCommandOnAllNodes(client -> client.configSet(param, value)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#setConfig(org.springframework.data.redis.connection.RedisClusterNode, java.lang.String, java.lang.String) + */ + @Override + public void setConfig(RedisClusterNode node, final String param, final String value) { + executeCommandOnSingleNode(client -> client.configSet(param, value), node); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceServerCommands#resetConfigStats() + */ + @Override + public void resetConfigStats() { + executeCommandOnAllNodes(RedisServerCommands::configResetstat); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#resetConfigStats(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public void resetConfigStats(RedisClusterNode node) { + executeCommandOnSingleNode(RedisServerCommands::configResetstat, node); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceServerCommands#time() + */ + @Override + public Long time() { + + return convertListOfStringToTime(connection.getClusterCommandExecutor() + .executeCommandOnArbitraryNode((LettuceClusterCommandCallback>) RedisServerCommands::time) + .getValue()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#time(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public Long time(RedisClusterNode node) { + return convertListOfStringToTime(executeCommandOnSingleNode(RedisServerCommands::time, node).getValue()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceServerCommands#getClientList() + */ + @Override + public List getClientList() { + + List map = executeCommandOnAllNodes(RedisServerCommands::clientList).resultsAsList(); + + ArrayList result = new ArrayList<>(); + for (String infos : map) { + result.addAll(LettuceConverters.toListOfRedisClientInformation(infos)); + } + return result; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisClusterServerCommands#getClientList(org.springframework.data.redis.connection.RedisClusterNode) + */ + @Override + public List getClientList(RedisClusterNode node) { + + return LettuceConverters + .toListOfRedisClientInformation(executeCommandOnSingleNode(RedisServerCommands::clientList, node).getValue()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceServerCommands#slaveOf(java.lang.String, int) + */ + @Override + public void slaveOf(String host, int port) { + throw new InvalidDataAccessApiUsageException( + "SlaveOf is not supported in cluster environment. Please use CLUSTER REPLICATE."); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceServerCommands#slaveOfNoOne() + */ + @Override + public void slaveOfNoOne() { + throw new InvalidDataAccessApiUsageException( + "SlaveOf is not supported in cluster environment. Please use CLUSTER REPLICATE."); + } + + private NodeResult executeCommandOnSingleNode(LettuceClusterCommandCallback command, + RedisClusterNode node) { + return connection.getClusterCommandExecutor().executeCommandOnSingleNode(command, node); + } + + private MulitNodeResult executeCommandOnAllNodes(final LettuceClusterCommandCallback cmd) { + return connection.getClusterCommandExecutor().executeCommandOnAllNodes(cmd); + } + + private static Long convertListOfStringToTime(List serverTimeInformation) { + + Assert.notEmpty(serverTimeInformation, "Received invalid result from server. Expected 2 items in collection."); + Assert.isTrue(serverTimeInformation.size() == 2, + "Received invalid number of arguments from redis server. Expected 2 received " + serverTimeInformation.size()); + + return Converters.toTimeMillis(LettuceConverters.toString(serverTimeInformation.get(0)), + LettuceConverters.toString(serverTimeInformation.get(1))); + } +} diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterSetCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterSetCommands.java index 272c997be..df5810f1d 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterSetCommands.java @@ -15,6 +15,8 @@ */ package org.springframework.data.redis.connection.lettuce; +import io.lettuce.core.api.sync.RedisSetCommands; + import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -70,8 +72,7 @@ class LettuceClusterSetCommands extends LettuceSetCommands { } Collection> nodeResult = connection.getClusterCommandExecutor() - .executeMuliKeyCommand( - (LettuceMultiKeyClusterCommandCallback>) (client, key) -> client.smembers(key), + .executeMuliKeyCommand((LettuceMultiKeyClusterCommandCallback>) RedisSetCommands::smembers, Arrays.asList(keys)) .resultsAsList(); @@ -89,7 +90,7 @@ class LettuceClusterSetCommands extends LettuceSetCommands { } } - if (result.isEmpty()) { + if (result == null || result.isEmpty()) { return Collections.emptySet(); } @@ -128,8 +129,7 @@ class LettuceClusterSetCommands extends LettuceSetCommands { } Collection> nodeResult = connection.getClusterCommandExecutor() - .executeMuliKeyCommand( - (LettuceMultiKeyClusterCommandCallback>) (client, key) -> client.smembers(key), + .executeMuliKeyCommand((LettuceMultiKeyClusterCommandCallback>) RedisSetCommands::smembers, Arrays.asList(keys)) .resultsAsList(); @@ -181,8 +181,7 @@ class LettuceClusterSetCommands extends LettuceSetCommands { ByteArraySet values = new ByteArraySet(sMembers(source)); Collection> nodeResult = connection.getClusterCommandExecutor() - .executeMuliKeyCommand( - (LettuceMultiKeyClusterCommandCallback>) (client, key) -> client.smembers(key), + .executeMuliKeyCommand((LettuceMultiKeyClusterCommandCallback>) RedisSetCommands::smembers, Arrays.asList(others)) .resultsAsList(); diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java index 715b982e4..057edff4d 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java @@ -34,20 +34,7 @@ import io.lettuce.core.cluster.api.async.RedisClusterAsyncCommands; import io.lettuce.core.cluster.api.sync.RedisClusterCommands; import io.lettuce.core.codec.ByteArrayCodec; import io.lettuce.core.codec.RedisCodec; -import io.lettuce.core.output.BooleanOutput; -import io.lettuce.core.output.ByteArrayOutput; -import io.lettuce.core.output.CommandOutput; -import io.lettuce.core.output.DateOutput; -import io.lettuce.core.output.DoubleOutput; -import io.lettuce.core.output.IntegerOutput; -import io.lettuce.core.output.KeyListOutput; -import io.lettuce.core.output.KeyValueOutput; -import io.lettuce.core.output.MapOutput; -import io.lettuce.core.output.MultiOutput; -import io.lettuce.core.output.StatusOutput; -import io.lettuce.core.output.ValueListOutput; -import io.lettuce.core.output.ValueOutput; -import io.lettuce.core.output.ValueSetOutput; +import io.lettuce.core.output.*; import io.lettuce.core.protocol.Command; import io.lettuce.core.protocol.CommandArgs; import io.lettuce.core.protocol.CommandType; @@ -56,13 +43,11 @@ import io.lettuce.core.sentinel.api.StatefulRedisSentinelConnection; import java.lang.reflect.Constructor; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.Queue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Future; @@ -76,27 +61,10 @@ import org.springframework.dao.QueryTimeoutException; import org.springframework.data.redis.ExceptionTranslationStrategy; import org.springframework.data.redis.FallbackExceptionTranslationStrategy; import org.springframework.data.redis.RedisConnectionFailureException; -import org.springframework.data.redis.connection.AbstractRedisConnection; -import org.springframework.data.redis.connection.FutureResult; -import org.springframework.data.redis.connection.MessageListener; -import org.springframework.data.redis.connection.RedisGeoCommands; -import org.springframework.data.redis.connection.RedisHashCommands; -import org.springframework.data.redis.connection.RedisHyperLogLogCommands; -import org.springframework.data.redis.connection.RedisKeyCommands; -import org.springframework.data.redis.connection.RedisListCommands; -import org.springframework.data.redis.connection.RedisNode; -import org.springframework.data.redis.connection.RedisPipelineException; -import org.springframework.data.redis.connection.RedisSentinelConnection; -import org.springframework.data.redis.connection.RedisSetCommands; -import org.springframework.data.redis.connection.RedisStringCommands; -import org.springframework.data.redis.connection.RedisSubscribedConnectionException; -import org.springframework.data.redis.connection.RedisZSetCommands; -import org.springframework.data.redis.connection.ReturnType; -import org.springframework.data.redis.connection.Subscription; +import org.springframework.data.redis.connection.*; import org.springframework.data.redis.connection.convert.TransactionResultConverter; import org.springframework.data.redis.core.RedisCommand; import org.springframework.data.redis.core.ScanOptions; -import org.springframework.data.redis.core.types.RedisClientInfo; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; @@ -104,7 +72,7 @@ import org.springframework.util.ObjectUtils; /** * {@code RedisConnection} implementation on top of Lettuce Redis * client. - * + * * @author Costin Leau * @author Jennifer Hickey * @author Christoph Strobl @@ -134,7 +102,7 @@ public class LettuceConnection extends AbstractRedisConnection { private boolean isMulti = false; private boolean isPipelined = false; private List ppline; - private Queue> txResults = new LinkedList>(); + private Queue> txResults = new LinkedList<>(); private AbstractRedisClient client; private volatile LettuceSubscription subscription; private LettucePool pool; @@ -240,30 +208,9 @@ public class LettuceConnection extends AbstractRedisConnection { } } - private class LettuceEvalResultsConverter implements Converter { - private ReturnType returnType; - - public LettuceEvalResultsConverter(ReturnType returnType) { - this.returnType = returnType; - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - public T convert(Object source) { - if (returnType == ReturnType.MULTI) { - List resultList = (List) source; - for (Object obj : resultList) { - if (obj instanceof Exception) { - throw convertLettuceAccessException((Exception) obj); - } - } - } - return (T) source; - } - } - /** * Instantiates a new lettuce connection. - * + * * @param timeout The connection timeout (in milliseconds) * @param client The {@link RedisClient} to use when instantiating a native connection */ @@ -273,7 +220,7 @@ public class LettuceConnection extends AbstractRedisConnection { /** * Instantiates a new lettuce connection. - * + * * @param timeout The connection timeout (in milliseconds) * @param client The {@link RedisClient} to use when * instantiating a pub/sub connection * @param pool The connection pool to use for all other native connections @@ -284,7 +231,7 @@ public class LettuceConnection extends AbstractRedisConnection { /** * Instantiates a new lettuce connection. - * + * * @param sharedConnection A native connection that is shared with other {@link LettuceConnection}s. Will not be used * for transactions or blocking operations * @param timeout The connection timeout (in milliseconds) @@ -296,7 +243,7 @@ public class LettuceConnection extends AbstractRedisConnection { /** * Instantiates a new lettuce connection. - * + * * @param sharedConnection A native connection that is shared with other {@link LettuceConnection}s. Should not be * used for transactions or blocking operations * @param timeout The connection timeout (in milliseconds) @@ -339,41 +286,91 @@ public class LettuceConnection extends AbstractRedisConnection { return exception; } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#geoCommands() + */ @Override public RedisGeoCommands geoCommands() { return new LettuceGeoCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#hashCommands() + */ @Override public RedisHashCommands hashCommands() { return new LettuceHashCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#hyperLogLogCommands() + */ @Override public RedisHyperLogLogCommands hyperLogLogCommands() { return new LettuceHyperLogLogCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#keyCommands() + */ @Override public RedisKeyCommands keyCommands() { return new LettuceKeyCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#listCommands() + */ @Override public RedisListCommands listCommands() { return new LettuceListCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#setCommands() + */ @Override public RedisSetCommands setCommands() { return new LettuceSetCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#scriptingCommands() + */ + @Override + public RedisScriptingCommands scriptingCommands() { + return new LettuceScriptingCommands(this); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#stringCommands() + */ @Override public RedisStringCommands stringCommands() { return new LettuceStringCommands(this); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#serverCommands() + */ + @Override + public RedisServerCommands serverCommands() { + return new LettuceServerCommands(this); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisConnection#zSetCommands() + */ @Override public RedisZSetCommands zSetCommands() { return new LettuceZSetCommands(this); @@ -412,7 +409,7 @@ public class LettuceConnection extends AbstractRedisConnection { validateCommandIfRunningInTransactionMode(commandType, args); - CommandArgs cmdArg = new CommandArgs(CODEC); + CommandArgs cmdArg = new CommandArgs<>(CODEC); if (!ObjectUtils.isEmpty(args)) { cmdArg.addKeys(args); } @@ -497,7 +494,7 @@ public class LettuceConnection extends AbstractRedisConnection { public void openPipeline() { if (!isPipelined) { isPipelined = true; - ppline = new ArrayList(); + ppline = new ArrayList<>(); } } @@ -505,7 +502,7 @@ public class LettuceConnection extends AbstractRedisConnection { if (isPipelined) { isPipelined = false; - List> futures = new ArrayList>(); + List> futures = new ArrayList<>(); for (LettuceResult result : ppline) { futures.add(result.getResultHolder()); } @@ -514,7 +511,7 @@ public class LettuceConnection extends AbstractRedisConnection { boolean done = LettuceFutures.awaitAll(timeout, TimeUnit.MILLISECONDS, futures.toArray(new RedisFuture[futures.size()])); - List results = new ArrayList(futures.size()); + List results = new ArrayList<>(futures.size()); Exception problem = null; @@ -560,241 +557,11 @@ public class LettuceConnection extends AbstractRedisConnection { return Collections.emptyList(); } - public Long dbSize() { - try { - if (isPipelined()) { - pipeline(new LettuceResult(getAsyncConnection().dbsize())); - return null; - } - if (isQueueing()) { - transaction(new LettuceTxResult(getConnection().dbsize())); - return null; - } - return getConnection().dbsize(); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - public void flushDb() { - try { - if (isPipelined()) { - pipeline(new LettuceStatusResult(getAsyncConnection().flushdb())); - return; - } - if (isQueueing()) { - transaction(new LettuceTxStatusResult(getConnection().flushdb())); - return; - } - getConnection().flushdb(); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - public void flushAll() { - try { - if (isPipelined()) { - pipeline(new LettuceStatusResult(getAsyncConnection().flushall())); - return; - } - if (isQueueing()) { - transaction(new LettuceTxStatusResult(getConnection().flushall())); - return; - } - getConnection().flushall(); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - public void bgSave() { - try { - if (isPipelined()) { - pipeline(new LettuceStatusResult(getAsyncConnection().bgsave())); - return; - } - if (isQueueing()) { - transaction(new LettuceTxStatusResult(getConnection().bgsave())); - return; - } - getConnection().bgsave(); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - public void bgReWriteAof() { - try { - if (isPipelined()) { - pipeline(new LettuceStatusResult(getAsyncConnection().bgrewriteaof())); - return; - } - if (isQueueing()) { - transaction(new LettuceTxStatusResult(getConnection().bgrewriteaof())); - return; - } - getConnection().bgrewriteaof(); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - /** - * @deprecated As of 1.3, use {@link #bgReWriteAof}. - */ - @Deprecated - public void bgWriteAof() { - bgReWriteAof(); - } - - public void save() { - try { - if (isPipelined()) { - pipeline(new LettuceStatusResult(getAsyncConnection().save())); - return; - } - if (isQueueing()) { - transaction(new LettuceTxStatusResult(getConnection().save())); - return; - } - getConnection().save(); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - public List getConfig(String param) { - try { - if (isPipelined()) { - pipeline(new LettuceResult(getAsyncConnection().configGet(param))); - return null; - } - if (isQueueing()) { - transaction(new LettuceTxResult(getConnection().configGet(param))); - return null; - } - return getConnection().configGet(param); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - public Properties info() { - try { - if (isPipelined()) { - pipeline(new LettuceResult(getAsyncConnection().info(), LettuceConverters.stringToProps())); - return null; - } - if (isQueueing()) { - transaction(new LettuceTxResult(getConnection().info(), LettuceConverters.stringToProps())); - return null; - } - return LettuceConverters.toProperties(getConnection().info()); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - public Properties info(String section) { - try { - if (isPipelined()) { - pipeline(new LettuceResult(getAsyncConnection().info(section), LettuceConverters.stringToProps())); - return null; - } - if (isQueueing()) { - transaction(new LettuceTxResult(getConnection().info(section), LettuceConverters.stringToProps())); - return null; - } - return LettuceConverters.toProperties(getConnection().info(section)); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - public Long lastSave() { - try { - if (isPipelined()) { - pipeline(new LettuceResult(getAsyncConnection().lastsave(), LettuceConverters.dateToLong())); - return null; - } - if (isQueueing()) { - transaction(new LettuceTxResult(getConnection().lastsave(), LettuceConverters.dateToLong())); - return null; - } - return LettuceConverters.toLong(getConnection().lastsave()); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - public void setConfig(String param, String value) { - try { - if (isPipelined()) { - pipeline(new LettuceStatusResult(getAsyncConnection().configSet(param, value))); - return; - } - if (isQueueing()) { - transaction(new LettuceTxStatusResult(getConnection().configSet(param, value))); - return; - } - getConnection().configSet(param, value); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - public void resetConfigStats() { - try { - if (isPipelined()) { - pipeline(new LettuceStatusResult(getAsyncConnection().configResetstat())); - return; - } - if (isQueueing()) { - transaction(new LettuceTxStatusResult(getConnection().configResetstat())); - return; - } - getConnection().configResetstat(); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - public void shutdown() { - try { - if (isPipelined()) { - getAsyncConnection().shutdown(true); - return; - } - getConnection().shutdown(true); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - /* * (non-Javadoc) * @see org.springframework.data.redis.connection.RedisServerCommands#shutdown(org.springframework.data.redis.connection.RedisServerCommands.ShutdownOption) */ @Override - public void shutdown(ShutdownOption option) { - - if (option == null) { - shutdown(); - return; - } - - boolean save = ShutdownOption.SAVE.equals(option); - try { - if (isPipelined()) { - getAsyncConnection().shutdown(save); - return; - } - getConnection().shutdown(save); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } public byte[] echo(byte[] message) { try { @@ -943,129 +710,6 @@ public class LettuceConnection extends AbstractRedisConnection { } } - // - // Scripting commands - // - - public void scriptFlush() { - try { - if (isPipelined()) { - pipeline(new LettuceStatusResult(getAsyncConnection().scriptFlush())); - return; - } - if (isQueueing()) { - transaction(new LettuceTxStatusResult(getConnection().scriptFlush())); - return; - } - getConnection().scriptFlush(); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - public void scriptKill() { - if (isQueueing()) { - throw new UnsupportedOperationException("Script kill not permitted in a transaction"); - } - try { - if (isPipelined()) { - pipeline(new LettuceStatusResult(getAsyncConnection().scriptKill())); - return; - } - if (isQueueing()) { - transaction(new LettuceTxStatusResult(getConnection().scriptKill())); - return; - } - getConnection().scriptKill(); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - public String scriptLoad(byte[] script) { - try { - if (isPipelined()) { - pipeline(new LettuceResult(getAsyncConnection().scriptLoad(script))); - return null; - } - if (isQueueing()) { - transaction(new LettuceTxResult(getConnection().scriptLoad(script))); - return null; - } - return getConnection().scriptLoad(script); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - public List scriptExists(String... scriptSha1) { - try { - if (isPipelined()) { - pipeline(new LettuceResult(getAsyncConnection().scriptExists(scriptSha1))); - return null; - } - if (isQueueing()) { - transaction(new LettuceTxResult(getConnection().scriptExists(scriptSha1))); - return null; - } - return getConnection().scriptExists(scriptSha1); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - public T eval(byte[] script, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { - try { - byte[][] keys = extractScriptKeys(numKeys, keysAndArgs); - byte[][] args = extractScriptArgs(numKeys, keysAndArgs); - String convertedScript = LettuceConverters.toString(script); - if (isPipelined()) { - pipeline(new LettuceResult( - getAsyncConnection().eval(convertedScript, LettuceConverters.toScriptOutputType(returnType), keys, args), - new LettuceEvalResultsConverter(returnType))); - return null; - } - if (isQueueing()) { - transaction(new LettuceTxResult( - getConnection().eval(convertedScript, LettuceConverters.toScriptOutputType(returnType), keys, args), - new LettuceEvalResultsConverter(returnType))); - return null; - } - return new LettuceEvalResultsConverter(returnType) - .convert(getConnection().eval(convertedScript, LettuceConverters.toScriptOutputType(returnType), keys, args)); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - public T evalSha(String scriptSha1, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { - try { - byte[][] keys = extractScriptKeys(numKeys, keysAndArgs); - byte[][] args = extractScriptArgs(numKeys, keysAndArgs); - - if (isPipelined()) { - pipeline(new LettuceResult( - getAsyncConnection().evalsha(scriptSha1, LettuceConverters.toScriptOutputType(returnType), keys, args), - new LettuceEvalResultsConverter(returnType))); - return null; - } - if (isQueueing()) { - transaction(new LettuceTxResult( - getConnection().evalsha(scriptSha1, LettuceConverters.toScriptOutputType(returnType), keys, args), - new LettuceEvalResultsConverter(returnType))); - return null; - } - return new LettuceEvalResultsConverter(returnType) - .convert(getConnection().evalsha(scriptSha1, LettuceConverters.toScriptOutputType(returnType), keys, args)); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - public T evalSha(byte[] scriptSha1, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { - return evalSha(LettuceConverters.toString(scriptSha1), returnType, numKeys, keysAndArgs); - } - // // Pub/Sub functionality // @@ -1126,145 +770,6 @@ public class LettuceConnection extends AbstractRedisConnection { } } - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#time() - */ - @Override - public Long time() { - - try { - - if (isPipelined()) { - pipeline(new LettuceResult(getAsyncConnection().time(), LettuceConverters.toTimeConverter())); - return null; - } - if (isQueueing()) { - transaction(new LettuceTxResult(getConnection().time(), LettuceConverters.toTimeConverter())); - return null; - } - - return LettuceConverters.toTimeConverter().convert(getConnection().time()); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - @Override - public void killClient(String host, int port) { - - Assert.hasText(host, "Host for 'CLIENT KILL' must not be 'null' or 'empty'."); - - String client = String.format("%s:%s", host, port); - try { - if (isPipelined()) { - pipeline(new LettuceStatusResult(getAsyncConnection().clientKill(client))); - return; - } - getConnection().clientKill(client); - } catch (Exception e) { - throw convertLettuceAccessException(e); - } - } - - @Override - public void setClientName(byte[] name) { - - if (isQueueing()) { - pipeline(new LettuceStatusResult(getAsyncConnection().clientSetname(name))); - return; - } - if (isQueueing()) { - transaction(new LettuceTxResult(getConnection().clientSetname(name))); - return; - } - - getAsyncConnection().clientSetname(name); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#slaveOf(java.lang.String, int) - */ - @Override - public void slaveOf(String host, int port) { - - Assert.hasText(host, "Host must not be null for 'SLAVEOF' command."); - try { - if (isPipelined()) { - pipeline(new LettuceStatusResult(getAsyncConnection().slaveof(host, port))); - return; - } - if (isQueueing()) { - transaction(new LettuceTxResult(getConnection().slaveof(host, port))); - return; - } - getConnection().slaveof(host, port); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#getClientName() - */ - @Override - public String getClientName() { - - try { - - if (isPipelined()) { - pipeline(new LettuceResult(getAsyncConnection().clientGetname(), LettuceConverters.bytesToString())); - return null; - } - if (isQueueing()) { - transaction(new LettuceTxResult(getConnection().clientGetname(), LettuceConverters.bytesToString())); - return null; - } - - return LettuceConverters.toString(getConnection().clientGetname()); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - - @Override - public List getClientList() { - - if (isPipelined()) { - throw new UnsupportedOperationException("Cannot be called in pipeline mode."); - } - if (isQueueing()) { - transaction( - new LettuceTxResult(getAsyncConnection().clientList(), LettuceConverters.stringToRedisClientListConverter())); - return null; - } - - return LettuceConverters.toListOfRedisClientInformation(getConnection().clientList()); - } - - /* - * @see org.springframework.data.redis.connection.RedisServerCommands#slaveOfNoOne() - */ - @Override - public void slaveOfNoOne() { - - try { - if (isPipelined()) { - pipeline(new LettuceStatusResult(getAsyncConnection().slaveofNoOne())); - return; - } - if (isQueueing()) { - transaction(new LettuceTxResult(getConnection().slaveofNoOne())); - return; - } - getConnection().slaveofNoOne(); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - @SuppressWarnings("unchecked") T failsafeReadScanValues(List source, @SuppressWarnings("rawtypes") Converter converter) { @@ -1279,7 +784,7 @@ public class LettuceConnection extends AbstractRedisConnection { /** * Specifies if pipelined and transaction results should be converted to the expected data type. If false, results of * {@link #closePipeline()} and {@link #exec()} will be of the type returned by the Lettuce driver - * + * * @param convertPipelineAndTxResults Whether or not to convert pipeline and tx results */ public void setConvertPipelineAndTxResults(boolean convertPipelineAndTxResults) { @@ -1401,20 +906,6 @@ public class LettuceConnection extends AbstractRedisConnection { String.format("%s is not a supported connection type.", asyncDedicatedConn.getClass().getName())); } - private byte[][] extractScriptKeys(int numKeys, byte[]... keysAndArgs) { - if (numKeys > 0) { - return Arrays.copyOfRange(keysAndArgs, 0, numKeys); - } - return new byte[0][0]; - } - - private byte[][] extractScriptArgs(int numKeys, byte[]... keysAndArgs) { - if (keysAndArgs.length > numKeys) { - return Arrays.copyOfRange(keysAndArgs, numKeys, keysAndArgs.length); - } - return new byte[0][0]; - } - io.lettuce.core.ScanCursor getScanCursor(long cursorId) { return io.lettuce.core.ScanCursor.of(Long.toString(cursorId)); } @@ -1493,16 +984,16 @@ public class LettuceConnection extends AbstractRedisConnection { /** * {@link TypeHints} provide {@link CommandOutput} information for a given {@link CommandType}. - * + * * @since 1.2.1 */ static class TypeHints { @SuppressWarnings("rawtypes") // - private static final Map> COMMAND_OUTPUT_TYPE_MAPPING = new HashMap>(); + private static final Map> COMMAND_OUTPUT_TYPE_MAPPING = new HashMap<>(); @SuppressWarnings("rawtypes") // - private static final Map, Constructor> CONSTRUCTORS = new ConcurrentHashMap, Constructor>(); + private static final Map, Constructor> CONSTRUCTORS = new ConcurrentHashMap<>(); { // INTEGER @@ -1654,18 +1145,18 @@ public class LettuceConnection extends AbstractRedisConnection { /** * Returns the {@link CommandOutput} mapped for given {@link CommandType} or {@link ByteArrayOutput} as default. - * + * * @param type * @return {@link ByteArrayOutput} as default when no matching {@link CommandOutput} available. */ @SuppressWarnings("rawtypes") public CommandOutput getTypeHint(CommandType type) { - return getTypeHint(type, new ByteArrayOutput(CODEC)); + return getTypeHint(type, new ByteArrayOutput<>(CODEC)); } /** * Returns the {@link CommandOutput} mapped for given {@link CommandType} given {@link CommandOutput} as default. - * + * * @param type * @return */ @@ -1691,38 +1182,4 @@ public class LettuceConnection extends AbstractRedisConnection { return BeanUtils.instantiateClass(constructor, CODEC); } } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption) - */ - @Override - public void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option) { - migrate(key, target, dbIndex, option, Long.MAX_VALUE); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption, long) - */ - @Override - public void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option, long timeout) { - - try { - if (isPipelined()) { - pipeline( - new LettuceResult(getAsyncConnection().migrate(target.getHost(), target.getPort(), key, dbIndex, timeout))); - return; - } - if (isQueueing()) { - transaction( - new LettuceTxResult(getConnection().migrate(target.getHost(), target.getPort(), key, dbIndex, timeout))); - return; - } - getConnection().migrate(target.getHost(), target.getPort(), key, dbIndex, timeout); - } catch (Exception ex) { - throw convertLettuceAccessException(ex); - } - } - } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactory.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactory.java index 6097d60ff..516df39f6 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactory.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactory.java @@ -594,7 +594,7 @@ public class LettuceConnectionFactory if (isClusterAware()) { - List initialUris = new ArrayList(); + List initialUris = new ArrayList<>(); for (RedisNode node : this.clusterConfiguration.getClusterNodes()) { initialUris.add(createRedisURIAndApplySettings(node.getHost(), node.getPort())); } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConverters.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConverters.java index e0fb86bba..314ca5e51 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConverters.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConverters.java @@ -15,34 +15,13 @@ */ package org.springframework.data.redis.connection.lettuce; -import io.lettuce.core.GeoArgs; -import io.lettuce.core.GeoCoordinates; -import io.lettuce.core.GeoWithin; -import io.lettuce.core.KeyValue; -import io.lettuce.core.Limit; -import io.lettuce.core.Range; -import io.lettuce.core.RedisURI; -import io.lettuce.core.ScoredValue; -import io.lettuce.core.ScriptOutputType; -import io.lettuce.core.SetArgs; -import io.lettuce.core.SortArgs; -import io.lettuce.core.TransactionResult; +import io.lettuce.core.*; import io.lettuce.core.cluster.models.partitions.Partitions; import io.lettuce.core.cluster.models.partitions.RedisClusterNode.NodeFlag; import io.lettuce.core.protocol.LettuceCharsets; import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -88,7 +67,7 @@ import org.springframework.util.StringUtils; /** * Lettuce type converters - * + * * @author Jennifer Hickey * @author Christoph Strobl * @author Thomas Darimont @@ -134,7 +113,7 @@ abstract public class LettuceConverters extends Converters { }; BYTES_LIST_TO_BYTES_SET = new Converter, Set>() { public Set convert(List results) { - return results != null ? new LinkedHashSet(results) : null; + return results != null ? new LinkedHashSet<>(results) : null; } }; BYTES_TO_STRING = new Converter() { @@ -159,7 +138,7 @@ abstract public class LettuceConverters extends Converters { }; BYTES_SET_TO_BYTES_LIST = new Converter, List>() { public List convert(Set results) { - return results != null ? new ArrayList(results) : null; + return results != null ? new ArrayList<>(results) : null; } }; BYTES_COLLECTION_TO_BYTES_LIST = new Converter, List>() { @@ -167,7 +146,7 @@ abstract public class LettuceConverters extends Converters { if (results instanceof List) { return (List) results; } - return results != null ? new ArrayList(results) : null; + return results != null ? new ArrayList<>(results) : null; } }; KEY_VALUE_TO_BYTES_LIST = new Converter, List>() { @@ -175,7 +154,7 @@ abstract public class LettuceConverters extends Converters { if (source == null) { return null; } - List list = new ArrayList(2); + List list = new ArrayList<>(2); list.add(source.getKey()); list.add(source.getValue()); return list; @@ -190,7 +169,7 @@ abstract public class LettuceConverters extends Converters { return Collections.emptyMap(); } - Map target = new LinkedHashMap(); + Map target = new LinkedHashMap<>(); Iterator kv = source.iterator(); while (kv.hasNext()) { @@ -205,7 +184,7 @@ abstract public class LettuceConverters extends Converters { if (source == null) { return null; } - Set tuples = new LinkedHashSet(source.size()); + Set tuples = new LinkedHashSet<>(source.size()); for (ScoredValue value : source) { tuples.add(LettuceConverters.toTuple(value)); } @@ -218,7 +197,7 @@ abstract public class LettuceConverters extends Converters { if (source == null) { return null; } - List tuples = new ArrayList(source.size()); + List tuples = new ArrayList<>(source.size()); for (ScoredValue value : source) { tuples.add(LettuceConverters.toTuple(value)); } @@ -239,7 +218,7 @@ abstract public class LettuceConverters extends Converters { return Collections.emptyList(); } - List tuples = new ArrayList(); + List tuples = new ArrayList<>(); Iterator it = source.iterator(); while (it.hasNext()) { tuples.add( @@ -257,7 +236,7 @@ abstract public class LettuceConverters extends Converters { if (source == null) { return Collections.emptyList(); } - List nodes = new ArrayList(); + List nodes = new ArrayList<>(); for (io.lettuce.core.cluster.models.partitions.RedisClusterNode node : source.getPartitions()) { nodes.add(CLUSTER_NODE_TO_CLUSTER_NODE_CONVERTER.convert(node)); } @@ -283,7 +262,7 @@ abstract public class LettuceConverters extends Converters { private Set parseFlags(Set source) { - Set flags = new LinkedHashSet(source != null ? source.size() : 8, 1); + Set flags = new LinkedHashSet<>(source != null ? source.size() : 8, 1); for (NodeFlag flag : source) { switch (flag) { case NOFLAGS: @@ -342,8 +321,7 @@ abstract public class LettuceConverters extends Converters { : null; } }; - GEO_COORDINATE_LIST_TO_POINT_LIST_CONVERTER = new ListConverter( - GEO_COORDINATE_TO_POINT_CONVERTER); + GEO_COORDINATE_LIST_TO_POINT_LIST_CONVERTER = new ListConverter<>(GEO_COORDINATE_TO_POINT_CONVERTER); KEY_VALUE_UNWRAPPER = new Converter, Object>() { @@ -658,7 +636,7 @@ abstract public class LettuceConverters extends Converters { return Collections.emptyList(); } - List sentinels = new ArrayList(); + List sentinels = new ArrayList<>(); for (Map info : source) { sentinels.add(RedisServer.newServerFrom(Converters.toProperties(info))); } @@ -783,7 +761,7 @@ abstract public class LettuceConverters extends Converters { /** * Converts a given {@link Expiration} and {@link SetOption} to the according {@link SetArgs}.
    - * + * * @param expiration can be {@literal null}. * @param option can be {@literal null}. * @since 1.7 @@ -825,7 +803,7 @@ abstract public class LettuceConverters extends Converters { /** * Convert {@link Metric} into {@link GeoArgs.Unit}. - * + * * @param metric * @return * @since 1.8 @@ -839,7 +817,7 @@ abstract public class LettuceConverters extends Converters { /** * Convert {@link GeoRadiusCommandArgs} into {@link GeoArgs}. - * + * * @param args * @return * @since 1.8 @@ -880,7 +858,7 @@ abstract public class LettuceConverters extends Converters { /** * Get {@link Converter} capable of {@link Set} of {@link Byte} into {@link GeoResults}. - * + * * @return * @since 1.8 */ @@ -891,22 +869,22 @@ abstract public class LettuceConverters extends Converters { public GeoResults> convert(Set source) { if (CollectionUtils.isEmpty(source)) { - return new GeoResults>(Collections.>> emptyList()); + return new GeoResults<>(Collections.>> emptyList()); } - List>> results = new ArrayList>>(source.size()); + List>> results = new ArrayList<>(source.size()); Iterator it = source.iterator(); while (it.hasNext()) { - results.add(new GeoResult>(new GeoLocation(it.next(), null), new Distance(0D))); + results.add(new GeoResult<>(new GeoLocation<>(it.next(), null), new Distance(0D))); } - return new GeoResults>(results); + return new GeoResults<>(results); } }; } /** * Get {@link Converter} capable of convering {@link GeoWithin} into {@link GeoResults}. - * + * * @param metric * @return * @since 1.8 @@ -962,7 +940,7 @@ abstract public class LettuceConverters extends Converters { @Override public GeoResults> convert(List> source) { - List>> results = new ArrayList>>(source.size()); + List>> results = new ArrayList<>(source.size()); Converter, GeoResult>> converter = GeoResultConverterFactory.INSTANCE .forMetric(metric); @@ -970,7 +948,7 @@ abstract public class LettuceConverters extends Converters { results.add(converter.convert(result)); } - return new GeoResults>(results, metric); + return new GeoResults<>(results, metric); } } } @@ -1000,7 +978,7 @@ abstract public class LettuceConverters extends Converters { Point point = GEO_COORDINATE_TO_POINT_CONVERTER.convert(source.getCoordinates()); - return new GeoResult>(new GeoLocation(source.getMember(), point), + return new GeoResult<>(new GeoLocation<>(source.getMember(), point), new Distance(source.getDistance() != null ? source.getDistance() : 0D, metric)); } } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceGeoCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceGeoCommands.java index 8d0b4db02..da0c66396 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceGeoCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceGeoCommands.java @@ -117,7 +117,7 @@ class LettuceGeoCommands implements RedisGeoCommands { Assert.notNull(key, "Key must not be null!"); Assert.notNull(memberCoordinateMap, "MemberCoordinateMap must not be null!"); - List values = new ArrayList(); + List values = new ArrayList<>(); for (Entry entry : memberCoordinateMap.entrySet()) { values.add(entry.getValue().getX()); @@ -138,7 +138,7 @@ class LettuceGeoCommands implements RedisGeoCommands { Assert.notNull(key, "Key must not be null!"); Assert.notNull(locations, "Locations must not be null!"); - List values = new ArrayList(); + List values = new ArrayList<>(); for (GeoLocation location : locations) { values.add(location.getPoint().getX()); @@ -438,7 +438,7 @@ class LettuceGeoCommands implements RedisGeoCommands { connection.transaction(result); } - RedisClusterAsyncCommands getAsyncConnection() { + private RedisClusterAsyncCommands getAsyncConnection() { return connection.getAsyncConnection(); } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceHashCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceHashCommands.java index 7bb93bf2a..81502409d 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceHashCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceHashCommands.java @@ -380,7 +380,7 @@ class LettuceHashCommands implements RedisHashCommands { connection.transaction(result); } - RedisClusterAsyncCommands getAsyncConnection() { + private RedisClusterAsyncCommands getAsyncConnection() { return connection.getAsyncConnection(); } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceHyperLogLogCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceHyperLogLogCommands.java index 05a3df8a7..1b0a55539 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceHyperLogLogCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceHyperLogLogCommands.java @@ -143,7 +143,7 @@ class LettuceHyperLogLogCommands implements RedisHyperLogLogCommands { connection.transaction(result); } - RedisClusterAsyncCommands getAsyncConnection() { + private RedisClusterAsyncCommands getAsyncConnection() { return connection.getAsyncConnection(); } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceKeyCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceKeyCommands.java index 4dfcb0450..85e047441 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceKeyCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceKeyCommands.java @@ -589,7 +589,7 @@ class LettuceKeyCommands implements RedisKeyCommands { connection.transaction(result); } - RedisClusterAsyncCommands getAsyncConnection() { + private RedisClusterAsyncCommands getAsyncConnection() { return connection.getAsyncConnection(); } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceListCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceListCommands.java index be2e28eca..95bbbf659 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceListCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceListCommands.java @@ -418,7 +418,7 @@ class LettuceListCommands implements RedisListCommands { connection.transaction(result); } - RedisClusterAsyncCommands getAsyncConnection() { + private RedisClusterAsyncCommands getAsyncConnection() { return connection.getAsyncConnection(); } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterGeoCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterGeoCommands.java index 4a8fd6148..aca8e243c 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterGeoCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterGeoCommands.java @@ -21,8 +21,7 @@ import org.springframework.data.redis.connection.ReactiveClusterGeoCommands; * @author Christoph Strobl * @since 2.0 */ -public class LettuceReactiveClusterGeoCommands extends LettuceReactiveGeoCommands - implements ReactiveClusterGeoCommands { +class LettuceReactiveClusterGeoCommands extends LettuceReactiveGeoCommands implements ReactiveClusterGeoCommands { /** * Create new {@link LettuceReactiveGeoCommands}. diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterHashCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterHashCommands.java index a33f1fafd..0615eea9d 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterHashCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterHashCommands.java @@ -21,8 +21,7 @@ import org.springframework.data.redis.connection.ReactiveClusterHashCommands; * @author Christoph Strobl * @since 2.0 */ -public class LettuceReactiveClusterHashCommands extends LettuceReactiveHashCommands - implements ReactiveClusterHashCommands { +class LettuceReactiveClusterHashCommands extends LettuceReactiveHashCommands implements ReactiveClusterHashCommands { /** * Create new {@link LettuceReactiveHashCommands}. diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterHyperLogLogCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterHyperLogLogCommands.java index 34f204073..be2ac6cbb 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterHyperLogLogCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterHyperLogLogCommands.java @@ -15,6 +15,9 @@ */ package org.springframework.data.redis.connection.lettuce; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; @@ -27,14 +30,11 @@ import org.springframework.data.redis.connection.ReactiveRedisConnection.Boolean import org.springframework.data.redis.connection.ReactiveRedisConnection.NumericResponse; import org.springframework.util.Assert; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - /** * @author Christoph Strobl * @since @since 2.0 */ -public class LettuceReactiveClusterHyperLogLogCommands extends LettuceReactiveHyperLogLogCommands +class LettuceReactiveClusterHyperLogLogCommands extends LettuceReactiveHyperLogLogCommands implements ReactiveClusterHyperLogLogCommands { /** diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterKeyCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterKeyCommands.java index 082f66e76..da891ef4b 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterKeyCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterKeyCommands.java @@ -36,8 +36,7 @@ import org.springframework.util.Assert; * @author Mark Paluch * @since 2.0 */ -public class LettuceReactiveClusterKeyCommands extends LettuceReactiveKeyCommands - implements ReactiveClusterKeyCommands { +class LettuceReactiveClusterKeyCommands extends LettuceReactiveKeyCommands implements ReactiveClusterKeyCommands { private LettuceReactiveRedisClusterConnection connection; diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterListCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterListCommands.java index 6bec796ef..13caca7a5 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterListCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterListCommands.java @@ -15,6 +15,9 @@ */ package org.springframework.data.redis.connection.lettuce; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + import java.nio.ByteBuffer; import org.reactivestreams.Publisher; @@ -24,16 +27,12 @@ import org.springframework.data.redis.connection.ReactiveClusterListCommands; import org.springframework.data.redis.connection.ReactiveRedisConnection.ByteBufferResponse; import org.springframework.util.Assert; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - /** * @author Christoph Strobl * @author Mark Paluch * @since 2.0 */ -public class LettuceReactiveClusterListCommands extends LettuceReactiveListCommands - implements ReactiveClusterListCommands { +class LettuceReactiveClusterListCommands extends LettuceReactiveListCommands implements ReactiveClusterListCommands { /** * Create new {@link LettuceReactiveListCommands}. diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterNumberCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterNumberCommands.java index a20f33f0e..b867a67d7 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterNumberCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterNumberCommands.java @@ -21,7 +21,7 @@ import org.springframework.data.redis.connection.ReactiveClusterNumberCommands; * @author Christoph Strobl * @since 2.0 */ -public class LettuceReactiveClusterNumberCommands extends LettuceReactiveNumberCommands +class LettuceReactiveClusterNumberCommands extends LettuceReactiveNumberCommands implements ReactiveClusterNumberCommands { /** diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterSetCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterSetCommands.java index 09699f962..0f597b29e 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterSetCommands.java @@ -36,8 +36,7 @@ import org.springframework.util.Assert; * @author Mark Paluch * @since 2.0 */ -public class LettuceReactiveClusterSetCommands extends LettuceReactiveSetCommands - implements ReactiveClusterSetCommands { +class LettuceReactiveClusterSetCommands extends LettuceReactiveSetCommands implements ReactiveClusterSetCommands { /** * Create new {@link LettuceReactiveSetCommands}. diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterStringCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterStringCommands.java index 887637122..f9ed97fe1 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterStringCommands.java @@ -15,6 +15,9 @@ */ package org.springframework.data.redis.connection.lettuce; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; @@ -25,14 +28,11 @@ import org.springframework.data.redis.connection.ClusterSlotHashUtil; import org.springframework.data.redis.connection.ReactiveClusterStringCommands; import org.springframework.data.redis.connection.ReactiveRedisConnection; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - /** * @author Christoph Strobl * @since 2.0 */ -public class LettuceReactiveClusterStringCommands extends LettuceReactiveStringCommands +class LettuceReactiveClusterStringCommands extends LettuceReactiveStringCommands implements ReactiveClusterStringCommands { /** diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterZSetCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterZSetCommands.java index dabf252ac..cf68db741 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterZSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterZSetCommands.java @@ -15,6 +15,9 @@ */ package org.springframework.data.redis.connection.lettuce; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + import org.reactivestreams.Publisher; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.redis.connection.ClusterSlotHashUtil; @@ -22,15 +25,11 @@ import org.springframework.data.redis.connection.ReactiveClusterZSetCommands; import org.springframework.data.redis.connection.ReactiveRedisConnection.NumericResponse; import org.springframework.util.Assert; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - /** * @author Christoph Strobl * @since @since 2.0 */ -public class LettuceReactiveClusterZSetCommands extends LettuceReactiveZSetCommands - implements ReactiveClusterZSetCommands { +class LettuceReactiveClusterZSetCommands extends LettuceReactiveZSetCommands implements ReactiveClusterZSetCommands { /** * Create new {@link LettuceReactiveSetCommands}. diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveGeoCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveGeoCommands.java index 9f0dc37d6..247290c2b 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveGeoCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveGeoCommands.java @@ -45,7 +45,7 @@ import org.springframework.util.Assert; * @author Christoph Strobl * @since 2.0 */ -public class LettuceReactiveGeoCommands implements ReactiveGeoCommands { +class LettuceReactiveGeoCommands implements ReactiveGeoCommands { private final LettuceReactiveRedisConnection connection; diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveHashCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveHashCommands.java index 89e9581db..3653cef26 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveHashCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveHashCommands.java @@ -41,7 +41,7 @@ import org.springframework.util.ObjectUtils; * @author Mark Paluch * @since 2.0 */ -public class LettuceReactiveHashCommands implements ReactiveHashCommands { +class LettuceReactiveHashCommands implements ReactiveHashCommands { private final LettuceReactiveRedisConnection connection; diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveHyperLogLogCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveHyperLogLogCommands.java index f39746207..51f434369 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveHyperLogLogCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveHyperLogLogCommands.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2017 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. @@ -15,6 +15,8 @@ */ package org.springframework.data.redis.connection.lettuce; +import reactor.core.publisher.Flux; + import java.nio.ByteBuffer; import org.reactivestreams.Publisher; @@ -23,13 +25,11 @@ import org.springframework.data.redis.connection.ReactiveRedisConnection.Boolean import org.springframework.data.redis.connection.ReactiveRedisConnection.NumericResponse; import org.springframework.util.Assert; -import reactor.core.publisher.Flux; - /** * @author Christoph Strobl * @since 2.0 */ -public class LettuceReactiveHyperLogLogCommands implements ReactiveHyperLogLogCommands { +class LettuceReactiveHyperLogLogCommands implements ReactiveHyperLogLogCommands { private final LettuceReactiveRedisConnection connection; diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveKeyCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveKeyCommands.java index 99a97abc9..82ce5397c 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveKeyCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveKeyCommands.java @@ -38,7 +38,7 @@ import org.springframework.util.Assert; * @author Mark Paluch * @since 2.0 */ -public class LettuceReactiveKeyCommands implements ReactiveKeyCommands { +class LettuceReactiveKeyCommands implements ReactiveKeyCommands { private final LettuceReactiveRedisConnection connection; diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveListCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveListCommands.java index 549e788d4..46cc03d60 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveListCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveListCommands.java @@ -40,7 +40,7 @@ import org.springframework.util.ObjectUtils; * @author Mark Paluch * @since 2.0 */ -public class LettuceReactiveListCommands implements ReactiveListCommands { +class LettuceReactiveListCommands implements ReactiveListCommands { private final LettuceReactiveRedisConnection connection; diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveNumberCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveNumberCommands.java index f4d5c38d5..91c268af3 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveNumberCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveNumberCommands.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2017 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. @@ -15,6 +15,9 @@ */ package org.springframework.data.redis.connection.lettuce; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + import org.reactivestreams.Publisher; import org.springframework.data.redis.connection.ReactiveNumberCommands; import org.springframework.data.redis.connection.ReactiveRedisConnection.KeyCommand; @@ -22,15 +25,12 @@ import org.springframework.data.redis.connection.ReactiveRedisConnection.Numeric import org.springframework.util.Assert; import org.springframework.util.NumberUtils; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - /** * @author Christoph Strobl * @author Mark Paluch * @since 2.0 */ -public class LettuceReactiveNumberCommands implements ReactiveNumberCommands { +class LettuceReactiveNumberCommands implements ReactiveNumberCommands { private final LettuceReactiveRedisConnection connection; diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveRedisClusterConnection.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveRedisClusterConnection.java index 361d918dd..c41ea22c0 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveRedisClusterConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveRedisClusterConnection.java @@ -33,7 +33,7 @@ import org.springframework.util.StringUtils; * @author Mark Paluch * @since 2.0 */ -public class LettuceReactiveRedisClusterConnection extends LettuceReactiveRedisConnection +class LettuceReactiveRedisClusterConnection extends LettuceReactiveRedisConnection implements ReactiveRedisClusterConnection { public LettuceReactiveRedisClusterConnection(RedisClusterClient client) { diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveRedisConnection.java index 8894b20fd..4ec8fd69f 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveRedisConnection.java @@ -31,7 +31,16 @@ import java.util.function.Function; import org.reactivestreams.Publisher; import org.springframework.dao.DataAccessException; import org.springframework.dao.InvalidDataAccessResourceUsageException; -import org.springframework.data.redis.connection.*; +import org.springframework.data.redis.connection.ReactiveGeoCommands; +import org.springframework.data.redis.connection.ReactiveHashCommands; +import org.springframework.data.redis.connection.ReactiveHyperLogLogCommands; +import org.springframework.data.redis.connection.ReactiveKeyCommands; +import org.springframework.data.redis.connection.ReactiveListCommands; +import org.springframework.data.redis.connection.ReactiveNumberCommands; +import org.springframework.data.redis.connection.ReactiveRedisConnection; +import org.springframework.data.redis.connection.ReactiveSetCommands; +import org.springframework.data.redis.connection.ReactiveStringCommands; +import org.springframework.data.redis.connection.ReactiveZSetCommands; import org.springframework.util.Assert; /** @@ -39,7 +48,7 @@ import org.springframework.util.Assert; * @author Mark Paluch * @since 2.0 */ -public class LettuceReactiveRedisConnection implements ReactiveRedisConnection { +class LettuceReactiveRedisConnection implements ReactiveRedisConnection { private StatefulConnection connection; diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveSetCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveSetCommands.java index a9fece31c..ef7900572 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveSetCommands.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2017 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. @@ -34,7 +34,7 @@ import org.springframework.util.Assert; * @author Mark Paluch * @since 2.0 */ -public class LettuceReactiveSetCommands implements ReactiveSetCommands { +class LettuceReactiveSetCommands implements ReactiveSetCommands { private final LettuceReactiveRedisConnection connection; diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommands.java index 6211dc44d..382311f6e 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommands.java @@ -38,7 +38,7 @@ import org.springframework.util.Assert; * @author Mark Paluch * @since 2.0 */ -public class LettuceReactiveStringCommands implements ReactiveStringCommands { +class LettuceReactiveStringCommands implements ReactiveStringCommands { private final static ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.wrap(new byte[0]); private final LettuceReactiveRedisConnection connection; diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveZSetCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveZSetCommands.java index 979a61a89..5a5fa9023 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveZSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveZSetCommands.java @@ -48,7 +48,7 @@ import org.springframework.util.StringUtils; * @author Mark Paluch * @since 2.0 */ -public class LettuceReactiveZSetCommands implements ReactiveZSetCommands { +class LettuceReactiveZSetCommands implements ReactiveZSetCommands { private final LettuceReactiveRedisConnection connection; diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceScriptingCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceScriptingCommands.java new file mode 100644 index 000000000..235e121e0 --- /dev/null +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceScriptingCommands.java @@ -0,0 +1,259 @@ +/* + * Copyright 2017 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.lettuce; + +import io.lettuce.core.cluster.api.async.RedisClusterAsyncCommands; +import io.lettuce.core.cluster.api.sync.RedisClusterCommands; + +import java.util.Arrays; +import java.util.List; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.dao.DataAccessException; +import org.springframework.data.redis.connection.RedisScriptingCommands; +import org.springframework.data.redis.connection.ReturnType; +import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceResult; +import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceTxResult; + +/** + * @author Mark Paluch + * @since 2.0 + */ +class LettuceScriptingCommands implements RedisScriptingCommands { + + private final LettuceConnection connection; + + public LettuceScriptingCommands(LettuceConnection connection) { + this.connection = connection; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptFlush() + */ + @Override + public void scriptFlush() { + try { + if (isPipelined()) { + pipeline(connection.newLettuceStatusResult(getAsyncConnection().scriptFlush())); + return; + } + if (isQueueing()) { + transaction(connection.newLettuceTxStatusResult(getConnection().scriptFlush())); + return; + } + getConnection().scriptFlush(); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptKill() + */ + @Override + public void scriptKill() { + if (isQueueing()) { + throw new UnsupportedOperationException("Script kill not permitted in a transaction"); + } + try { + if (isPipelined()) { + pipeline(connection.newLettuceStatusResult(getAsyncConnection().scriptKill())); + return; + } + if (isQueueing()) { + transaction(connection.newLettuceTxStatusResult(getConnection().scriptKill())); + return; + } + getConnection().scriptKill(); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptLoad(byte[]) + */ + @Override + public String scriptLoad(byte[] script) { + try { + if (isPipelined()) { + pipeline(connection.newLettuceResult(getAsyncConnection().scriptLoad(script))); + return null; + } + if (isQueueing()) { + transaction(connection.newLettuceTxResult(getConnection().scriptLoad(script))); + return null; + } + return getConnection().scriptLoad(script); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#scriptExists(java.lang.String[]) + */ + @Override + public List scriptExists(String... scriptSha1) { + try { + if (isPipelined()) { + pipeline(connection.newLettuceResult(getAsyncConnection().scriptExists(scriptSha1))); + return null; + } + if (isQueueing()) { + transaction(connection.newLettuceTxResult(getConnection().scriptExists(scriptSha1))); + return null; + } + return getConnection().scriptExists(scriptSha1); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#eval(byte[], org.springframework.data.redis.connection.ReturnType, int, byte[][]) + */ + @Override + public T eval(byte[] script, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { + try { + byte[][] keys = extractScriptKeys(numKeys, keysAndArgs); + byte[][] args = extractScriptArgs(numKeys, keysAndArgs); + String convertedScript = LettuceConverters.toString(script); + if (isPipelined()) { + pipeline(connection.newLettuceResult( + getAsyncConnection().eval(convertedScript, LettuceConverters.toScriptOutputType(returnType), keys, args), + new LettuceEvalResultsConverter(returnType))); + return null; + } + if (isQueueing()) { + transaction(connection.newLettuceTxResult( + getConnection().eval(convertedScript, LettuceConverters.toScriptOutputType(returnType), keys, args), + new LettuceEvalResultsConverter(returnType))); + return null; + } + return new LettuceEvalResultsConverter(returnType) + .convert(getConnection().eval(convertedScript, LettuceConverters.toScriptOutputType(returnType), keys, args)); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#evalSha(java.lang.String, org.springframework.data.redis.connection.ReturnType, int, byte[][]) + */ + @Override + public T evalSha(String scriptSha1, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { + try { + byte[][] keys = extractScriptKeys(numKeys, keysAndArgs); + byte[][] args = extractScriptArgs(numKeys, keysAndArgs); + + if (isPipelined()) { + pipeline(connection.newLettuceResult( + getAsyncConnection().evalsha(scriptSha1, LettuceConverters.toScriptOutputType(returnType), keys, args), + new LettuceEvalResultsConverter(returnType))); + return null; + } + if (isQueueing()) { + transaction(connection.newLettuceTxResult( + getConnection().evalsha(scriptSha1, LettuceConverters.toScriptOutputType(returnType), keys, args), + new LettuceEvalResultsConverter(returnType))); + return null; + } + return new LettuceEvalResultsConverter(returnType) + .convert(getConnection().evalsha(scriptSha1, LettuceConverters.toScriptOutputType(returnType), keys, args)); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisScriptingCommands#evalSha(byte[], org.springframework.data.redis.connection.ReturnType, int, byte[][]) + */ + @Override + public T evalSha(byte[] scriptSha1, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { + return evalSha(LettuceConverters.toString(scriptSha1), returnType, numKeys, keysAndArgs); + } + + private boolean isPipelined() { + return connection.isPipelined(); + } + + private boolean isQueueing() { + return connection.isQueueing(); + } + + private void pipeline(LettuceResult result) { + connection.pipeline(result); + } + + private void transaction(LettuceTxResult result) { + connection.transaction(result); + } + + private RedisClusterAsyncCommands getAsyncConnection() { + return connection.getAsyncConnection(); + } + + public RedisClusterCommands getConnection() { + return connection.getConnection(); + } + + private DataAccessException convertLettuceAccessException(Exception ex) { + return connection.convertLettuceAccessException(ex); + } + + private static byte[][] extractScriptKeys(int numKeys, byte[]... keysAndArgs) { + if (numKeys > 0) { + return Arrays.copyOfRange(keysAndArgs, 0, numKeys); + } + return new byte[0][0]; + } + + private static byte[][] extractScriptArgs(int numKeys, byte[]... keysAndArgs) { + if (keysAndArgs.length > numKeys) { + return Arrays.copyOfRange(keysAndArgs, numKeys, keysAndArgs.length); + } + return new byte[0][0]; + } + + private class LettuceEvalResultsConverter implements Converter { + private ReturnType returnType; + + public LettuceEvalResultsConverter(ReturnType returnType) { + this.returnType = returnType; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public T convert(Object source) { + if (returnType == ReturnType.MULTI) { + List resultList = (List) source; + for (Object obj : resultList) { + if (obj instanceof Exception) { + throw convertLettuceAccessException((Exception) obj); + } + } + } + return (T) source; + } + } +} diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceServerCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceServerCommands.java new file mode 100644 index 000000000..a8e476414 --- /dev/null +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceServerCommands.java @@ -0,0 +1,549 @@ +/* + * Copyright 2017 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.lettuce; + +import io.lettuce.core.cluster.api.async.RedisClusterAsyncCommands; +import io.lettuce.core.cluster.api.sync.RedisClusterCommands; + +import java.util.List; +import java.util.Properties; + +import org.springframework.dao.DataAccessException; +import org.springframework.data.redis.connection.RedisNode; +import org.springframework.data.redis.connection.RedisServerCommands; +import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceResult; +import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceTxResult; +import org.springframework.data.redis.core.types.RedisClientInfo; +import org.springframework.util.Assert; + +/** + * @author Mark Paluch + * @since 2.0 + */ +class LettuceServerCommands implements RedisServerCommands { + + private final LettuceConnection connection; + + public LettuceServerCommands(LettuceConnection connection) { + this.connection = connection; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#bgReWriteAof() + */ + @Override + public void bgReWriteAof() { + try { + if (isPipelined()) { + pipeline(connection.newLettuceStatusResult(getAsyncConnection().bgrewriteaof())); + return; + } + if (isQueueing()) { + transaction(connection.newLettuceTxStatusResult(getConnection().bgrewriteaof())); + return; + } + getConnection().bgrewriteaof(); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#bgSave() + */ + @Override + public void bgSave() { + try { + if (isPipelined()) { + pipeline(connection.newLettuceStatusResult(getAsyncConnection().bgsave())); + return; + } + if (isQueueing()) { + transaction(connection.newLettuceTxStatusResult(getConnection().bgsave())); + return; + } + getConnection().bgsave(); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#lastSave() + */ + @Override + public Long lastSave() { + try { + if (isPipelined()) { + pipeline(connection.newLettuceResult(getAsyncConnection().lastsave(), LettuceConverters.dateToLong())); + return null; + } + if (isQueueing()) { + transaction(connection.newLettuceTxResult(getConnection().lastsave(), LettuceConverters.dateToLong())); + return null; + } + return LettuceConverters.toLong(getConnection().lastsave()); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#save() + */ + @Override + public void save() { + try { + if (isPipelined()) { + pipeline(connection.newLettuceStatusResult(getAsyncConnection().save())); + return; + } + if (isQueueing()) { + transaction(connection.newLettuceTxStatusResult(getConnection().save())); + return; + } + getConnection().save(); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#dbSize() + */ + @Override + public Long dbSize() { + try { + if (isPipelined()) { + pipeline(connection.newLettuceResult(getAsyncConnection().dbsize())); + return null; + } + if (isQueueing()) { + transaction(connection.newLettuceTxResult(getConnection().dbsize())); + return null; + } + return getConnection().dbsize(); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#flushDb() + */ + @Override + public void flushDb() { + try { + if (isPipelined()) { + pipeline(connection.newLettuceStatusResult(getAsyncConnection().flushdb())); + return; + } + if (isQueueing()) { + transaction(connection.newLettuceTxStatusResult(getConnection().flushdb())); + return; + } + getConnection().flushdb(); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#flushAll() + */ + @Override + public void flushAll() { + try { + if (isPipelined()) { + pipeline(connection.newLettuceStatusResult(getAsyncConnection().flushall())); + return; + } + if (isQueueing()) { + transaction(connection.newLettuceTxResult(getConnection().flushall())); + return; + } + getConnection().flushall(); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#info() + */ + @Override + public Properties info() { + try { + if (isPipelined()) { + pipeline(connection.newLettuceResult(getAsyncConnection().info(), LettuceConverters.stringToProps())); + return null; + } + if (isQueueing()) { + transaction(connection.newLettuceTxResult(getConnection().info(), LettuceConverters.stringToProps())); + return null; + } + return LettuceConverters.toProperties(getConnection().info()); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#info(java.lang.String) + */ + @Override + public Properties info(String section) { + try { + if (isPipelined()) { + pipeline(connection.newLettuceResult(getAsyncConnection().info(section), LettuceConverters.stringToProps())); + return null; + } + if (isQueueing()) { + transaction(connection.newLettuceTxResult(getConnection().info(section), LettuceConverters.stringToProps())); + return null; + } + return LettuceConverters.toProperties(getConnection().info(section)); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#shutdown() + */ + @Override + public void shutdown() { + try { + if (isPipelined()) { + getAsyncConnection().shutdown(true); + return; + } + getConnection().shutdown(true); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#shutdown(org.springframework.data.redis.connection.RedisServerCommands.ShutdownOption) + */ + @Override + public void shutdown(ShutdownOption option) { + + if (option == null) { + shutdown(); + return; + } + + boolean save = ShutdownOption.SAVE.equals(option); + try { + if (isPipelined()) { + getAsyncConnection().shutdown(save); + return; + } + getConnection().shutdown(save); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#getConfig(java.lang.String) + */ + @Override + public List getConfig(String param) { + try { + if (isPipelined()) { + pipeline(connection.newLettuceResult(getAsyncConnection().configGet(param))); + return null; + } + if (isQueueing()) { + transaction(connection.newLettuceTxResult(getConnection().configGet(param))); + return null; + } + return getConnection().configGet(param); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#setConfig(java.lang.String, java.lang.String) + */ + @Override + public void setConfig(String param, String value) { + try { + if (isPipelined()) { + pipeline(connection.newLettuceStatusResult(getAsyncConnection().configSet(param, value))); + return; + } + if (isQueueing()) { + transaction(connection.newLettuceTxStatusResult(getConnection().configSet(param, value))); + return; + } + getConnection().configSet(param, value); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#resetConfigStats() + */ + @Override + public void resetConfigStats() { + try { + if (isPipelined()) { + pipeline(connection.newLettuceStatusResult(getAsyncConnection().configResetstat())); + return; + } + if (isQueueing()) { + transaction(connection.newLettuceTxStatusResult(getConnection().configResetstat())); + return; + } + getConnection().configResetstat(); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#time() + */ + @Override + public Long time() { + + try { + + if (isPipelined()) { + pipeline(connection.newLettuceResult(getAsyncConnection().time(), LettuceConverters.toTimeConverter())); + return null; + } + if (isQueueing()) { + transaction(connection.newLettuceTxResult(getConnection().time(), LettuceConverters.toTimeConverter())); + return null; + } + + return LettuceConverters.toTimeConverter().convert(getConnection().time()); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#killClient(java.lang.String, int) + */ + @Override + public void killClient(String host, int port) { + + Assert.hasText(host, "Host for 'CLIENT KILL' must not be 'null' or 'empty'."); + + String client = String.format("%s:%s", host, port); + try { + if (isPipelined()) { + pipeline(connection.newLettuceStatusResult(getAsyncConnection().clientKill(client))); + return; + } + getConnection().clientKill(client); + } catch (Exception e) { + throw convertLettuceAccessException(e); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#setClientName(byte[]) + */ + @Override + public void setClientName(byte[] name) { + + if (isQueueing()) { + pipeline(connection.newLettuceStatusResult(getAsyncConnection().clientSetname(name))); + return; + } + if (isQueueing()) { + transaction(connection.newLettuceTxStatusResult(getConnection().clientSetname(name))); + return; + } + + getAsyncConnection().clientSetname(name); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#getClientName() + */ + @Override + public String getClientName() { + + try { + + if (isPipelined()) { + pipeline(connection.newLettuceResult(getAsyncConnection().clientGetname(), LettuceConverters.bytesToString())); + return null; + } + if (isQueueing()) { + transaction(connection.newLettuceTxResult(getConnection().clientGetname(), LettuceConverters.bytesToString())); + return null; + } + + return LettuceConverters.toString(getConnection().clientGetname()); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#getClientList() + */ + @Override + public List getClientList() { + + if (isPipelined()) { + throw new UnsupportedOperationException("Cannot be called in pipeline mode."); + } + if (isQueueing()) { + transaction(connection.newLettuceTxResult(getAsyncConnection().clientList(), + LettuceConverters.stringToRedisClientListConverter())); + return null; + } + + return LettuceConverters.toListOfRedisClientInformation(getConnection().clientList()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#slaveOf(java.lang.String, int) + */ + @Override + public void slaveOf(String host, int port) { + + Assert.hasText(host, "Host must not be null for 'SLAVEOF' command."); + try { + if (isPipelined()) { + pipeline(connection.newLettuceStatusResult(getAsyncConnection().slaveof(host, port))); + return; + } + if (isQueueing()) { + transaction(connection.newLettuceTxResult(getConnection().slaveof(host, port))); + return; + } + getConnection().slaveof(host, port); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#slaveOfNoOne() + */ + @Override + public void slaveOfNoOne() { + + try { + if (isPipelined()) { + pipeline(connection.newLettuceStatusResult(getAsyncConnection().slaveofNoOne())); + return; + } + if (isQueueing()) { + transaction(connection.newLettuceTxResult(getConnection().slaveofNoOne())); + return; + } + getConnection().slaveofNoOne(); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption) + */ + @Override + public void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option) { + migrate(key, target, dbIndex, option, Long.MAX_VALUE); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption, long) + */ + @Override + public void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option, long timeout) { + + try { + if (isPipelined()) { + pipeline(connection + .newLettuceResult(getAsyncConnection().migrate(target.getHost(), target.getPort(), key, dbIndex, timeout))); + return; + } + if (isQueueing()) { + transaction(connection + .newLettuceTxResult(getConnection().migrate(target.getHost(), target.getPort(), key, dbIndex, timeout))); + return; + } + getConnection().migrate(target.getHost(), target.getPort(), key, dbIndex, timeout); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + private boolean isPipelined() { + return connection.isPipelined(); + } + + private boolean isQueueing() { + return connection.isQueueing(); + } + + private void pipeline(LettuceResult result) { + connection.pipeline(result); + } + + private void transaction(LettuceTxResult result) { + connection.transaction(result); + } + + private RedisClusterAsyncCommands getAsyncConnection() { + return connection.getAsyncConnection(); + } + + public RedisClusterCommands getConnection() { + return connection.getConnection(); + } + + private DataAccessException convertLettuceAccessException(Exception ex) { + return connection.convertLettuceAccessException(ex); + } +} diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceZSetCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceZSetCommands.java index 1795e416f..47d1e20f7 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceZSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceZSetCommands.java @@ -684,7 +684,7 @@ class LettuceZSetCommands implements RedisZSetCommands { List> result = scoredValueScanCursor.getValues(); List values = connection.failsafeReadScanValues(result, LettuceConverters.scoredValuesToTupleList()); - return new ScanIteration(Long.valueOf(nextCursorId), values); + return new ScanIteration<>(Long.valueOf(nextCursorId), values); } protected void doClose() { diff --git a/src/test/java/org/springframework/data/redis/connection/jedis/ScanTests.java b/src/test/java/org/springframework/data/redis/connection/jedis/ScanTests.java index e2f8cef28..2cca48a33 100644 --- a/src/test/java/org/springframework/data/redis/connection/jedis/ScanTests.java +++ b/src/test/java/org/springframework/data/redis/connection/jedis/ScanTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2017 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. @@ -35,6 +35,7 @@ import org.junit.runners.Parameterized.Parameters; import org.springframework.data.redis.ConnectionFactoryTracker; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceTestClientResources; import org.springframework.data.redis.core.BoundHashOperations; import org.springframework.data.redis.core.Cursor; import org.springframework.data.redis.core.RedisTemplate; @@ -69,6 +70,7 @@ public class ScanTests { jedisConnectionFactory.afterPropertiesSet(); LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(); + lettuceConnectionFactory.setClientResources(LettuceTestClientResources.getSharedClientResources()); lettuceConnectionFactory.setHostName("127.0.0.1"); lettuceConnectionFactory.setPort(6379); lettuceConnectionFactory.afterPropertiesSet(); diff --git a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactoryTests.java b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactoryTests.java index 69ff0096d..6ebc26bd2 100644 --- a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactoryTests.java +++ b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactoryTests.java @@ -39,7 +39,7 @@ import org.springframework.data.redis.connection.StringRedisConnection; /** * Integration test of {@link LettuceConnectionFactory} - * + * * @author Jennifer Hickey * @author Thomas Darimont * @author Christoph Strobl @@ -325,6 +325,7 @@ public class LettuceConnectionFactoryTests { public void factoryShouldReturnReactiveConnectionWhenCorrectly() { LettuceConnectionFactory factory = new LettuceConnectionFactory(); + factory.setClientResources(LettuceTestClientResources.getSharedClientResources()); factory.afterPropertiesSet(); ConnectionFactoryTracker.add(factory); diff --git a/src/test/java/org/springframework/data/redis/core/DefaultReactiveHashOperationsIntegrationTests.java b/src/test/java/org/springframework/data/redis/core/DefaultReactiveHashOperationsIntegrationTests.java index f2c2708b2..151349451 100644 --- a/src/test/java/org/springframework/data/redis/core/DefaultReactiveHashOperationsIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/core/DefaultReactiveHashOperationsIntegrationTests.java @@ -41,6 +41,7 @@ import org.springframework.data.redis.StringObjectFactory; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceTestClientResources; import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.StringRedisSerializer; @@ -68,6 +69,7 @@ public class DefaultReactiveHashOperationsIntegrationTests { ObjectFactory rawFactory = new RawObjectFactory(); LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(); + lettuceConnectionFactory.setClientResources(LettuceTestClientResources.getSharedClientResources()); lettuceConnectionFactory.setPort(SettingsUtils.getPort()); lettuceConnectionFactory.setHostName(SettingsUtils.getHost()); lettuceConnectionFactory.afterPropertiesSet(); diff --git a/src/test/java/org/springframework/data/redis/core/ReactiveOperationsTestParams.java b/src/test/java/org/springframework/data/redis/core/ReactiveOperationsTestParams.java index 5fd5ca77c..0b142f772 100644 --- a/src/test/java/org/springframework/data/redis/core/ReactiveOperationsTestParams.java +++ b/src/test/java/org/springframework/data/redis/core/ReactiveOperationsTestParams.java @@ -36,6 +36,7 @@ import org.springframework.data.redis.StringObjectFactory; import org.springframework.data.redis.connection.RedisClusterConfiguration; import org.springframework.data.redis.connection.RedisClusterNode; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceTestClientResources; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.GenericToStringSerializer; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; @@ -72,6 +73,7 @@ abstract public class ReactiveOperationsTestParams { } LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(); + lettuceConnectionFactory.setClientResources(LettuceTestClientResources.getSharedClientResources()); lettuceConnectionFactory.setPort(SettingsUtils.getPort()); lettuceConnectionFactory.setHostName(SettingsUtils.getHost()); lettuceConnectionFactory.afterPropertiesSet(); diff --git a/src/test/java/org/springframework/data/redis/core/RedisKeyValueAdapterTests.java b/src/test/java/org/springframework/data/redis/core/RedisKeyValueAdapterTests.java index 7065f9006..605a79c70 100644 --- a/src/test/java/org/springframework/data/redis/core/RedisKeyValueAdapterTests.java +++ b/src/test/java/org/springframework/data/redis/core/RedisKeyValueAdapterTests.java @@ -49,6 +49,7 @@ import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceTestClientResources; import org.springframework.data.redis.core.RedisKeyValueAdapter.EnableKeyspaceEvents; import org.springframework.data.redis.core.convert.KeyspaceConfiguration; import org.springframework.data.redis.core.convert.MappingConfiguration; @@ -82,7 +83,10 @@ public class RedisKeyValueAdapterTests { @Parameters public static List params() { - return Arrays. asList(new JedisConnectionFactory(), new LettuceConnectionFactory()); + + LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(); + lettuceConnectionFactory.setClientResources(LettuceTestClientResources.getSharedClientResources()); + return Arrays. asList(new JedisConnectionFactory(), lettuceConnectionFactory); } @AfterClass diff --git a/src/test/java/org/springframework/data/redis/core/RedisKeyValueTemplateTests.java b/src/test/java/org/springframework/data/redis/core/RedisKeyValueTemplateTests.java index 6060e3559..fef718a95 100644 --- a/src/test/java/org/springframework/data/redis/core/RedisKeyValueTemplateTests.java +++ b/src/test/java/org/springframework/data/redis/core/RedisKeyValueTemplateTests.java @@ -19,6 +19,9 @@ import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.number.IsCloseTo.*; import static org.junit.Assert.*; +import lombok.Data; +import lombok.EqualsAndHashCode; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -41,13 +44,11 @@ import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceTestClientResources; import org.springframework.data.redis.core.index.Indexed; import org.springframework.data.redis.core.mapping.RedisMappingContext; import org.springframework.util.ObjectUtils; -import lombok.Data; -import lombok.EqualsAndHashCode; - /** * Integration tests for {@link RedisKeyValueTemplate}. * @@ -77,6 +78,7 @@ public class RedisKeyValueTemplateTests { jedis.afterPropertiesSet(); LettuceConnectionFactory lettuce = new LettuceConnectionFactory(); + lettuce.setClientResources(LettuceTestClientResources.getSharedClientResources()); lettuce.afterPropertiesSet(); return Arrays. asList(jedis, lettuce); diff --git a/src/test/java/org/springframework/data/redis/core/RedisTemplateTests.java b/src/test/java/org/springframework/data/redis/core/RedisTemplateTests.java index 9d6ee3365..4ffb3f74e 100644 --- a/src/test/java/org/springframework/data/redis/core/RedisTemplateTests.java +++ b/src/test/java/org/springframework/data/redis/core/RedisTemplateTests.java @@ -21,17 +21,7 @@ import static org.junit.Assume.*; import static org.springframework.data.redis.SpinBarrier.*; import static org.springframework.data.redis.matcher.RedisTestMatchers.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.TimeUnit; import org.hamcrest.core.IsNot; @@ -55,6 +45,7 @@ import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.StringRedisConnection; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceTestClientResources; import org.springframework.data.redis.core.ZSetOperations.TypedTuple; import org.springframework.data.redis.core.query.SortQueryBuilder; import org.springframework.data.redis.core.script.DefaultRedisScript; @@ -261,6 +252,7 @@ public class RedisTemplateTests { public void testExecConversionDisabled() { LettuceConnectionFactory factory2 = new LettuceConnectionFactory(SettingsUtils.getHost(), SettingsUtils.getPort()); + factory2.setClientResources(LettuceTestClientResources.getSharedClientResources()); factory2.setConvertPipelineAndTxResults(false); factory2.afterPropertiesSet(); diff --git a/src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperTests.java b/src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperTests.java index a9b88e866..a9b5f94c8 100644 --- a/src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperTests.java +++ b/src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperTests.java @@ -33,6 +33,7 @@ import org.springframework.data.redis.Person; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceTestClientResources; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.hash.Jackson2HashMapper; @@ -40,6 +41,7 @@ import org.springframework.data.redis.hash.Jackson2HashMapper; * Integration tests for {@link Jackson2HashMapper}. * * @author Christoph Strobl + * @author Mark Paluch */ @RunWith(Parameterized.class) public class Jackson2HashMapperTests { @@ -60,7 +62,10 @@ public class Jackson2HashMapperTests { @Parameters public static Collection params() { - return Arrays. asList(new JedisConnectionFactory(), new LettuceConnectionFactory()); + + LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(); + lettuceConnectionFactory.setClientResources(LettuceTestClientResources.getSharedClientResources()); + return Arrays. asList(new JedisConnectionFactory(), lettuceConnectionFactory); } @AfterClass