package com.lambdaworks.redis.cluster.api.sync; import java.util.List; import java.util.Map; import java.util.function.Predicate; import com.lambdaworks.redis.*; import com.lambdaworks.redis.api.sync.RedisKeyCommands; import com.lambdaworks.redis.api.sync.RedisScriptingCommands; import com.lambdaworks.redis.api.sync.RedisServerCommands; import com.lambdaworks.redis.api.sync.RedisStringCommands; import com.lambdaworks.redis.cluster.ClusterClientOptions; import com.lambdaworks.redis.cluster.RedisAdvancedClusterConnection; import com.lambdaworks.redis.cluster.api.NodeSelectionSupport; import com.lambdaworks.redis.cluster.api.StatefulRedisClusterConnection; import com.lambdaworks.redis.cluster.models.partitions.RedisClusterNode; import com.lambdaworks.redis.output.KeyStreamingChannel; /** * Advanced synchronous and thread-safe Redis Cluster API. * * @author Mark Paluch * @since 4.0 */ public interface RedisAdvancedClusterCommands<K, V> extends RedisClusterCommands<K, V>, RedisAdvancedClusterConnection<K, V> { /** * Retrieve a connection to the specified cluster node using the nodeId. Host and port are looked up in the node list. In * contrast to the {@link RedisAdvancedClusterCommands}, node-connections do not route commands to other cluster nodes * * @param nodeId the node Id * @return a connection to the requested cluster node */ RedisClusterCommands<K, V> getConnection(String nodeId); /** * Retrieve a connection to the specified cluster node using host and port. In contrast to the * {@link RedisAdvancedClusterCommands}, node-connections do not route commands to other cluster nodes. Host and port * connections are verified by default for cluster membership, see * {@link ClusterClientOptions#isValidateClusterNodeMembership()}. * * @param host the host * @param port the port * @return a connection to the requested cluster node */ RedisClusterCommands<K, V> getConnection(String host, int port); /** * @return the underlying connection. */ StatefulRedisClusterConnection<K, V> getStatefulConnection(); /** * Select all masters. * * @return API with synchronous executed commands on a selection of master cluster nodes. */ default NodeSelection<K, V> masters() { return nodes(redisClusterNode -> redisClusterNode.is(RedisClusterNode.NodeFlag.MASTER)); } /** * Select all slaves. * * @return API with synchronous executed commands on a selection of slave cluster nodes. */ default NodeSelection<K, V> slaves() { return readonly(redisClusterNode -> redisClusterNode.is(RedisClusterNode.NodeFlag.SLAVE)); } /** * Select all slaves. * * @param predicate Predicate to filter nodes * @return API with synchronous executed commands on a selection of slave cluster nodes. */ default NodeSelection<K, V> slaves(Predicate<RedisClusterNode> predicate) { return readonly( redisClusterNode -> predicate.test(redisClusterNode) && redisClusterNode.is(RedisClusterNode.NodeFlag.SLAVE)); } /** * Select all known cluster nodes. * * @return API with synchronous executed commands on a selection of all cluster nodes. */ default NodeSelection<K, V> all() { return nodes(redisClusterNode -> true); } /** * Select slave nodes by a predicate and keeps a static selection. Slave connections operate in {@literal READONLY} mode. * The set of nodes within the {@link NodeSelectionSupport} does not change when the cluster view changes. * * @param predicate Predicate to filter nodes * @return API with synchronous executed commands on a selection of cluster nodes matching {@code predicate} */ NodeSelection<K, V> readonly(Predicate<RedisClusterNode> predicate); /** * Select nodes by a predicate and keeps a static selection. The set of nodes within the {@link NodeSelectionSupport} does * not change when the cluster view changes. * * @param predicate Predicate to filter nodes * @return API with synchronous executed commands on a selection of cluster nodes matching {@code predicate} */ NodeSelection<K, V> nodes(Predicate<RedisClusterNode> predicate); /** * Select nodes by a predicate * * @param predicate Predicate to filter nodes * @param dynamic Defines, whether the set of nodes within the {@link NodeSelectionSupport} can change when the cluster view * changes. * @return API with synchronous executed commands on a selection of cluster nodes matching {@code predicate} */ NodeSelection<K, V> nodes(Predicate<RedisClusterNode> predicate, boolean dynamic); /** * Delete one or more keys with pipelining. Cross-slot keys will result in multiple calls to the particular cluster nodes. * * @param keys the keys * @return Long integer-reply The number of keys that were removed. * @see RedisKeyCommands#del(Object[]) */ Long del(K... keys); /** * Unlink one or more keys with pipelining. Cross-slot keys will result in multiple calls to the particular cluster nodes. * * @param keys the keys * @return Long integer-reply The number of keys that were removed. * @see RedisKeyCommands#unlink(Object[]) */ Long unlink(K... keys); /** * Determine how many keys exist with pipelining. Cross-slot keys will result in multiple calls to the particular cluster nodes. * * @param keys the keys * @return Long integer-reply specifically: Number of existing keys */ Long exists(K... keys); /** * Get the values of all the given keys with pipelining. Cross-slot keys will result in multiple calls to the particular * cluster nodes. * * @param keys the key * @return List<V> array-reply list of values at the specified keys. * @see RedisStringCommands#mget(Object[]) */ List<V> mget(K... keys); /** * Set multiple keys to multiple values with pipelining. Cross-slot keys will result in multiple calls to the particular * cluster nodes. * * @param map the map * @return String simple-string-reply always {@code OK} since {@code MSET} can't fail. * @see RedisStringCommands#mset(Map) */ String mset(Map<K, V> map); /** * Set multiple keys to multiple values, only if none of the keys exist with pipelining. Cross-slot keys will result in * multiple calls to the particular cluster nodes. * * @param map the null * @return Boolean integer-reply specifically: * * {@code 1} if the all the keys were set. {@code 0} if no key was set (at least one key already existed). * @see RedisStringCommands#msetnx(Map) */ Boolean msetnx(Map<K, V> map); /** * Set the current connection name on all known cluster nodes with pipelining. * * @param name the client name * @return simple-string-reply {@code OK} if the connection name was successfully set. * @see RedisServerCommands#clientSetname(Object) */ String clientSetname(K name); /** * Remove all keys from all databases on all cluster masters with pipelining. * * @return String simple-string-reply * @see RedisServerCommands#flushall() */ String flushall(); /** * Remove all keys from the current database on all cluster masters with pipelining. * * @return String simple-string-reply * @see RedisServerCommands#flushdb() */ String flushdb(); /** * Return the number of keys in the selected database on all cluster masters. * * @return Long integer-reply * @see RedisServerCommands#dbsize() */ Long dbsize(); /** * Find all keys matching the given pattern on all cluster masters. * * @param pattern the pattern type: patternkey (pattern) * @return List<K> array-reply list of keys matching {@code pattern}. * @see RedisKeyCommands#keys(Object) */ List<K> keys(K pattern); /** * Find all keys matching the given pattern on all cluster masters. * * @param channel the channel * @param pattern the pattern * @return Long array-reply list of keys matching {@code pattern}. * @see RedisKeyCommands#keys(KeyStreamingChannel, Object) */ Long keys(KeyStreamingChannel<K> channel, K pattern); /** * Return a random key from the keyspace on a random master. * * @return V bulk-string-reply the random key, or {@literal null} when the database is empty. * @see RedisKeyCommands#randomkey() */ V randomkey(); /** * Remove all the scripts from the script cache on all cluster nodes. * * @return String simple-string-reply * @see RedisScriptingCommands#scriptFlush() */ String scriptFlush(); /** * Kill the script currently in execution on all cluster nodes. This call does not fail even if no scripts are running. * * @return String simple-string-reply, always {@literal OK}. * @see RedisScriptingCommands#scriptKill() */ String scriptKill(); /** * Synchronously save the dataset to disk and then shut down all nodes of the cluster. * * @param save {@literal true} force save operation * @see RedisServerCommands#shutdown(boolean) */ void shutdown(boolean save); /** * Incrementally iterate the keys space over the whole Cluster. * * @return KeyScanCursor<K> scan cursor. * @see RedisKeyCommands#scan() */ KeyScanCursor<K> scan(); /** * Incrementally iterate the keys space over the whole Cluster. * * @param scanArgs scan arguments * @return KeyScanCursor<K> scan cursor. * @see RedisKeyCommands#scan(ScanArgs) */ KeyScanCursor<K> scan(ScanArgs scanArgs); /** * Incrementally iterate the keys space over the whole Cluster. * * @param scanCursor cursor to resume the scan. It's required to reuse the {@code scanCursor} instance from the previous * {@link #scan()} call. * @param scanArgs scan arguments * @return KeyScanCursor<K> scan cursor. * @see RedisKeyCommands#scan(ScanCursor, ScanArgs) */ KeyScanCursor<K> scan(ScanCursor scanCursor, ScanArgs scanArgs); /** * Incrementally iterate the keys space over the whole Cluster. * * @param scanCursor cursor to resume the scan. It's required to reuse the {@code scanCursor} instance from the previous * {@link #scan()} call. * @return KeyScanCursor<K> scan cursor. * @see RedisKeyCommands#scan(ScanCursor) */ KeyScanCursor<K> scan(ScanCursor scanCursor); /** * Incrementally iterate the keys space over the whole Cluster. * * @param channel streaming channel that receives a call for every key * @return StreamScanCursor scan cursor. * @see RedisKeyCommands#scan(KeyStreamingChannel) */ StreamScanCursor scan(KeyStreamingChannel<K> channel); /** * Incrementally iterate the keys space over the whole Cluster. * * @param channel streaming channel that receives a call for every key * @param scanArgs scan arguments * @return StreamScanCursor scan cursor. * @see RedisKeyCommands#scan(KeyStreamingChannel, ScanArgs) */ StreamScanCursor scan(KeyStreamingChannel<K> channel, ScanArgs scanArgs); /** * Incrementally iterate the keys space over the whole Cluster. * * @param channel streaming channel that receives a call for every key * @param scanCursor cursor to resume the scan. It's required to reuse the {@code scanCursor} instance from the previous * {@link #scan()} call. * @param scanArgs scan arguments * @return StreamScanCursor scan cursor. * @see RedisKeyCommands#scan(KeyStreamingChannel, ScanCursor, ScanArgs) */ StreamScanCursor scan(KeyStreamingChannel<K> channel, ScanCursor scanCursor, ScanArgs scanArgs); /** * Incrementally iterate the keys space over the whole Cluster. * * @param channel streaming channel that receives a call for every key * @param scanCursor cursor to resume the scan. It's required to reuse the {@code scanCursor} instance from the previous * {@link #scan()} call. * @return StreamScanCursor scan cursor. * @see RedisKeyCommands#scan(ScanCursor, ScanArgs) */ StreamScanCursor scan(KeyStreamingChannel<K> channel, ScanCursor scanCursor); /** * Touch one or more keys with pipelining. Touch sets the last accessed time for a key. Non-exsitent keys wont get created. * Cross-slot keys will result in multiple calls to the particular cluster nodes. * * @param keys the keys * @return Long integer-reply the number of found keys. */ Long touch(K... keys); }