DATAREDIS-626 - Refactor RedisConnection implementations to Redis feature-specific interfaces.
We refactored JedisConnection and LettuceConnection from monolithic connection classes into modular classes that organize methods according the Redis feature group and created segregated interfaces per Redis feature group. Segregated interfaces reduce the number of methods available on the interface to the used data type. This refactoring reduces the responsibility of JedisConnection/LettuceConnection and JedisClusterConnection/LettuceClusterConnection to a minimum of commands. To preserve backwards-compatibility with users of the connection classes, we introduced DefaultedRedisConnection and DefaultedRedisClusterConnection to forward calls from the connection facade to the specific implementation. Deprecation of connection facade method assists migration off these methods towards using methods on the feature group interface. LettuceConnection connection = … connection.keyCommands().del(key); connection.hashCommands().hSet(key, field, value); Original pull request: #247.
This commit is contained in:
committed by
Mark Paluch
parent
016af63dd4
commit
c636400104
@@ -27,7 +27,7 @@ import org.springframework.data.redis.RedisSystemException;
|
||||
* @author Christoph Strobl
|
||||
* @since 1.4
|
||||
*/
|
||||
public abstract class AbstractRedisConnection implements RedisConnection {
|
||||
public abstract class AbstractRedisConnection implements DefaultedRedisConnection {
|
||||
|
||||
private RedisSentinelConfiguration sentinelConfiguration;
|
||||
private ConcurrentHashMap<RedisNode, RedisSentinelConnection> connectionCache = new ConcurrentHashMap<RedisNode, RedisSentinelConnection>();
|
||||
|
||||
@@ -3034,7 +3034,7 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.HyperLogLogCommands#pfAdd(byte[], byte[][])
|
||||
* @see org.springframework.data.redis.connection.RedisHyperLogLogCommands#pfAdd(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long pfAdd(byte[] key, byte[]... values) {
|
||||
@@ -3052,7 +3052,7 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.HyperLogLogCommands#pfCount(byte[][])
|
||||
* @see org.springframework.data.redis.connection.RedisHyperLogLogCommands#pfCount(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long pfCount(byte[]... keys) {
|
||||
@@ -3070,7 +3070,7 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.HyperLogLogCommands#pfMerge(byte[], byte[][])
|
||||
* @see org.springframework.data.redis.connection.RedisHyperLogLogCommands#pfMerge(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public void pfMerge(byte[] destinationKey, byte[]... sourceKeys) {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface DefaultedRedisClusterConnection extends RedisClusterConnection, DefaultedRedisConnection {
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -24,7 +24,7 @@ package org.springframework.data.redis.connection;
|
||||
*/
|
||||
public interface RedisCommands extends RedisKeyCommands, RedisStringCommands, RedisListCommands, RedisSetCommands,
|
||||
RedisZSetCommands, RedisHashCommands, RedisTxCommands, RedisPubSubCommands, RedisConnectionCommands,
|
||||
RedisServerCommands, RedisScriptingCommands, RedisGeoCommands, HyperLogLogCommands {
|
||||
RedisServerCommands, RedisScriptingCommands, RedisGeoCommands, RedisHyperLogLogCommands {
|
||||
|
||||
/**
|
||||
* 'Native' or 'raw' execution of the given command along-side the given arguments. The command is executed as is,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
* 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.
|
||||
@@ -26,9 +26,88 @@ import org.springframework.dao.DataAccessException;
|
||||
* The methods follow as much as possible the Redis names and conventions.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public interface RedisConnection extends RedisCommands {
|
||||
|
||||
/**
|
||||
* Get {@link RedisGeoCommands}.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
default RedisGeoCommands geoCommands() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link RedisHashCommands}.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @since 2.0
|
||||
*/
|
||||
default RedisHashCommands hashCommands() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link RedisHyperLogLogCommands}.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
default RedisHyperLogLogCommands hyperLogLogCommands() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link RedisKeyCommands}.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @since 2.0
|
||||
*/
|
||||
default RedisKeyCommands keyCommands() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link RedisListCommands}.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @since 2.0
|
||||
*/
|
||||
default RedisListCommands listCommands() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link RedisSetCommands}.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @since 2.0
|
||||
*/
|
||||
default RedisSetCommands setCommands() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link RedisStringCommands}.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @since 2.0
|
||||
*/
|
||||
default RedisStringCommands stringCommands() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link RedisZSetCommands}.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @since 2.0
|
||||
*/
|
||||
default RedisZSetCommands zSetCommands() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes (or quits) the connection.
|
||||
*
|
||||
|
||||
@@ -60,7 +60,13 @@ public interface RedisGeoCommands {
|
||||
* @return Number of elements added.
|
||||
* @see <a href="http://redis.io/commands/geoadd">Redis Documentation: GEOADD</a>
|
||||
*/
|
||||
Long geoAdd(byte[] key, GeoLocation<byte[]> location);
|
||||
default Long geoAdd(byte[] key, GeoLocation<byte[]> location) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(location, "Location must not be null!");
|
||||
|
||||
return geoAdd(key, location.getPoint(), location.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add {@link Map} of member / {@link Point} pairs to {@literal key}.
|
||||
@@ -156,7 +162,9 @@ public interface RedisGeoCommands {
|
||||
* @return never {@literal null}.
|
||||
* @see <a href="http://redis.io/commands/georadiusbymember">Redis Documentation: GEORADIUSBYMEMBER</a>
|
||||
*/
|
||||
GeoResults<GeoLocation<byte[]>> geoRadiusByMember(byte[] key, byte[] member, double radius);
|
||||
default GeoResults<GeoLocation<byte[]>> geoRadiusByMember(byte[] key, byte[] member, double radius) {
|
||||
return geoRadiusByMember(key, member, new Distance(radius, DistanceUnit.METERS));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s within the circle defined by the {@literal members} coordinates and given
|
||||
@@ -201,7 +209,7 @@ public interface RedisGeoCommands {
|
||||
* @author Christoph Strobl
|
||||
* @since 1.8
|
||||
*/
|
||||
public class GeoRadiusCommandArgs implements Cloneable {
|
||||
class GeoRadiusCommandArgs implements Cloneable {
|
||||
|
||||
Set<Flag> flags = new LinkedHashSet<Flag>(2, 1);
|
||||
Long limit;
|
||||
@@ -332,7 +340,7 @@ public interface RedisGeoCommands {
|
||||
*/
|
||||
@Data
|
||||
@RequiredArgsConstructor
|
||||
public static class GeoLocation<T> {
|
||||
class GeoLocation<T> {
|
||||
|
||||
private final T name;
|
||||
private final Point point;
|
||||
@@ -344,7 +352,7 @@ public interface RedisGeoCommands {
|
||||
* @author Christoph Strobl
|
||||
* @since 1.8
|
||||
*/
|
||||
public static enum DistanceUnit implements Metric {
|
||||
enum DistanceUnit implements Metric {
|
||||
|
||||
METERS(6378137, "m"), KILOMETERS(6378.137, "km"), MILES(3963.191, "mi"), FEET(20925646.325, "ft");
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ package org.springframework.data.redis.connection;
|
||||
* @author Mark Paluch
|
||||
* @since 1.5
|
||||
*/
|
||||
public interface HyperLogLogCommands {
|
||||
public interface RedisHyperLogLogCommands {
|
||||
|
||||
/**
|
||||
* Adds given {@literal values} to the HyperLogLog stored at given {@literal key}.
|
||||
@@ -29,7 +29,7 @@ import org.springframework.data.redis.core.types.Expiration;
|
||||
*/
|
||||
public interface RedisStringCommands {
|
||||
|
||||
public enum BitOperation {
|
||||
enum BitOperation {
|
||||
AND, OR, XOR, NOT;
|
||||
}
|
||||
|
||||
@@ -278,7 +278,7 @@ public interface RedisStringCommands {
|
||||
* @author Christoph Strobl
|
||||
* @since 1.7
|
||||
*/
|
||||
public static enum SetOption {
|
||||
enum SetOption {
|
||||
|
||||
/**
|
||||
* Do not set any additional command argument.
|
||||
|
||||
@@ -35,14 +35,14 @@ public interface RedisZSetCommands {
|
||||
/**
|
||||
* Sort aggregation operations.
|
||||
*/
|
||||
public enum Aggregate {
|
||||
enum Aggregate {
|
||||
SUM, MIN, MAX;
|
||||
}
|
||||
|
||||
/**
|
||||
* ZSet tuple.
|
||||
*/
|
||||
public interface Tuple extends Comparable<Double> {
|
||||
interface Tuple extends Comparable<Double> {
|
||||
|
||||
byte[] getValue();
|
||||
|
||||
@@ -55,7 +55,7 @@ public interface RedisZSetCommands {
|
||||
* @author Christoph Strobl
|
||||
* @since 1.6
|
||||
*/
|
||||
public class Range {
|
||||
class Range {
|
||||
|
||||
Boundary min;
|
||||
Boundary max;
|
||||
@@ -177,7 +177,7 @@ public interface RedisZSetCommands {
|
||||
* @author Christoph Strobl
|
||||
* @since 1.6
|
||||
*/
|
||||
public class Limit {
|
||||
class Limit {
|
||||
|
||||
int offset;
|
||||
int count;
|
||||
@@ -298,7 +298,9 @@ public interface RedisZSetCommands {
|
||||
* @return
|
||||
* @see <a href="http://redis.io/commands/zrangebyscore">Redis Documentation: ZRANGEBYSCORE</a>
|
||||
*/
|
||||
Set<byte[]> zRangeByScore(byte[] key, double min, double max);
|
||||
default Set<byte[]> zRangeByScore(byte[] key, double min, double max) {
|
||||
return zRangeByScore(key, new Range().gte(min).lte(max));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get set of {@link Tuple}s where score is between {@code Range#min} and {@code Range#max} from sorted set.
|
||||
@@ -309,7 +311,9 @@ public interface RedisZSetCommands {
|
||||
* @since 1.6
|
||||
* @see <a href="http://redis.io/commands/zrangebyscore">Redis Documentation: ZRANGEBYSCORE</a>
|
||||
*/
|
||||
Set<Tuple> zRangeByScoreWithScores(byte[] key, Range range);
|
||||
default Set<Tuple> zRangeByScoreWithScores(byte[] key, Range range) {
|
||||
return zRangeByScoreWithScores(key, range, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get set of {@link Tuple}s where score is between {@code min} and {@code max} from sorted set.
|
||||
@@ -320,7 +324,9 @@ public interface RedisZSetCommands {
|
||||
* @return
|
||||
* @see <a href="http://redis.io/commands/zrangebyscore">Redis Documentation: ZRANGEBYSCORE</a>
|
||||
*/
|
||||
Set<Tuple> zRangeByScoreWithScores(byte[] key, double min, double max);
|
||||
default Set<Tuple> zRangeByScoreWithScores(byte[] key, double min, double max) {
|
||||
return zRangeByScoreWithScores(key, new Range().gte(min).lte(max));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get elements in range from {@code start} to {@code end} where score is between {@code min} and {@code max} from
|
||||
@@ -334,7 +340,10 @@ public interface RedisZSetCommands {
|
||||
* @return
|
||||
* @see <a href="http://redis.io/commands/zrangebyscore">Redis Documentation: ZRANGEBYSCORE</a>
|
||||
*/
|
||||
Set<byte[]> zRangeByScore(byte[] key, double min, double max, long offset, long count);
|
||||
default Set<byte[]> zRangeByScore(byte[] key, double min, double max, long offset, long count) {
|
||||
return zRangeByScore(key, new Range().gte(min).lte(max),
|
||||
new Limit().offset(Long.valueOf(offset).intValue()).count(Long.valueOf(count).intValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get set of {@link Tuple}s in range from {@code start} to {@code end} where score is between {@code min} and
|
||||
@@ -348,7 +357,10 @@ public interface RedisZSetCommands {
|
||||
* @return
|
||||
* @see <a href="http://redis.io/commands/zrangebyscore">Redis Documentation: ZRANGEBYSCORE</a>
|
||||
*/
|
||||
Set<Tuple> zRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count);
|
||||
default Set<Tuple> zRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count) {
|
||||
return zRangeByScoreWithScores(key, new Range().gte(min).lte(max),
|
||||
new Limit().offset(Long.valueOf(offset).intValue()).count(Long.valueOf(count).intValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get set of {@link Tuple}s in range from {@code Limit#offset} to {@code Limit#offset + Limit#count} where score is
|
||||
@@ -394,7 +406,9 @@ public interface RedisZSetCommands {
|
||||
* @return
|
||||
* @see <a href="http://redis.io/commands/zrevrange">Redis Documentation: ZREVRANGE</a>
|
||||
*/
|
||||
Set<byte[]> zRevRangeByScore(byte[] key, double min, double max);
|
||||
default Set<byte[]> zRevRangeByScore(byte[] key, double min, double max) {
|
||||
return zRevRangeByScore(key, new Range().gte(min).lte(max));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get elements where score is between {@code Range#min} and {@code Range#max} from sorted set ordered from high to
|
||||
@@ -406,7 +420,9 @@ public interface RedisZSetCommands {
|
||||
* @since 1.6
|
||||
* @see <a href="http://redis.io/commands/zrevrangebyscore">Redis Documentation: ZREVRANGEBYSCORE</a>
|
||||
*/
|
||||
Set<byte[]> zRevRangeByScore(byte[] key, Range range);
|
||||
default Set<byte[]> zRevRangeByScore(byte[] key, Range range) {
|
||||
return zRevRangeByScore(key, range, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get set of {@link Tuple} where score is between {@code min} and {@code max} from sorted set ordered from high to
|
||||
@@ -418,7 +434,9 @@ public interface RedisZSetCommands {
|
||||
* @return
|
||||
* @see <a href="http://redis.io/commands/zrevrangebyscore">Redis Documentation: ZREVRANGEBYSCORE</a>
|
||||
*/
|
||||
Set<Tuple> zRevRangeByScoreWithScores(byte[] key, double min, double max);
|
||||
default Set<Tuple> zRevRangeByScoreWithScores(byte[] key, double min, double max) {
|
||||
return zRevRangeByScoreWithScores(key, new Range().gte(min).lte(max), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get elements in range from {@code start} to {@code end} where score is between {@code min} and {@code max} from
|
||||
@@ -432,7 +450,11 @@ public interface RedisZSetCommands {
|
||||
* @return
|
||||
* @see <a href="http://redis.io/commands/zrevrangebyscore">Redis Documentation: ZREVRANGEBYSCORE</a>
|
||||
*/
|
||||
Set<byte[]> zRevRangeByScore(byte[] key, double min, double max, long offset, long count);
|
||||
default Set<byte[]> zRevRangeByScore(byte[] key, double min, double max, long offset, long count) {
|
||||
|
||||
return zRevRangeByScore(key, new Range().gte(min).lte(max),
|
||||
new Limit().offset(Long.valueOf(offset).intValue()).count(Long.valueOf(count).intValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get elements in range from {@code Limit#offset} to {@code Limit#offset + Limit#count} where score is between
|
||||
@@ -459,7 +481,11 @@ public interface RedisZSetCommands {
|
||||
* @return
|
||||
* @see <a href="http://redis.io/commands/zrevrangebyscore">Redis Documentation: ZREVRANGEBYSCORE</a>
|
||||
*/
|
||||
Set<Tuple> zRevRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count);
|
||||
default Set<Tuple> zRevRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count) {
|
||||
|
||||
return zRevRangeByScoreWithScores(key, new Range().gte(min).lte(max),
|
||||
new Limit().offset(Long.valueOf(offset).intValue()).count(Long.valueOf(count).intValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get set of {@link Tuple} where score is between {@code Range#min} and {@code Range#max} from sorted set ordered
|
||||
@@ -471,7 +497,9 @@ public interface RedisZSetCommands {
|
||||
* @since 1.6
|
||||
* @see <a href="http://redis.io/commands/zrevrangebyscore">Redis Documentation: ZREVRANGEBYSCORE</a>
|
||||
*/
|
||||
Set<Tuple> zRevRangeByScoreWithScores(byte[] key, Range range);
|
||||
default Set<Tuple> zRevRangeByScoreWithScores(byte[] key, Range range) {
|
||||
return zRevRangeByScoreWithScores(key, range, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get set of {@link Tuple} in range from {@code Limit#offset} to {@code Limit#count} where score is between
|
||||
@@ -495,7 +523,9 @@ public interface RedisZSetCommands {
|
||||
* @return
|
||||
* @see <a href="http://redis.io/commands/zcount">Redis Documentation: ZCOUNT</a>
|
||||
*/
|
||||
Long zCount(byte[] key, double min, double max);
|
||||
default Long zCount(byte[] key, double min, double max) {
|
||||
return zCount(key, new Range().gte(min).lte(max));
|
||||
}
|
||||
|
||||
/**
|
||||
* Count number of elements within sorted set with scores between {@code Range#min} and {@code Range#max}.
|
||||
@@ -547,7 +577,9 @@ public interface RedisZSetCommands {
|
||||
* @return
|
||||
* @see <a href="http://redis.io/commands/zremrangebyscore">Redis Documentation: ZREMRANGEBYSCORE</a>
|
||||
*/
|
||||
Long zRemRangeByScore(byte[] key, double min, double max);
|
||||
default Long zRemRangeByScore(byte[] key, double min, double max) {
|
||||
return zRemRangeByScore(key, new Range().gte(min).lte(max));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove elements with scores between {@code Range#min} and {@code Range#max} from sorted set with {@code key}.
|
||||
@@ -625,7 +657,9 @@ public interface RedisZSetCommands {
|
||||
* @since 1.5
|
||||
* @see <a href="http://redis.io/commands/zrangebyscore">Redis Documentation: ZRANGEBYSCORE</a>
|
||||
*/
|
||||
Set<byte[]> zRangeByScore(byte[] key, String min, String max);
|
||||
default Set<byte[]> zRangeByScore(byte[] key, String min, String max) {
|
||||
return zRangeByScore(key, new Range().gte(min).lte(max));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get elements where score is between {@code Range#min} and {@code Range#max} from sorted set.
|
||||
@@ -636,7 +670,9 @@ public interface RedisZSetCommands {
|
||||
* @since 1.6
|
||||
* @see <a href="http://redis.io/commands/zrangebyscore">Redis Documentation: ZRANGEBYSCORE</a>
|
||||
*/
|
||||
Set<byte[]> zRangeByScore(byte[] key, Range range);
|
||||
default Set<byte[]> zRangeByScore(byte[] key, Range range) {
|
||||
return zRangeByScore(key, range, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get elements in range from {@code start} to {@code end} where score is between {@code min} and {@code max} from
|
||||
@@ -674,7 +710,9 @@ public interface RedisZSetCommands {
|
||||
* @since 1.6
|
||||
* @see <a href="http://redis.io/commands/zrangebylex">Redis Documentation: ZRANGEBYLEX</a>
|
||||
*/
|
||||
Set<byte[]> zRangeByLex(byte[] key);
|
||||
default Set<byte[]> zRangeByLex(byte[] key) {
|
||||
return zRangeByLex(key, Range.unbounded());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the elements in {@link Range} from the sorted set at {@literal key} in lexicographical ordering.
|
||||
@@ -685,7 +723,9 @@ public interface RedisZSetCommands {
|
||||
* @since 1.6
|
||||
* @see <a href="http://redis.io/commands/zrangebylex">Redis Documentation: ZRANGEBYLEX</a>
|
||||
*/
|
||||
Set<byte[]> zRangeByLex(byte[] key, Range range);
|
||||
default Set<byte[]> zRangeByLex(byte[] key, Range range) {
|
||||
return zRangeByLex(key, range, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the elements in {@link Range} from the sorted set at {@literal key} in lexicographical ordering. Result is
|
||||
|
||||
@@ -1502,7 +1502,7 @@ public interface StringRedisConnection extends RedisConnection {
|
||||
* @return
|
||||
* @since 1.5
|
||||
* @see <a href="http://redis.io/commands/pfadd">Redis Documentation: PFADD</a>
|
||||
* @see HyperLogLogCommands#pfAdd(byte[], byte[]...)
|
||||
* @see RedisHyperLogLogCommands#pfAdd(byte[], byte[]...)
|
||||
*/
|
||||
Long pfAdd(String key, String... values);
|
||||
|
||||
@@ -1512,7 +1512,7 @@ public interface StringRedisConnection extends RedisConnection {
|
||||
* @param keys must not be {@literal null}.
|
||||
* @return
|
||||
* @see <a href="http://redis.io/commands/pfcount">Redis Documentation: PFCOUNT</a>
|
||||
* @see HyperLogLogCommands#pfCount(byte[]...)
|
||||
* @see RedisHyperLogLogCommands#pfCount(byte[]...)
|
||||
*/
|
||||
Long pfCount(String... keys);
|
||||
|
||||
@@ -1522,7 +1522,7 @@ public interface StringRedisConnection extends RedisConnection {
|
||||
* @param destinationKey must not be {@literal null}.
|
||||
* @param sourceKeys must not be {@literal null}.
|
||||
* @see <a href="http://redis.io/commands/pfmerge">Redis Documentation: PFMERGE</a>
|
||||
* @see HyperLogLogCommands#pfMerge(byte[], byte[]...)
|
||||
* @see RedisHyperLogLogCommands#pfMerge(byte[], byte[]...)
|
||||
*/
|
||||
void pfMerge(String destinationKey, String... sourceKeys);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* 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.GeoCoordinate;
|
||||
import redis.clients.jedis.GeoUnit;
|
||||
import redis.clients.jedis.params.geo.GeoRadiusParam;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.geo.Circle;
|
||||
import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.GeoResults;
|
||||
import org.springframework.data.geo.Metric;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class JedisClusterGeoCommands implements RedisGeoCommands {
|
||||
|
||||
private final JedisClusterConnection connection;
|
||||
|
||||
public JedisClusterGeoCommands(JedisClusterConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoAdd(byte[], org.springframework.data.geo.Point, byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long geoAdd(byte[] key, Point point, byte[] member) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(point, "Point must not be null!");
|
||||
Assert.notNull(member, "Member must not be null!");
|
||||
|
||||
try {
|
||||
return connection.getCluster().geoadd(key, point.getX(), point.getY(), member);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoAdd(byte[], java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public Long geoAdd(byte[] key, Map<byte[], Point> memberCoordinateMap) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(memberCoordinateMap, "MemberCoordinateMap must not be null!");
|
||||
|
||||
Map<byte[], GeoCoordinate> redisGeoCoordinateMap = new HashMap<byte[], GeoCoordinate>();
|
||||
for (byte[] mapKey : memberCoordinateMap.keySet()) {
|
||||
redisGeoCoordinateMap.put(mapKey, JedisConverters.toGeoCoordinate(memberCoordinateMap.get(mapKey)));
|
||||
}
|
||||
|
||||
try {
|
||||
return connection.getCluster().geoadd(key, redisGeoCoordinateMap);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoAdd(byte[], java.lang.Iterable)
|
||||
*/
|
||||
@Override
|
||||
public Long geoAdd(byte[] key, Iterable<GeoLocation<byte[]>> locations) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(locations, "Locations must not be null!");
|
||||
|
||||
Map<byte[], redis.clients.jedis.GeoCoordinate> redisGeoCoordinateMap = new HashMap<byte[], GeoCoordinate>();
|
||||
for (GeoLocation<byte[]> location : locations) {
|
||||
redisGeoCoordinateMap.put(location.getName(), JedisConverters.toGeoCoordinate(location.getPoint()));
|
||||
}
|
||||
|
||||
try {
|
||||
return connection.getCluster().geoadd(key, redisGeoCoordinateMap);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoDist(byte[], byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Distance geoDist(byte[] key, byte[] member1, byte[] member2) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(member1, "Member1 must not be null!");
|
||||
Assert.notNull(member2, "Member2 must not be null!");
|
||||
|
||||
try {
|
||||
return JedisConverters.distanceConverterForMetric(DistanceUnit.METERS)
|
||||
.convert(connection.getCluster().geodist(key, member1, member2));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoDist(byte[], byte[], byte[], org.springframework.data.geo.Metric)
|
||||
*/
|
||||
@Override
|
||||
public Distance geoDist(byte[] key, byte[] member1, byte[] member2, Metric metric) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(member1, "Member1 must not be null!");
|
||||
Assert.notNull(member2, "Member2 must not be null!");
|
||||
Assert.notNull(metric, "Metric must not be null!");
|
||||
|
||||
GeoUnit geoUnit = JedisConverters.toGeoUnit(metric);
|
||||
try {
|
||||
return JedisConverters.distanceConverterForMetric(metric)
|
||||
.convert(connection.getCluster().geodist(key, member1, member2, geoUnit));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoHash(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<String> geoHash(byte[] key, byte[]... members) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(members, "Members must not be null!");
|
||||
Assert.noNullElements(members, "Members must not contain null!");
|
||||
|
||||
try {
|
||||
return JedisConverters.toStrings(connection.getCluster().geohash(key, members));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoPos(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<Point> geoPos(byte[] key, byte[]... members) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(members, "Members must not be null!");
|
||||
Assert.noNullElements(members, "Members must not contain null!");
|
||||
|
||||
try {
|
||||
return JedisConverters.geoCoordinateToPointConverter().convert(connection.getCluster().geopos(key, members));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoRadius(byte[], org.springframework.data.geo.Circle)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<byte[]>> geoRadius(byte[] key, Circle within) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(within, "Within must not be null!");
|
||||
|
||||
try {
|
||||
return JedisConverters.geoRadiusResponseToGeoResultsConverter(within.getRadius().getMetric())
|
||||
.convert(connection.getCluster().georadius(key, within.getCenter().getX(), within.getCenter().getY(),
|
||||
within.getRadius().getValue(), JedisConverters.toGeoUnit(within.getRadius().getMetric())));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoRadius(byte[], org.springframework.data.geo.Circle, org.springframework.data.redis.core.GeoRadiusCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<byte[]>> geoRadius(byte[] key, Circle within, GeoRadiusCommandArgs args) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(within, "Within must not be null!");
|
||||
Assert.notNull(args, "Args must not be null!");
|
||||
|
||||
GeoRadiusParam geoRadiusParam = JedisConverters.toGeoRadiusParam(args);
|
||||
|
||||
try {
|
||||
return JedisConverters.geoRadiusResponseToGeoResultsConverter(within.getRadius().getMetric())
|
||||
.convert(connection.getCluster().georadius(key, within.getCenter().getX(), within.getCenter().getY(),
|
||||
within.getRadius().getValue(), JedisConverters.toGeoUnit(within.getRadius().getMetric()),
|
||||
geoRadiusParam));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoRadiusByMember(byte[], byte[], org.springframework.data.geo.Distance)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<byte[]>> geoRadiusByMember(byte[] key, byte[] member, Distance radius) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(member, "Member must not be null!");
|
||||
Assert.notNull(radius, "Radius must not be null!");
|
||||
|
||||
GeoUnit geoUnit = JedisConverters.toGeoUnit(radius.getMetric());
|
||||
try {
|
||||
return JedisConverters.geoRadiusResponseToGeoResultsConverter(radius.getMetric())
|
||||
.convert(connection.getCluster().georadiusByMember(key, member, radius.getValue(), geoUnit));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoRadiusByMember(byte[], byte[], org.springframework.data.geo.Distance, org.springframework.data.redis.core.GeoRadiusCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<byte[]>> geoRadiusByMember(byte[] key, byte[] member, Distance radius,
|
||||
GeoRadiusCommandArgs args) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(member, "Member must not be null!");
|
||||
Assert.notNull(radius, "Radius must not be null!");
|
||||
Assert.notNull(args, "Args must not be null!");
|
||||
|
||||
GeoUnit geoUnit = JedisConverters.toGeoUnit(radius.getMetric());
|
||||
redis.clients.jedis.params.geo.GeoRadiusParam geoRadiusParam = JedisConverters.toGeoRadiusParam(args);
|
||||
|
||||
try {
|
||||
return JedisConverters.geoRadiusResponseToGeoResultsConverter(radius.getMetric())
|
||||
.convert(connection.getCluster().georadiusByMember(key, member, radius.getValue(), geoUnit, geoRadiusParam));
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoRemove(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long geoRemove(byte[] key, byte[]... members) {
|
||||
return connection.zRem(key, members);
|
||||
}
|
||||
|
||||
private DataAccessException convertJedisAccessException(Exception ex) {
|
||||
return connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* 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.ScanParams;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.connection.RedisHashCommands;
|
||||
import org.springframework.data.redis.core.Cursor;
|
||||
import org.springframework.data.redis.core.ScanCursor;
|
||||
import org.springframework.data.redis.core.ScanIteration;
|
||||
import org.springframework.data.redis.core.ScanOptions;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class JedisClusterHashCommands implements RedisHashCommands {
|
||||
|
||||
private final JedisClusterConnection connection;
|
||||
|
||||
public JedisClusterHashCommands(JedisClusterConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hSet(byte[], byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean hSet(byte[] key, byte[] field, byte[] value) {
|
||||
|
||||
try {
|
||||
return JedisConverters.toBoolean(connection.getCluster().hset(key, field, value));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hSetNX(byte[], byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean hSetNX(byte[] key, byte[] field, byte[] value) {
|
||||
|
||||
try {
|
||||
return JedisConverters.toBoolean(connection.getCluster().hsetnx(key, field, value));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hGet(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] hGet(byte[] key, byte[] field) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().hget(key, field);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hMGet(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> hMGet(byte[] key, byte[]... fields) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().hmget(key, fields);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hMSet(byte[], java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public void hMSet(byte[] key, Map<byte[], byte[]> hashes) {
|
||||
|
||||
try {
|
||||
connection.getCluster().hmset(key, hashes);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hIncrBy(byte[], byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public Long hIncrBy(byte[] key, byte[] field, long delta) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().hincrBy(key, field, delta);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hIncrBy(byte[], byte[], double)
|
||||
*/
|
||||
@Override
|
||||
public Double hIncrBy(byte[] key, byte[] field, double delta) {
|
||||
try {
|
||||
return connection.getCluster().hincrByFloat(key, field, delta);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hExists(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean hExists(byte[] key, byte[] field) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().hexists(key, field);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hDel(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long hDel(byte[] key, byte[]... fields) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().hdel(key, fields);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hLen(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long hLen(byte[] key) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().hlen(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hKeys(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> hKeys(byte[] key) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().hkeys(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hVals(byte[])
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> hVals(byte[] key) {
|
||||
|
||||
try {
|
||||
return new ArrayList<byte[]>(connection.getCluster().hvals(key));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hGetAll(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Map<byte[], byte[]> hGetAll(byte[] key) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().hgetAll(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hScan(byte[], org.springframework.data.redis.core.ScanOptions)
|
||||
*/
|
||||
@Override
|
||||
public Cursor<Entry<byte[], byte[]>> hScan(final byte[] key, ScanOptions options) {
|
||||
|
||||
return new ScanCursor<Entry<byte[], byte[]>>(options) {
|
||||
|
||||
@Override
|
||||
protected ScanIteration<Entry<byte[], byte[]>> doScan(long cursorId, ScanOptions options) {
|
||||
|
||||
ScanParams params = JedisConverters.toScanParams(options);
|
||||
|
||||
redis.clients.jedis.ScanResult<Map.Entry<byte[], byte[]>> result = connection.getCluster().hscan(key,
|
||||
JedisConverters.toBytes(cursorId), params);
|
||||
return new ScanIteration<>(Long.valueOf(result.getStringCursor()), result.getResult());
|
||||
}
|
||||
}.open();
|
||||
}
|
||||
|
||||
private DataAccessException convertJedisAccessException(Exception ex) {
|
||||
return connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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 org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.redis.connection.ClusterSlotHashUtil;
|
||||
import org.springframework.data.redis.connection.RedisHyperLogLogCommands;
|
||||
import org.springframework.data.redis.util.ByteUtils;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class JedisClusterHyperLogLogCommands implements RedisHyperLogLogCommands {
|
||||
|
||||
private final JedisClusterConnection connection;
|
||||
|
||||
public JedisClusterHyperLogLogCommands(JedisClusterConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHyperLogLogCommands#pfAdd(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long pfAdd(byte[] key, byte[]... values) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().pfadd(key, values);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHyperLogLogCommands#pfCount(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long pfCount(byte[]... keys) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().pfcount(keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
throw new InvalidDataAccessApiUsageException("All keys must map to same slot for pfcount in cluster mode.");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHyperLogLogCommands#pfMerge(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public void pfMerge(byte[] destinationKey, byte[]... sourceKeys) {
|
||||
|
||||
byte[][] allKeys = ByteUtils.mergeArrays(destinationKey, sourceKeys);
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(allKeys)) {
|
||||
try {
|
||||
connection.getCluster().pfmerge(destinationKey, sourceKeys);
|
||||
return;
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidDataAccessApiUsageException("All keys must map to same slot for pfmerge in cluster mode.");
|
||||
}
|
||||
|
||||
private DataAccessException convertJedisAccessException(Exception ex) {
|
||||
return connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,482 @@
|
||||
/*
|
||||
* 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.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.TimeUnit;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.redis.connection.ClusterSlotHashUtil;
|
||||
import org.springframework.data.redis.connection.DataType;
|
||||
import org.springframework.data.redis.connection.RedisClusterNode;
|
||||
import org.springframework.data.redis.connection.RedisKeyCommands;
|
||||
import org.springframework.data.redis.connection.RedisNode;
|
||||
import org.springframework.data.redis.connection.SortParameters;
|
||||
import org.springframework.data.redis.connection.convert.Converters;
|
||||
import org.springframework.data.redis.connection.jedis.JedisClusterConnection.JedisClusterCommandCallback;
|
||||
import org.springframework.data.redis.connection.jedis.JedisClusterConnection.JedisMultiKeyClusterCommandCallback;
|
||||
import org.springframework.data.redis.core.Cursor;
|
||||
import org.springframework.data.redis.core.ScanOptions;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class JedisClusterKeyCommands implements RedisKeyCommands {
|
||||
|
||||
private final JedisClusterConnection connection;
|
||||
|
||||
public JedisClusterKeyCommands(JedisClusterConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#del(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long del(byte[]... keys) {
|
||||
|
||||
Assert.noNullElements(keys, "Keys must not be null or contain null key!");
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
try {
|
||||
return connection.getCluster().del(keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return Long.valueOf(
|
||||
connection.getClusterCommandExecutor().executeMuliKeyCommand(new JedisMultiKeyClusterCommandCallback<Long>() {
|
||||
|
||||
@Override
|
||||
public Long doInCluster(Jedis client, byte[] key) {
|
||||
return client.del(key);
|
||||
}
|
||||
}, Arrays.asList(keys)).resultsAsList().size());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#type(byte[])
|
||||
*/
|
||||
@Override
|
||||
public DataType type(byte[] key) {
|
||||
|
||||
try {
|
||||
return JedisConverters.toDataType(connection.getCluster().type(key));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#keys(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> keys(final byte[] pattern) {
|
||||
|
||||
Assert.notNull(pattern, "Pattern must not be null!");
|
||||
|
||||
Collection<Set<byte[]>> keysPerNode = connection.getClusterCommandExecutor()
|
||||
.executeCommandOnAllNodes(new JedisClusterCommandCallback<Set<byte[]>>() {
|
||||
|
||||
@Override
|
||||
public Set<byte[]> doInCluster(Jedis client) {
|
||||
return client.keys(pattern);
|
||||
}
|
||||
}).resultsAsList();
|
||||
|
||||
Set<byte[]> keys = new HashSet<byte[]>();
|
||||
for (Set<byte[]> keySet : keysPerNode) {
|
||||
keys.addAll(keySet);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisClusterConnection#keys(org.springframework.data.redis.connection.RedisClusterNode, byte[])
|
||||
*/
|
||||
public Set<byte[]> keys(RedisClusterNode node, final byte[] pattern) {
|
||||
|
||||
Assert.notNull(pattern, "Pattern must not be null!");
|
||||
|
||||
return connection.getClusterCommandExecutor()
|
||||
.executeCommandOnSingleNode(new JedisClusterCommandCallback<Set<byte[]>>() {
|
||||
|
||||
@Override
|
||||
public Set<byte[]> doInCluster(Jedis client) {
|
||||
return client.keys(pattern);
|
||||
}
|
||||
}, node).getValue();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#scan(org.springframework.data.redis.core.ScanOptions)
|
||||
*/
|
||||
@Override
|
||||
public Cursor<byte[]> scan(ScanOptions options) {
|
||||
throw new InvalidDataAccessApiUsageException("Scan is not supported accros multiple nodes within a cluster");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#randomKey()
|
||||
*/
|
||||
@Override
|
||||
public byte[] randomKey() {
|
||||
|
||||
List<RedisClusterNode> nodes = new ArrayList<RedisClusterNode>(
|
||||
connection.getTopologyProvider().getTopology().getActiveMasterNodes());
|
||||
Set<RedisNode> inspectedNodes = new HashSet<RedisNode>(nodes.size());
|
||||
|
||||
do {
|
||||
|
||||
RedisClusterNode node = nodes.get(new Random().nextInt(nodes.size()));
|
||||
|
||||
while (inspectedNodes.contains(node)) {
|
||||
node = nodes.get(new Random().nextInt(nodes.size()));
|
||||
}
|
||||
inspectedNodes.add(node);
|
||||
byte[] key = randomKey(node);
|
||||
|
||||
if (key != null && key.length > 0) {
|
||||
return key;
|
||||
}
|
||||
} while (nodes.size() != inspectedNodes.size());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisClusterConnection#randomKey(org.springframework.data.redis.connection.RedisClusterNode)
|
||||
*/
|
||||
public byte[] randomKey(RedisClusterNode node) {
|
||||
|
||||
return connection.getClusterCommandExecutor().executeCommandOnSingleNode(new JedisClusterCommandCallback<byte[]>() {
|
||||
|
||||
@Override
|
||||
public byte[] doInCluster(Jedis client) {
|
||||
return client.randomBinaryKey();
|
||||
}
|
||||
}, node).getValue();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#rename(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public void rename(final byte[] sourceKey, final byte[] targetKey) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(sourceKey, targetKey)) {
|
||||
|
||||
try {
|
||||
connection.getCluster().rename(sourceKey, targetKey);
|
||||
return;
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
byte[] value = dump(sourceKey);
|
||||
|
||||
if (value != null && value.length > 0) {
|
||||
|
||||
restore(targetKey, 0, value);
|
||||
del(sourceKey);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#renameNX(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean renameNX(final byte[] sourceKey, final byte[] targetKey) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(sourceKey, targetKey)) {
|
||||
|
||||
try {
|
||||
return JedisConverters.toBoolean(connection.getCluster().renamenx(sourceKey, targetKey));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
byte[] value = dump(sourceKey);
|
||||
|
||||
if (value != null && value.length > 0 && !exists(targetKey)) {
|
||||
|
||||
restore(targetKey, 0, value);
|
||||
del(sourceKey);
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#expire(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public Boolean expire(byte[] key, long seconds) {
|
||||
|
||||
if (seconds > Integer.MAX_VALUE) {
|
||||
throw new UnsupportedOperationException("Jedis does not support seconds exceeding Integer.MAX_VALUE.");
|
||||
}
|
||||
try {
|
||||
return JedisConverters.toBoolean(connection.getCluster().expire(key, Long.valueOf(seconds).intValue()));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#pExpire(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public Boolean pExpire(final byte[] key, final long millis) {
|
||||
|
||||
try {
|
||||
return JedisConverters.toBoolean(connection.getCluster().pexpire(key, millis));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#expireAt(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public Boolean expireAt(byte[] key, long unixTime) {
|
||||
|
||||
try {
|
||||
return JedisConverters.toBoolean(connection.getCluster().expireAt(key, unixTime));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#pExpireAt(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public Boolean pExpireAt(byte[] key, long unixTimeInMillis) {
|
||||
|
||||
try {
|
||||
return JedisConverters.toBoolean(connection.getCluster().pexpireAt(key, unixTimeInMillis));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#persist(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean persist(byte[] key) {
|
||||
|
||||
try {
|
||||
return JedisConverters.toBoolean(connection.getCluster().persist(key));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#move(byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public Boolean move(byte[] key, int dbIndex) {
|
||||
throw new UnsupportedOperationException("Cluster mode does not allow moving keys.");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#ttl(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long ttl(byte[] key) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().ttl(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#ttl(byte[], java.util.concurrent.TimeUnit)
|
||||
*/
|
||||
@Override
|
||||
public Long ttl(byte[] key, TimeUnit timeUnit) {
|
||||
|
||||
try {
|
||||
return Converters.secondsToTimeUnit(connection.getCluster().ttl(key), timeUnit);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#pTtl(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long pTtl(final byte[] key) {
|
||||
|
||||
return connection.getClusterCommandExecutor().executeCommandOnSingleNode(new JedisClusterCommandCallback<Long>() {
|
||||
|
||||
@Override
|
||||
public Long doInCluster(Jedis client) {
|
||||
return client.pttl(key);
|
||||
}
|
||||
}, connection.getTopologyProvider().getTopology().getKeyServingMasterNode(key)).getValue();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#pTtl(byte[], java.util.concurrent.TimeUnit)
|
||||
*/
|
||||
@Override
|
||||
public Long pTtl(final byte[] key, final TimeUnit timeUnit) {
|
||||
|
||||
return connection.getClusterCommandExecutor().executeCommandOnSingleNode(new JedisClusterCommandCallback<Long>() {
|
||||
|
||||
@Override
|
||||
public Long doInCluster(Jedis client) {
|
||||
return Converters.millisecondsToTimeUnit(client.pttl(key), timeUnit);
|
||||
}
|
||||
}, connection.getTopologyProvider().getTopology().getKeyServingMasterNode(key)).getValue();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#dump(byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] dump(final byte[] key) {
|
||||
|
||||
return connection.getClusterCommandExecutor().executeCommandOnSingleNode(new JedisClusterCommandCallback<byte[]>() {
|
||||
|
||||
@Override
|
||||
public byte[] doInCluster(Jedis client) {
|
||||
return client.dump(key);
|
||||
}
|
||||
}, connection.getTopologyProvider().getTopology().getKeyServingMasterNode(key)).getValue();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#restore(byte[], long, byte[])
|
||||
*/
|
||||
@Override
|
||||
public void restore(final byte[] key, final long ttlInMillis, final byte[] serializedValue) {
|
||||
|
||||
if (ttlInMillis > Integer.MAX_VALUE) {
|
||||
throw new UnsupportedOperationException("Jedis does not support ttlInMillis exceeding Integer.MAX_VALUE.");
|
||||
}
|
||||
|
||||
connection.getClusterCommandExecutor().executeCommandOnSingleNode(new JedisClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(Jedis client) {
|
||||
return client.restore(key, Long.valueOf(ttlInMillis).intValue(), serializedValue);
|
||||
}
|
||||
}, connection.clusterGetNodeForKey(key));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#sort(byte[], org.springframework.data.redis.connection.SortParameters)
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> sort(byte[] key, SortParameters params) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().sort(key, JedisConverters.toSortingParams(params));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#sort(byte[], org.springframework.data.redis.connection.SortParameters, byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long sort(byte[] key, SortParameters params, byte[] storeKey) {
|
||||
|
||||
List<byte[]> sorted = sort(key, params);
|
||||
if (!CollectionUtils.isEmpty(sorted)) {
|
||||
|
||||
byte[][] arr = new byte[sorted.size()][];
|
||||
switch (type(key)) {
|
||||
|
||||
case SET:
|
||||
connection.setCommands().sAdd(storeKey, sorted.toArray(arr));
|
||||
return 1L;
|
||||
case LIST:
|
||||
connection.listCommands().lPush(storeKey, sorted.toArray(arr));
|
||||
return 1L;
|
||||
default:
|
||||
throw new IllegalArgumentException("sort and store is only supported for SET and LIST");
|
||||
}
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#exists(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean exists(final byte[] key) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().exists(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private DataAccessException convertJedisAccessException(Exception ex) {
|
||||
return connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
* 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.Jedis;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.connection.ClusterSlotHashUtil;
|
||||
import org.springframework.data.redis.connection.RedisListCommands;
|
||||
import org.springframework.data.redis.connection.jedis.JedisClusterConnection.JedisMultiKeyClusterCommandCallback;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class JedisClusterListCommands implements RedisListCommands {
|
||||
|
||||
private final JedisClusterConnection connection;
|
||||
|
||||
public JedisClusterListCommands(JedisClusterConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#rPush(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long rPush(byte[] key, byte[]... values) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().rpush(key, values);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lPush(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long lPush(byte[] key, byte[]... values) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().lpush(key, values);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#rPushX(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long rPushX(byte[] key, byte[] value) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().rpushx(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lPushX(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long lPushX(byte[] key, byte[] value) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().lpushx(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lLen(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long lLen(byte[] key) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().llen(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lRange(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> lRange(byte[] key, long begin, long end) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().lrange(key, begin, end);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lTrim(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public void lTrim(final byte[] key, final long begin, final long end) {
|
||||
|
||||
try {
|
||||
connection.getCluster().ltrim(key, begin, end);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lIndex(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public byte[] lIndex(byte[] key, long index) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().lindex(key, index);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lInsert(byte[], org.springframework.data.redis.connection.RedisListCommands.Position, byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long lInsert(byte[] key, Position where, byte[] pivot, byte[] value) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().linsert(key, JedisConverters.toListPosition(where), pivot, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lSet(byte[], long, byte[])
|
||||
*/
|
||||
@Override
|
||||
public void lSet(byte[] key, long index, byte[] value) {
|
||||
|
||||
try {
|
||||
connection.getCluster().lset(key, index, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lRem(byte[], long, byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long lRem(byte[] key, long count, byte[] value) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().lrem(key, count, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lPop(byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] lPop(byte[] key) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().lpop(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#rPop(byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] rPop(byte[] key) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().rpop(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#bLPop(int, byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> bLPop(final int timeout, final byte[]... keys) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
try {
|
||||
return connection.getCluster().blpop(timeout, keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return connection.getClusterCommandExecutor()
|
||||
.executeMuliKeyCommand(new JedisMultiKeyClusterCommandCallback<List<byte[]>>() {
|
||||
|
||||
@Override
|
||||
public List<byte[]> doInCluster(Jedis client, byte[] key) {
|
||||
return client.blpop(timeout, key);
|
||||
}
|
||||
}, Arrays.asList(keys)).getFirstNonNullNotEmptyOrDefault(Collections.<byte[]> emptyList());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#bRPop(int, byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> bRPop(final int timeout, byte[]... keys) {
|
||||
|
||||
return connection.getClusterCommandExecutor()
|
||||
.executeMuliKeyCommand(new JedisMultiKeyClusterCommandCallback<List<byte[]>>() {
|
||||
|
||||
@Override
|
||||
public List<byte[]> doInCluster(Jedis client, byte[] key) {
|
||||
return client.brpop(timeout, key);
|
||||
}
|
||||
}, Arrays.asList(keys)).getFirstNonNullNotEmptyOrDefault(Collections.<byte[]> emptyList());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#rPopLPush(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] rPopLPush(byte[] srcKey, byte[] dstKey) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(srcKey, dstKey)) {
|
||||
try {
|
||||
return connection.getCluster().rpoplpush(srcKey, dstKey);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
byte[] val = rPop(srcKey);
|
||||
lPush(dstKey, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#bRPopLPush(int, byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] bRPopLPush(int timeout, byte[] srcKey, byte[] dstKey) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(srcKey, dstKey)) {
|
||||
try {
|
||||
return connection.getCluster().brpoplpush(srcKey, dstKey, timeout);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
List<byte[]> val = bRPop(timeout, srcKey);
|
||||
if (!CollectionUtils.isEmpty(val)) {
|
||||
lPush(dstKey, val.get(1));
|
||||
return val.get(1);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private DataAccessException convertJedisAccessException(Exception ex) {
|
||||
return connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,393 @@
|
||||
/*
|
||||
* 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.ScanParams;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.connection.ClusterSlotHashUtil;
|
||||
import org.springframework.data.redis.connection.RedisSetCommands;
|
||||
import org.springframework.data.redis.connection.jedis.JedisClusterConnection.JedisMultiKeyClusterCommandCallback;
|
||||
import org.springframework.data.redis.connection.util.ByteArraySet;
|
||||
import org.springframework.data.redis.core.Cursor;
|
||||
import org.springframework.data.redis.core.ScanCursor;
|
||||
import org.springframework.data.redis.core.ScanIteration;
|
||||
import org.springframework.data.redis.core.ScanOptions;
|
||||
import org.springframework.data.redis.util.ByteUtils;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class JedisClusterSetCommands implements RedisSetCommands {
|
||||
|
||||
private final JedisClusterConnection connection;
|
||||
|
||||
public JedisClusterSetCommands(JedisClusterConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sAdd(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sAdd(byte[] key, byte[]... values) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().sadd(key, values);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sRem(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sRem(byte[] key, byte[]... values) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().srem(key, values);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sPop(byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] sPop(byte[] key) {
|
||||
try {
|
||||
return connection.getCluster().spop(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sMove(byte[], byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean sMove(byte[] srcKey, byte[] destKey, byte[] value) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(srcKey, destKey)) {
|
||||
try {
|
||||
return JedisConverters.toBoolean(connection.getCluster().smove(srcKey, destKey, value));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (connection.keyCommands().exists(srcKey)) {
|
||||
if (sRem(srcKey, value) > 0 && !sIsMember(destKey, value)) {
|
||||
return JedisConverters.toBoolean(sAdd(destKey, value));
|
||||
}
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sCard(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long sCard(byte[] key) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().scard(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sIsMember(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean sIsMember(byte[] key, byte[] value) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().sismember(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sInter(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> sInter(byte[]... keys) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
try {
|
||||
return connection.getCluster().sinter(keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
Collection<Set<byte[]>> resultList = connection.getClusterCommandExecutor()
|
||||
.executeMuliKeyCommand((JedisMultiKeyClusterCommandCallback<Set<byte[]>>) (client, key) -> client.smembers(key),
|
||||
Arrays.asList(keys))
|
||||
.resultsAsList();
|
||||
|
||||
ByteArraySet result = null;
|
||||
|
||||
for (Set<byte[]> value : resultList) {
|
||||
|
||||
ByteArraySet tmp = new ByteArraySet(value);
|
||||
if (result == null) {
|
||||
result = tmp;
|
||||
} else {
|
||||
result.retainAll(tmp);
|
||||
if (result.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
return result.asRawSet();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sInterStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sInterStore(byte[] destKey, byte[]... keys) {
|
||||
|
||||
byte[][] allKeys = ByteUtils.mergeArrays(destKey, keys);
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(allKeys)) {
|
||||
try {
|
||||
return connection.getCluster().sinterstore(destKey, keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
Set<byte[]> result = sInter(keys);
|
||||
if (result.isEmpty()) {
|
||||
return 0L;
|
||||
}
|
||||
return sAdd(destKey, result.toArray(new byte[result.size()][]));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sUnion(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> sUnion(byte[]... keys) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
try {
|
||||
return connection.getCluster().sunion(keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
Collection<Set<byte[]>> resultList = connection.getClusterCommandExecutor()
|
||||
.executeMuliKeyCommand((JedisMultiKeyClusterCommandCallback<Set<byte[]>>) (client, key) -> client.smembers(key),
|
||||
Arrays.asList(keys))
|
||||
.resultsAsList();
|
||||
|
||||
ByteArraySet result = new ByteArraySet();
|
||||
for (Set<byte[]> entry : resultList) {
|
||||
result.addAll(entry);
|
||||
}
|
||||
|
||||
if (result.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
return result.asRawSet();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sUnionStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sUnionStore(byte[] destKey, byte[]... keys) {
|
||||
|
||||
byte[][] allKeys = ByteUtils.mergeArrays(destKey, keys);
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(allKeys)) {
|
||||
try {
|
||||
return connection.getCluster().sunionstore(destKey, keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
Set<byte[]> result = sUnion(keys);
|
||||
if (result.isEmpty()) {
|
||||
return 0L;
|
||||
}
|
||||
return sAdd(destKey, result.toArray(new byte[result.size()][]));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sDiff(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> sDiff(byte[]... keys) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
try {
|
||||
return connection.getCluster().sdiff(keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
byte[] source = keys[0];
|
||||
byte[][] others = Arrays.copyOfRange(keys, 1, keys.length - 1);
|
||||
|
||||
ByteArraySet values = new ByteArraySet(sMembers(source));
|
||||
Collection<Set<byte[]>> resultList = connection.getClusterCommandExecutor()
|
||||
.executeMuliKeyCommand((JedisMultiKeyClusterCommandCallback<Set<byte[]>>) (client, key) -> client.smembers(key),
|
||||
Arrays.asList(others))
|
||||
.resultsAsList();
|
||||
|
||||
if (values.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
for (Set<byte[]> singleNodeValue : resultList) {
|
||||
values.removeAll(singleNodeValue);
|
||||
}
|
||||
|
||||
return values.asRawSet();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sDiffStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sDiffStore(byte[] destKey, byte[]... keys) {
|
||||
|
||||
byte[][] allKeys = ByteUtils.mergeArrays(destKey, keys);
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(allKeys)) {
|
||||
try {
|
||||
return connection.getCluster().sdiffstore(destKey, keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
Set<byte[]> diff = sDiff(keys);
|
||||
if (diff.isEmpty()) {
|
||||
return 0L;
|
||||
}
|
||||
|
||||
return sAdd(destKey, diff.toArray(new byte[diff.size()][]));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sMembers(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> sMembers(byte[] key) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().smembers(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sRandMember(byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] sRandMember(byte[] key) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().srandmember(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sRandMember(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> sRandMember(byte[] key, long count) {
|
||||
|
||||
if (count > Integer.MAX_VALUE) {
|
||||
throw new IllegalArgumentException("Count cannot exceed Integer.MAX_VALUE!");
|
||||
}
|
||||
|
||||
try {
|
||||
return connection.getCluster().srandmember(key, Long.valueOf(count).intValue());
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sScan(byte[], org.springframework.data.redis.core.ScanOptions)
|
||||
*/
|
||||
@Override
|
||||
public Cursor<byte[]> sScan(final byte[] key, ScanOptions options) {
|
||||
|
||||
return new ScanCursor<byte[]>(options) {
|
||||
|
||||
@Override
|
||||
protected ScanIteration<byte[]> doScan(long cursorId, ScanOptions options) {
|
||||
|
||||
ScanParams params = JedisConverters.toScanParams(options);
|
||||
redis.clients.jedis.ScanResult<byte[]> result = connection.getCluster().sscan(key,
|
||||
JedisConverters.toBytes(cursorId), params);
|
||||
return new ScanIteration<>(Long.valueOf(result.getStringCursor()), result.getResult());
|
||||
}
|
||||
}.open();
|
||||
}
|
||||
|
||||
private DataAccessException convertJedisAccessException(Exception ex) {
|
||||
return connection.convertJedisAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,463 @@
|
||||
/*
|
||||
* 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.Jedis;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.redis.connection.ClusterSlotHashUtil;
|
||||
import org.springframework.data.redis.connection.RedisStringCommands;
|
||||
import org.springframework.data.redis.connection.jedis.JedisClusterConnection.JedisClusterCommandCallback;
|
||||
import org.springframework.data.redis.connection.jedis.JedisClusterConnection.JedisMultiKeyClusterCommandCallback;
|
||||
import org.springframework.data.redis.core.types.Expiration;
|
||||
import org.springframework.data.redis.util.ByteUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class JedisClusterStringCommands implements RedisStringCommands {
|
||||
|
||||
private final JedisClusterConnection connection;
|
||||
|
||||
public JedisClusterStringCommands(JedisClusterConnection jedisClusterConnection) {
|
||||
this.connection = jedisClusterConnection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#get(byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] get(byte[] key) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().get(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#getSet(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] getSet(byte[] key, byte[] value) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().getSet(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#mGet(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> mGet(byte[]... keys) {
|
||||
|
||||
Assert.noNullElements(keys, "Keys must not contain null elements!");
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
return connection.getCluster().mget(keys);
|
||||
}
|
||||
|
||||
return connection.getClusterCommandExecutor()
|
||||
.executeMuliKeyCommand(new JedisMultiKeyClusterCommandCallback<byte[]>() {
|
||||
|
||||
@Override
|
||||
public byte[] doInCluster(Jedis client, byte[] key) {
|
||||
return client.get(key);
|
||||
}
|
||||
}, Arrays.asList(keys)).resultsAsListSortBy(keys);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#set(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public void set(byte[] key, byte[] value) {
|
||||
|
||||
try {
|
||||
connection.getCluster().set(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#set(byte[], byte[], org.springframework.data.redis.core.types.Expiration, org.springframework.data.redis.connection.RedisStringCommands.SetOptions)
|
||||
*/
|
||||
@Override
|
||||
public void set(byte[] key, byte[] value, Expiration expiration, SetOption option) {
|
||||
|
||||
if (expiration == null || expiration.isPersistent()) {
|
||||
|
||||
if (option == null || ObjectUtils.nullSafeEquals(SetOption.UPSERT, option)) {
|
||||
set(key, value);
|
||||
} else {
|
||||
|
||||
// BinaryCluster does not support set with nxxx and binary key/value pairs.
|
||||
if (ObjectUtils.nullSafeEquals(SetOption.SET_IF_PRESENT, option)) {
|
||||
throw new UnsupportedOperationException("Jedis does not support SET XX without PX or EX on BinaryCluster.");
|
||||
}
|
||||
|
||||
setNX(key, value);
|
||||
}
|
||||
} else {
|
||||
|
||||
if (option == null || ObjectUtils.nullSafeEquals(SetOption.UPSERT, option)) {
|
||||
|
||||
if (ObjectUtils.nullSafeEquals(TimeUnit.MILLISECONDS, expiration.getTimeUnit())) {
|
||||
pSetEx(key, expiration.getExpirationTime(), value);
|
||||
} else {
|
||||
setEx(key, expiration.getExpirationTime(), value);
|
||||
}
|
||||
} else {
|
||||
|
||||
byte[] nxxx = JedisConverters.toSetCommandNxXxArgument(option);
|
||||
byte[] expx = JedisConverters.toSetCommandExPxArgument(expiration);
|
||||
|
||||
try {
|
||||
connection.getCluster().set(key, value, nxxx, expx, expiration.getExpirationTime());
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#setNX(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean setNX(byte[] key, byte[] value) {
|
||||
|
||||
try {
|
||||
return JedisConverters.toBoolean(connection.getCluster().setnx(key, value));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#setEx(byte[], long, byte[])
|
||||
*/
|
||||
@Override
|
||||
public void setEx(byte[] key, long seconds, byte[] value) {
|
||||
|
||||
if (seconds > Integer.MAX_VALUE) {
|
||||
throw new IllegalArgumentException("Seconds have cannot exceed Integer.MAX_VALUE!");
|
||||
}
|
||||
|
||||
try {
|
||||
connection.getCluster().setex(key, Long.valueOf(seconds).intValue(), value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#pSetEx(byte[], long, byte[])
|
||||
*/
|
||||
@Override
|
||||
public void pSetEx(final byte[] key, final long milliseconds, final byte[] value) {
|
||||
|
||||
if (milliseconds > Integer.MAX_VALUE) {
|
||||
throw new IllegalArgumentException("Milliseconds have cannot exceed Integer.MAX_VALUE!");
|
||||
}
|
||||
|
||||
connection.getClusterCommandExecutor().executeCommandOnSingleNode(new JedisClusterCommandCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInCluster(Jedis client) {
|
||||
return client.psetex(key, milliseconds, value);
|
||||
}
|
||||
}, connection.getTopologyProvider().getTopology().getKeyServingMasterNode(key));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#mSet(java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public void mSet(Map<byte[], byte[]> tuples) {
|
||||
|
||||
Assert.notNull(tuples, "Tuples must not be null!");
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(tuples.keySet().toArray(new byte[tuples.keySet().size()][]))) {
|
||||
try {
|
||||
connection.getCluster().mset(JedisConverters.toByteArrays(tuples));
|
||||
return;
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<byte[], byte[]> entry : tuples.entrySet()) {
|
||||
set(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#mSetNX(java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public Boolean mSetNX(Map<byte[], byte[]> tuples) {
|
||||
|
||||
Assert.notNull(tuples, "Tuple must not be null!");
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(tuples.keySet().toArray(new byte[tuples.keySet().size()][]))) {
|
||||
try {
|
||||
return JedisConverters.toBoolean(connection.getCluster().msetnx(JedisConverters.toByteArrays(tuples)));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
boolean result = true;
|
||||
for (Map.Entry<byte[], byte[]> entry : tuples.entrySet()) {
|
||||
if (!setNX(entry.getKey(), entry.getValue()) && result) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#incr(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long incr(byte[] key) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().incr(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#incrBy(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public Long incrBy(byte[] key, long value) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().incrBy(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#incrBy(byte[], double)
|
||||
*/
|
||||
@Override
|
||||
public Double incrBy(byte[] key, double value) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().incrByFloat(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#decr(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long decr(byte[] key) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().decr(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#decrBy(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public Long decrBy(byte[] key, long value) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().decrBy(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#append(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long append(byte[] key, byte[] value) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().append(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#getRange(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public byte[] getRange(byte[] key, long begin, long end) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().getrange(key, begin, end);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#setRange(byte[], byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public void setRange(byte[] key, byte[] value, long offset) {
|
||||
|
||||
try {
|
||||
connection.getCluster().setrange(key, offset, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#getBit(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public Boolean getBit(byte[] key, long offset) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().getbit(key, offset);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#setBit(byte[], long, boolean)
|
||||
*/
|
||||
@Override
|
||||
public Boolean setBit(byte[] key, long offset, boolean value) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().setbit(key, offset, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#bitCount(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long bitCount(byte[] key) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().bitcount(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#bitCount(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public Long bitCount(byte[] key, long begin, long end) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().bitcount(key, begin, end);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#bitOp(org.springframework.data.redis.connection.RedisStringCommands.BitOperation, byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long bitOp(BitOperation op, byte[] destination, byte[]... keys) {
|
||||
|
||||
byte[][] allKeys = ByteUtils.mergeArrays(destination, keys);
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(allKeys)) {
|
||||
try {
|
||||
return connection.getCluster().bitop(JedisConverters.toBitOp(op), destination, keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidDataAccessApiUsageException("BITOP is only supported for same slot keys in cluster mode.");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#strLen(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long strLen(byte[] key) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().strlen(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private DataAccessException convertJedisAccessException(Exception ex) {
|
||||
return connection.convertJedisAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,681 @@
|
||||
/*
|
||||
* 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.ScanParams;
|
||||
import redis.clients.jedis.ZParams;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.redis.connection.ClusterSlotHashUtil;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands;
|
||||
import org.springframework.data.redis.core.Cursor;
|
||||
import org.springframework.data.redis.core.ScanCursor;
|
||||
import org.springframework.data.redis.core.ScanIteration;
|
||||
import org.springframework.data.redis.core.ScanOptions;
|
||||
import org.springframework.data.redis.util.ByteUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class JedisClusterZSetCommands implements RedisZSetCommands {
|
||||
|
||||
private final JedisClusterConnection connection;
|
||||
|
||||
public JedisClusterZSetCommands(JedisClusterConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], double, byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean zAdd(byte[] key, double score, byte[] value) {
|
||||
|
||||
try {
|
||||
return JedisConverters.toBoolean(connection.getCluster().zadd(key, score, value));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], java.util.Set)
|
||||
*/
|
||||
@Override
|
||||
public Long zAdd(byte[] key, Set<Tuple> tuples) {
|
||||
|
||||
// TODO: need to move the tuple conversion form jedisconnection.
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRem(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long zRem(byte[] key, byte[]... values) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().zrem(key, values);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zIncrBy(byte[], double, byte[])
|
||||
*/
|
||||
@Override
|
||||
public Double zIncrBy(byte[] key, double increment, byte[] value) {
|
||||
try {
|
||||
return connection.getCluster().zincrby(key, increment, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRank(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long zRank(byte[] key, byte[] value) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().zrank(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRank(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long zRevRank(byte[] key, byte[] value) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().zrevrank(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRange(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRange(byte[] key, long begin, long end) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().zrange(key, begin, end);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByScoreWithScores(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)
|
||||
*/
|
||||
@Override
|
||||
public Set<Tuple> zRangeByScoreWithScores(byte[] key, Range range, Limit limit) {
|
||||
|
||||
Assert.notNull(range, "Range cannot be null for ZRANGEBYSCOREWITHSCORES.");
|
||||
|
||||
byte[] min = JedisConverters.boundaryToBytesForZRange(range.getMin(), JedisConverters.NEGATIVE_INFINITY_BYTES);
|
||||
byte[] max = JedisConverters.boundaryToBytesForZRange(range.getMax(), JedisConverters.POSITIVE_INFINITY_BYTES);
|
||||
|
||||
try {
|
||||
if (limit != null) {
|
||||
return JedisConverters.toTupleSet(
|
||||
connection.getCluster().zrangeByScoreWithScores(key, min, max, limit.getOffset(), limit.getCount()));
|
||||
}
|
||||
return JedisConverters.toTupleSet(connection.getCluster().zrangeByScoreWithScores(key, min, max));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRangeByScore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRevRangeByScore(byte[] key, Range range, Limit limit) {
|
||||
|
||||
Assert.notNull(range, "Range cannot be null for ZREVRANGEBYSCORE.");
|
||||
byte[] min = JedisConverters.boundaryToBytesForZRange(range.getMin(), JedisConverters.NEGATIVE_INFINITY_BYTES);
|
||||
byte[] max = JedisConverters.boundaryToBytesForZRange(range.getMax(), JedisConverters.POSITIVE_INFINITY_BYTES);
|
||||
|
||||
try {
|
||||
if (limit != null) {
|
||||
return connection.getCluster().zrevrangeByScore(key, max, min, limit.getOffset(), limit.getCount());
|
||||
}
|
||||
return connection.getCluster().zrevrangeByScore(key, max, min);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRangeByScoreWithScores(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)
|
||||
*/
|
||||
@Override
|
||||
public Set<Tuple> zRevRangeByScoreWithScores(byte[] key, Range range, Limit limit) {
|
||||
|
||||
Assert.notNull(range, "Range cannot be null for ZREVRANGEBYSCOREWITHSCORES.");
|
||||
|
||||
byte[] min = JedisConverters.boundaryToBytesForZRange(range.getMin(), JedisConverters.NEGATIVE_INFINITY_BYTES);
|
||||
byte[] max = JedisConverters.boundaryToBytesForZRange(range.getMax(), JedisConverters.POSITIVE_INFINITY_BYTES);
|
||||
|
||||
try {
|
||||
if (limit != null) {
|
||||
return JedisConverters.toTupleSet(
|
||||
connection.getCluster().zrevrangeByScoreWithScores(key, max, min, limit.getOffset(), limit.getCount()));
|
||||
}
|
||||
return JedisConverters.toTupleSet(connection.getCluster().zrevrangeByScoreWithScores(key, max, min));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zCount(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
|
||||
*/
|
||||
@Override
|
||||
public Long zCount(byte[] key, Range range) {
|
||||
|
||||
Assert.notNull(range, "Range cannot be null for ZCOUNT.");
|
||||
|
||||
byte[] min = JedisConverters.boundaryToBytesForZRange(range.getMin(), JedisConverters.NEGATIVE_INFINITY_BYTES);
|
||||
byte[] max = JedisConverters.boundaryToBytesForZRange(range.getMax(), JedisConverters.POSITIVE_INFINITY_BYTES);
|
||||
|
||||
try {
|
||||
return connection.getCluster().zcount(key, min, max);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRangeByScore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
|
||||
*/
|
||||
@Override
|
||||
public Long zRemRangeByScore(byte[] key, Range range) {
|
||||
|
||||
Assert.notNull(range, "Range cannot be null for ZREMRANGEBYSCORE.");
|
||||
|
||||
byte[] min = JedisConverters.boundaryToBytesForZRange(range.getMin(), JedisConverters.NEGATIVE_INFINITY_BYTES);
|
||||
byte[] max = JedisConverters.boundaryToBytesForZRange(range.getMax(), JedisConverters.POSITIVE_INFINITY_BYTES);
|
||||
|
||||
try {
|
||||
return connection.getCluster().zremrangeByScore(key, min, max);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByScore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRangeByScore(byte[] key, Range range, Limit limit) {
|
||||
|
||||
Assert.notNull(range, "Range cannot be null for ZRANGEBYSCORE.");
|
||||
|
||||
byte[] min = JedisConverters.boundaryToBytesForZRange(range.getMin(), JedisConverters.NEGATIVE_INFINITY_BYTES);
|
||||
byte[] max = JedisConverters.boundaryToBytesForZRange(range.getMax(), JedisConverters.POSITIVE_INFINITY_BYTES);
|
||||
|
||||
try {
|
||||
if (limit != null) {
|
||||
return connection.getCluster().zrangeByScore(key, min, max, limit.getOffset(), limit.getCount());
|
||||
}
|
||||
return connection.getCluster().zrangeByScore(key, min, max);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByLex(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRangeByLex(byte[] key, Range range, Limit limit) {
|
||||
|
||||
Assert.notNull(range, "Range cannot be null for ZRANGEBYLEX.");
|
||||
|
||||
byte[] min = JedisConverters.boundaryToBytesForZRangeByLex(range.getMin(), JedisConverters.toBytes("-"));
|
||||
byte[] max = JedisConverters.boundaryToBytesForZRangeByLex(range.getMax(), JedisConverters.toBytes("+"));
|
||||
|
||||
try {
|
||||
if (limit != null) {
|
||||
return connection.getCluster().zrangeByLex(key, min, max, limit.getOffset(), limit.getCount());
|
||||
}
|
||||
return connection.getCluster().zrangeByLex(key, min, max);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeWithScores(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public Set<Tuple> zRangeWithScores(byte[] key, long begin, long end) {
|
||||
|
||||
try {
|
||||
return JedisConverters.toTupleSet(connection.getCluster().zrangeWithScores(key, begin, end));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByScore(byte[], double, double)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRangeByScore(byte[] key, double min, double max) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().zrangeByScore(key, min, max);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByScoreWithScores(byte[], double, double)
|
||||
*/
|
||||
@Override
|
||||
public Set<Tuple> zRangeByScoreWithScores(byte[] key, double min, double max) {
|
||||
|
||||
try {
|
||||
return JedisConverters.toTupleSet(connection.getCluster().zrangeByScoreWithScores(key, min, max));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByScore(byte[], double, double, long, long)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRangeByScore(byte[] key, double min, double max, long offset, long count) {
|
||||
|
||||
if (offset > Integer.MAX_VALUE || count > Integer.MAX_VALUE) {
|
||||
throw new IllegalArgumentException("Count/Offset cannot exceed Integer.MAX_VALUE!");
|
||||
}
|
||||
|
||||
try {
|
||||
return connection.getCluster().zrangeByScore(key, min, max, Long.valueOf(offset).intValue(),
|
||||
Long.valueOf(count).intValue());
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByScoreWithScores(byte[], double, double, long, long)
|
||||
*/
|
||||
@Override
|
||||
public Set<Tuple> zRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count) {
|
||||
|
||||
if (offset > Integer.MAX_VALUE || count > Integer.MAX_VALUE) {
|
||||
throw new IllegalArgumentException("Count/Offset cannot exceed Integer.MAX_VALUE!");
|
||||
}
|
||||
|
||||
try {
|
||||
return JedisConverters.toTupleSet(connection.getCluster().zrangeByScoreWithScores(key, min, max,
|
||||
Long.valueOf(offset).intValue(), Long.valueOf(count).intValue()));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRange(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRevRange(byte[] key, long begin, long end) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().zrevrange(key, begin, end);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRangeWithScores(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public Set<Tuple> zRevRangeWithScores(byte[] key, long begin, long end) {
|
||||
|
||||
try {
|
||||
return JedisConverters.toTupleSet(connection.getCluster().zrevrangeWithScores(key, begin, end));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRangeByScore(byte[], double, double)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRevRangeByScore(byte[] key, double min, double max) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().zrevrangeByScore(key, max, min);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRangeByScoreWithScores(byte[], double, double)
|
||||
*/
|
||||
@Override
|
||||
public Set<Tuple> zRevRangeByScoreWithScores(byte[] key, double min, double max) {
|
||||
|
||||
try {
|
||||
return JedisConverters.toTupleSet(connection.getCluster().zrevrangeByScoreWithScores(key, max, min));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRangeByScore(byte[], double, double, long, long)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRevRangeByScore(byte[] key, double min, double max, long offset, long count) {
|
||||
|
||||
if (offset > Integer.MAX_VALUE || count > Integer.MAX_VALUE) {
|
||||
throw new IllegalArgumentException("Count/Offset cannot exceed Integer.MAX_VALUE!");
|
||||
}
|
||||
|
||||
try {
|
||||
return connection.getCluster().zrevrangeByScore(key, max, min, Long.valueOf(offset).intValue(),
|
||||
Long.valueOf(count).intValue());
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRangeByScoreWithScores(byte[], double, double, long, long)
|
||||
*/
|
||||
@Override
|
||||
public Set<Tuple> zRevRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count) {
|
||||
|
||||
if (offset > Integer.MAX_VALUE || count > Integer.MAX_VALUE) {
|
||||
throw new IllegalArgumentException("Count/Offset cannot exceed Integer.MAX_VALUE!");
|
||||
}
|
||||
|
||||
try {
|
||||
return JedisConverters.toTupleSet(connection.getCluster().zrevrangeByScoreWithScores(key, max, min,
|
||||
Long.valueOf(offset).intValue(), Long.valueOf(count).intValue()));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zCount(byte[], double, double)
|
||||
*/
|
||||
@Override
|
||||
public Long zCount(byte[] key, double min, double max) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().zcount(key, min, max);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zCard(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long zCard(byte[] key) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().zcard(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zScore(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Double zScore(byte[] key, byte[] value) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().zscore(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRange(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public Long zRemRange(byte[] key, long begin, long end) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().zremrangeByRank(key, begin, end);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRangeByScore(byte[], double, double)
|
||||
*/
|
||||
@Override
|
||||
public Long zRemRangeByScore(byte[] key, double min, double max) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().zremrangeByScore(key, min, max);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zUnionStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long zUnionStore(byte[] destKey, byte[]... sets) {
|
||||
|
||||
byte[][] allKeys = ByteUtils.mergeArrays(destKey, sets);
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(allKeys)) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().zunionstore(destKey, sets);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidDataAccessApiUsageException("ZUNIONSTORE can only be executed when all keys map to the same slot");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zUnionStore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Aggregate, int[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long zUnionStore(byte[] destKey, Aggregate aggregate, int[] weights, byte[]... sets) {
|
||||
|
||||
byte[][] allKeys = ByteUtils.mergeArrays(destKey, sets);
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(allKeys)) {
|
||||
|
||||
ZParams zparams = new ZParams().weights(weights).aggregate(ZParams.Aggregate.valueOf(aggregate.name()));
|
||||
|
||||
try {
|
||||
return connection.getCluster().zunionstore(destKey, zparams, sets);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidDataAccessApiUsageException("ZUNIONSTORE can only be executed when all keys map to the same slot");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zInterStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long zInterStore(byte[] destKey, byte[]... sets) {
|
||||
|
||||
byte[][] allKeys = ByteUtils.mergeArrays(destKey, sets);
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(allKeys)) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().zinterstore(destKey, sets);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidDataAccessApiUsageException("ZINTERSTORE can only be executed when all keys map to the same slot");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zInterStore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Aggregate, int[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long zInterStore(byte[] destKey, Aggregate aggregate, int[] weights, byte[]... sets) {
|
||||
|
||||
byte[][] allKeys = ByteUtils.mergeArrays(destKey, sets);
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(allKeys)) {
|
||||
|
||||
ZParams zparams = new ZParams().weights(weights).aggregate(ZParams.Aggregate.valueOf(aggregate.name()));
|
||||
|
||||
try {
|
||||
return connection.getCluster().zinterstore(destKey, zparams, sets);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("ZINTERSTORE can only be executed when all keys map to the same slot");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zScan(byte[], org.springframework.data.redis.core.ScanOptions)
|
||||
*/
|
||||
@Override
|
||||
public Cursor<Tuple> zScan(final byte[] key, final ScanOptions options) {
|
||||
return new ScanCursor<Tuple>(options) {
|
||||
|
||||
@Override
|
||||
protected ScanIteration<Tuple> doScan(long cursorId, ScanOptions options) {
|
||||
|
||||
ScanParams params = JedisConverters.toScanParams(options);
|
||||
|
||||
redis.clients.jedis.ScanResult<redis.clients.jedis.Tuple> result = connection.getCluster().zscan(key,
|
||||
JedisConverters.toBytes(cursorId), params);
|
||||
return new ScanIteration<Tuple>(Long.valueOf(result.getStringCursor()),
|
||||
JedisConverters.tuplesToTuples().convert(result.getResult()));
|
||||
}
|
||||
}.open();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByScore(byte[], java.lang.String, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRangeByScore(byte[] key, String min, String max) {
|
||||
|
||||
try {
|
||||
return connection.getCluster().zrangeByScore(key, JedisConverters.toBytes(min), JedisConverters.toBytes(max));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByScore(byte[], java.lang.String, java.lang.String, long, long)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRangeByScore(byte[] key, String min, String max, long offset, long count) {
|
||||
|
||||
if (offset > Integer.MAX_VALUE || count > Integer.MAX_VALUE) {
|
||||
throw new IllegalArgumentException("Count/Offset cannot exceed Integer.MAX_VALUE!");
|
||||
}
|
||||
|
||||
try {
|
||||
return connection.getCluster().zrangeByScore(key, JedisConverters.toBytes(min), JedisConverters.toBytes(max),
|
||||
Long.valueOf(offset).intValue(), Long.valueOf(count).intValue());
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private DataAccessException convertJedisAccessException(Exception ex) {
|
||||
return connection.convertJedisAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,433 @@
|
||||
/*
|
||||
* 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.GeoCoordinate;
|
||||
import redis.clients.jedis.GeoUnit;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.geo.Circle;
|
||||
import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.GeoResults;
|
||||
import org.springframework.data.geo.Metric;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands;
|
||||
import org.springframework.data.redis.connection.convert.ListConverter;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnection.JedisResult;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class JedisGeoCommands implements RedisGeoCommands {
|
||||
|
||||
private final JedisConnection connection;
|
||||
|
||||
public JedisGeoCommands(JedisConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoAdd(byte[], org.springframework.data.geo.Point, byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long geoAdd(byte[] key, Point point, byte[] member) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(point, "Point must not be null!");
|
||||
Assert.notNull(member, "Member must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().geoadd(key, point.getX(), point.getY(), member)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(
|
||||
connection.newJedisResult(connection.getTransaction().geoadd(key, point.getX(), point.getY(), member)));
|
||||
return null;
|
||||
}
|
||||
|
||||
return connection.getJedis().geoadd(key, point.getX(), point.getY(), member);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoAdd(byte[], java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public Long geoAdd(byte[] key, Map<byte[], Point> memberCoordinateMap) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(memberCoordinateMap, "MemberCoordinateMap must not be null!");
|
||||
|
||||
Map<byte[], GeoCoordinate> redisGeoCoordinateMap = new HashMap<byte[], GeoCoordinate>();
|
||||
|
||||
for (byte[] mapKey : memberCoordinateMap.keySet()) {
|
||||
redisGeoCoordinateMap.put(mapKey, JedisConverters.toGeoCoordinate(memberCoordinateMap.get(mapKey)));
|
||||
}
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().geoadd(key, redisGeoCoordinateMap)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().geoadd(key, redisGeoCoordinateMap)));
|
||||
return null;
|
||||
}
|
||||
|
||||
return connection.getJedis().geoadd(key, redisGeoCoordinateMap);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoAdd(byte[], java.lang.Iterable)
|
||||
*/
|
||||
@Override
|
||||
public Long geoAdd(byte[] key, Iterable<GeoLocation<byte[]>> locations) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(locations, "Locations must not be null!");
|
||||
|
||||
Map<byte[], redis.clients.jedis.GeoCoordinate> redisGeoCoordinateMap = new HashMap<byte[], redis.clients.jedis.GeoCoordinate>();
|
||||
|
||||
for (GeoLocation<byte[]> location : locations) {
|
||||
redisGeoCoordinateMap.put(location.getName(), JedisConverters.toGeoCoordinate(location.getPoint()));
|
||||
}
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().geoadd(key, redisGeoCoordinateMap)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().geoadd(key, redisGeoCoordinateMap)));
|
||||
return null;
|
||||
}
|
||||
|
||||
return connection.getJedis().geoadd(key, redisGeoCoordinateMap);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoDist(byte[], byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Distance geoDist(byte[] key, byte[] member1, byte[] member2) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(member1, "Member1 must not be null!");
|
||||
Assert.notNull(member2, "Member2 must not be null!");
|
||||
|
||||
Converter<Double, Distance> distanceConverter = JedisConverters.distanceConverterForMetric(DistanceUnit.METERS);
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().geodist(key, member1, member2), distanceConverter));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(
|
||||
connection.newJedisResult(connection.getTransaction().geodist(key, member1, member2), distanceConverter));
|
||||
return null;
|
||||
}
|
||||
|
||||
return distanceConverter.convert(connection.getJedis().geodist(key, member1, member2));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoDist(byte[], byte[], byte[], org.springframework.data.geo.Metric)
|
||||
*/
|
||||
@Override
|
||||
public Distance geoDist(byte[] key, byte[] member1, byte[] member2, Metric metric) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(member1, "Member1 must not be null!");
|
||||
Assert.notNull(member2, "Member2 must not be null!");
|
||||
Assert.notNull(metric, "Metric must not be null!");
|
||||
|
||||
GeoUnit geoUnit = JedisConverters.toGeoUnit(metric);
|
||||
Converter<Double, Distance> distanceConverter = JedisConverters.distanceConverterForMetric(metric);
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().geodist(key, member1, member2, geoUnit),
|
||||
distanceConverter));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().geodist(key, member1, member2, geoUnit),
|
||||
distanceConverter));
|
||||
return null;
|
||||
}
|
||||
|
||||
return distanceConverter.convert(connection.getJedis().geodist(key, member1, member2, geoUnit));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoHash(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<String> geoHash(byte[] key, byte[]... members) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(members, "Members must not be null!");
|
||||
Assert.noNullElements(members, "Members must not contain null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().geohash(key, members),
|
||||
JedisConverters.bytesListToStringListConverter()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().geohash(key, members),
|
||||
JedisConverters.bytesListToStringListConverter()));
|
||||
return null;
|
||||
}
|
||||
|
||||
return JedisConverters.bytesListToStringListConverter().convert(connection.getJedis().geohash(key, members));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoPos(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<Point> geoPos(byte[] key, byte[]... members) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(members, "Members must not be null!");
|
||||
Assert.noNullElements(members, "Members must not contain null!");
|
||||
|
||||
ListConverter<GeoCoordinate, Point> converter = JedisConverters.geoCoordinateToPointConverter();
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().geopos(key, members), converter));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().geopos(key, members), converter));
|
||||
return null;
|
||||
}
|
||||
return converter.convert(connection.getJedis().geopos(key, members));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoRadius(byte[], org.springframework.data.geo.Circle)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<byte[]>> geoRadius(byte[] key, Circle within) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(within, "Within must not be null!");
|
||||
|
||||
Converter<List<redis.clients.jedis.GeoRadiusResponse>, GeoResults<GeoLocation<byte[]>>> converter = JedisConverters
|
||||
.geoRadiusResponseToGeoResultsConverter(within.getRadius().getMetric());
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(
|
||||
connection.newJedisResult(
|
||||
connection.getPipeline().georadius(key, within.getCenter().getX(), within.getCenter().getY(),
|
||||
within.getRadius().getValue(), JedisConverters.toGeoUnit(within.getRadius().getMetric())),
|
||||
converter));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(
|
||||
connection.newJedisResult(
|
||||
connection.getTransaction().georadius(key, within.getCenter().getX(), within.getCenter().getY(),
|
||||
within.getRadius().getValue(), JedisConverters.toGeoUnit(within.getRadius().getMetric())),
|
||||
converter));
|
||||
return null;
|
||||
}
|
||||
|
||||
return converter
|
||||
.convert(connection.getJedis().georadius(key, within.getCenter().getX(), within.getCenter().getY(),
|
||||
within.getRadius().getValue(), JedisConverters.toGeoUnit(within.getRadius().getMetric())));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoRadius(byte[], org.springframework.data.geo.Circle, org.springframework.data.redis.core.GeoRadiusCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<byte[]>> geoRadius(byte[] key, Circle within, GeoRadiusCommandArgs args) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(within, "Within must not be null!");
|
||||
Assert.notNull(args, "Args must not be null!");
|
||||
|
||||
redis.clients.jedis.params.geo.GeoRadiusParam geoRadiusParam = JedisConverters.toGeoRadiusParam(args);
|
||||
Converter<List<redis.clients.jedis.GeoRadiusResponse>, GeoResults<GeoLocation<byte[]>>> converter = JedisConverters
|
||||
.geoRadiusResponseToGeoResultsConverter(within.getRadius().getMetric());
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().georadius(key, within.getCenter().getX(),
|
||||
within.getCenter().getY(), within.getRadius().getValue(),
|
||||
JedisConverters.toGeoUnit(within.getRadius().getMetric()), geoRadiusParam), converter));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().georadius(key, within.getCenter().getX(),
|
||||
within.getCenter().getY(), within.getRadius().getValue(),
|
||||
JedisConverters.toGeoUnit(within.getRadius().getMetric()), geoRadiusParam), converter));
|
||||
return null;
|
||||
}
|
||||
|
||||
return converter.convert(connection.getJedis().georadius(key, within.getCenter().getX(),
|
||||
within.getCenter().getY(), within.getRadius().getValue(),
|
||||
JedisConverters.toGeoUnit(within.getRadius().getMetric()), geoRadiusParam));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoRadiusByMember(byte[], byte[], org.springframework.data.geo.Distance)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<byte[]>> geoRadiusByMember(byte[] key, byte[] member, Distance radius) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(member, "Member must not be null!");
|
||||
Assert.notNull(radius, "Radius must not be null!");
|
||||
|
||||
GeoUnit geoUnit = JedisConverters.toGeoUnit(radius.getMetric());
|
||||
Converter<List<redis.clients.jedis.GeoRadiusResponse>, GeoResults<GeoLocation<byte[]>>> converter = JedisConverters
|
||||
.geoRadiusResponseToGeoResultsConverter(radius.getMetric());
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(
|
||||
connection.getPipeline().georadiusByMember(key, member, radius.getValue(), geoUnit), converter));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(
|
||||
connection.getTransaction().georadiusByMember(key, member, radius.getValue(), geoUnit), converter));
|
||||
return null;
|
||||
}
|
||||
|
||||
return converter.convert(connection.getJedis().georadiusByMember(key, member, radius.getValue(), geoUnit));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoRadiusByMember(byte[], byte[], org.springframework.data.geo.Distance, org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<byte[]>> geoRadiusByMember(byte[] key, byte[] member, Distance radius,
|
||||
GeoRadiusCommandArgs args) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(member, "Member must not be null!");
|
||||
Assert.notNull(radius, "Radius must not be null!");
|
||||
Assert.notNull(args, "Args must not be null!");
|
||||
|
||||
GeoUnit geoUnit = JedisConverters.toGeoUnit(radius.getMetric());
|
||||
Converter<List<redis.clients.jedis.GeoRadiusResponse>, GeoResults<GeoLocation<byte[]>>> converter = JedisConverters
|
||||
.geoRadiusResponseToGeoResultsConverter(radius.getMetric());
|
||||
redis.clients.jedis.params.geo.GeoRadiusParam geoRadiusParam = JedisConverters.toGeoRadiusParam(args);
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(
|
||||
connection.getPipeline().georadiusByMember(key, member, radius.getValue(), geoUnit, geoRadiusParam),
|
||||
converter));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(
|
||||
connection.getTransaction().georadiusByMember(key, member, radius.getValue(), geoUnit, geoRadiusParam),
|
||||
converter));
|
||||
return null;
|
||||
}
|
||||
return converter
|
||||
.convert(connection.getJedis().georadiusByMember(key, member, radius.getValue(), geoUnit, geoRadiusParam));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoRemove(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long geoRemove(byte[] key, byte[]... members) {
|
||||
return connection.zSetCommands().zRem(key, members);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,396 @@
|
||||
/*
|
||||
* 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.ScanParams;
|
||||
import redis.clients.jedis.ScanResult;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.redis.connection.RedisHashCommands;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnection.JedisResult;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class JedisHashCommands implements RedisHashCommands {
|
||||
|
||||
private final JedisConnection connection;
|
||||
|
||||
public JedisHashCommands(JedisConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hSet(byte[], byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean hSet(byte[] key, byte[] field, byte[] value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().hset(key, field, value),
|
||||
JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().hset(key, field, value),
|
||||
JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
return JedisConverters.toBoolean(connection.getJedis().hset(key, field, value));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hSetNX(byte[], byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean hSetNX(byte[] key, byte[] field, byte[] value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().hsetnx(key, field, value),
|
||||
JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().hsetnx(key, field, value),
|
||||
JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
return JedisConverters.toBoolean(connection.getJedis().hsetnx(key, field, value));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hDel(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long hDel(byte[] key, byte[]... fields) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().hdel(key, fields)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().hdel(key, fields)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().hdel(key, fields);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hExists(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean hExists(byte[] key, byte[] field) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().hexists(key, field)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().hexists(key, field)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().hexists(key, field);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hGet(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] hGet(byte[] key, byte[] field) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().hget(key, field)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().hget(key, field)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().hget(key, field);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hGetAll(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Map<byte[], byte[]> hGetAll(byte[] key) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().hgetAll(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().hgetAll(key)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().hgetAll(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hIncrBy(byte[], byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public Long hIncrBy(byte[] key, byte[] field, long delta) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().hincrBy(key, field, delta)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().hincrBy(key, field, delta)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().hincrBy(key, field, delta);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hIncrBy(byte[], byte[], double)
|
||||
*/
|
||||
@Override
|
||||
public Double hIncrBy(byte[] key, byte[] field, double delta) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().hincrByFloat(key, field, delta)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().hincrByFloat(key, field, delta)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().hincrByFloat(key, field, delta);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hKeys(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> hKeys(byte[] key) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().hkeys(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().hkeys(key)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().hkeys(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hLen(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long hLen(byte[] key) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().hlen(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().hlen(key)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().hlen(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hMGet(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> hMGet(byte[] key, byte[]... fields) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().hmget(key, fields)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().hmget(key, fields)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().hmget(key, fields);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hMSet(byte[], java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public void hMSet(byte[] key, Map<byte[], byte[]> tuple) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newStatusResult(connection.getPipeline().hmset(key, tuple)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newStatusResult(connection.getTransaction().hmset(key, tuple)));
|
||||
return;
|
||||
}
|
||||
connection.getJedis().hmset(key, tuple);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hVals(byte[])
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> hVals(byte[] key) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().hvals(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().hvals(key)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().hvals(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hScan(byte[], org.springframework.data.redis.core.ScanOptions)
|
||||
*/
|
||||
@Override
|
||||
public Cursor<Entry<byte[], byte[]>> hScan(byte[] key, ScanOptions options) {
|
||||
return hScan(key, 0, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.4
|
||||
* @param key
|
||||
* @param cursorId
|
||||
* @param options
|
||||
* @return
|
||||
*/
|
||||
public Cursor<Entry<byte[], byte[]>> hScan(byte[] key, long cursorId, ScanOptions options) {
|
||||
|
||||
return new KeyBoundCursor<Entry<byte[], byte[]>>(key, cursorId, options) {
|
||||
|
||||
@Override
|
||||
protected ScanIteration<Entry<byte[], byte[]>> doScan(byte[] key, long cursorId, ScanOptions options) {
|
||||
|
||||
if (isQueueing() || isPipelined()) {
|
||||
throw new UnsupportedOperationException("'HSCAN' cannot be called in pipeline / transaction mode.");
|
||||
}
|
||||
|
||||
ScanParams params = JedisConverters.toScanParams(options);
|
||||
|
||||
ScanResult<Entry<byte[], byte[]>> result = connection.getJedis().hscan(key, JedisConverters.toBytes(cursorId),
|
||||
params);
|
||||
return new ScanIteration<>(Long.valueOf(result.getStringCursor()), result.getResult());
|
||||
}
|
||||
|
||||
protected void doClose() {
|
||||
JedisHashCommands.this.connection.close();
|
||||
};
|
||||
|
||||
}.open();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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 org.springframework.data.redis.connection.RedisHyperLogLogCommands;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnection.JedisResult;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class JedisHyperLogLogCommands implements RedisHyperLogLogCommands {
|
||||
|
||||
private final JedisConnection connection;
|
||||
|
||||
public JedisHyperLogLogCommands(JedisConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHyperLogLogCommands#pfAdd(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long pfAdd(byte[] key, byte[]... values) {
|
||||
|
||||
Assert.notEmpty(values, "PFADD requires at least one non 'null' value.");
|
||||
Assert.noNullElements(values, "Values for PFADD must not contain 'null'.");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().pfadd(key, values)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().pfadd(key, values)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().pfadd(key, values);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHyperLogLogCommands#pfCount(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long pfCount(byte[]... keys) {
|
||||
|
||||
Assert.notEmpty(keys, "PFCOUNT requires at least one non 'null' key.");
|
||||
Assert.noNullElements(keys, "Keys for PFOUNT must not contain 'null'.");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().pfcount(keys)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().pfcount(keys)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().pfcount(keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHyperLogLogCommands#pfMerge(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public void pfMerge(byte[] destinationKey, byte[]... sourceKeys) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().pfmerge(destinationKey, sourceKeys)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().pfmerge(destinationKey, sourceKeys)));
|
||||
return;
|
||||
}
|
||||
connection.getJedis().pfmerge(destinationKey, sourceKeys);
|
||||
} 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,634 @@
|
||||
/*
|
||||
* 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.ScanParams;
|
||||
import redis.clients.jedis.SortingParams;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.data.redis.connection.DataType;
|
||||
import org.springframework.data.redis.connection.RedisKeyCommands;
|
||||
import org.springframework.data.redis.connection.SortParameters;
|
||||
import org.springframework.data.redis.connection.convert.Converters;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnection.JedisResult;
|
||||
import org.springframework.data.redis.core.Cursor;
|
||||
import org.springframework.data.redis.core.ScanCursor;
|
||||
import org.springframework.data.redis.core.ScanIteration;
|
||||
import org.springframework.data.redis.core.ScanOptions;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class JedisKeyCommands implements RedisKeyCommands {
|
||||
|
||||
private final JedisConnection connection;
|
||||
|
||||
public JedisKeyCommands(JedisConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#exists(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean exists(byte[] key) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().exists(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().exists(key)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().exists(key);
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#del(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long del(byte[]... keys) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().del(keys)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().del(keys)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().del(keys);
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#type(byte[])
|
||||
*/
|
||||
@Override
|
||||
public DataType type(byte[] key) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().type(key), JedisConverters.stringToDataType()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(
|
||||
connection.newJedisResult(connection.getTransaction().type(key), JedisConverters.stringToDataType()));
|
||||
return null;
|
||||
}
|
||||
return JedisConverters.toDataType(connection.getJedis().type(key));
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#keys(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> keys(byte[] pattern) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().keys(pattern)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().keys(pattern)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().keys(pattern);
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#scan(org.springframework.data.redis.core.ScanOptions)
|
||||
*/
|
||||
public Cursor<byte[]> scan(ScanOptions options) {
|
||||
return scan(0, options != null ? options : ScanOptions.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.4
|
||||
* @param cursorId
|
||||
* @param options
|
||||
* @return
|
||||
*/
|
||||
public Cursor<byte[]> scan(long cursorId, ScanOptions options) {
|
||||
|
||||
return new ScanCursor<byte[]>(cursorId, options) {
|
||||
|
||||
@Override
|
||||
protected ScanIteration<byte[]> doScan(long cursorId, ScanOptions options) {
|
||||
|
||||
if (isQueueing() || isPipelined()) {
|
||||
throw new UnsupportedOperationException("'SCAN' cannot be called in pipeline / transaction mode.");
|
||||
}
|
||||
|
||||
ScanParams params = JedisConverters.toScanParams(options);
|
||||
redis.clients.jedis.ScanResult<String> result = connection.getJedis().scan(Long.toString(cursorId), params);
|
||||
return new ScanIteration<byte[]>(Long.valueOf(result.getStringCursor()),
|
||||
JedisConverters.stringListToByteList().convert(result.getResult()));
|
||||
}
|
||||
|
||||
protected void doClose() {
|
||||
JedisKeyCommands.this.connection.close();
|
||||
};
|
||||
|
||||
}.open();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#randomKey()
|
||||
*/
|
||||
@Override
|
||||
public byte[] randomKey() {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().randomKeyBinary()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().randomKeyBinary()));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().randomBinaryKey();
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#rename(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public void rename(byte[] oldName, byte[] newName) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newStatusResult(connection.getPipeline().rename(oldName, newName)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newStatusResult(connection.getTransaction().rename(oldName, newName)));
|
||||
return;
|
||||
}
|
||||
connection.getJedis().rename(oldName, newName);
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#renameNX(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean renameNX(byte[] oldName, byte[] newName) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().renamenx(oldName, newName),
|
||||
JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().renamenx(oldName, newName),
|
||||
JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
return JedisConverters.toBoolean(connection.getJedis().renamenx(oldName, newName));
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#expire(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public Boolean expire(byte[] key, long seconds) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
if (seconds > Integer.MAX_VALUE) {
|
||||
return pExpire(key, TimeUnit.SECONDS.toMillis(seconds));
|
||||
}
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().expire(key, (int) seconds),
|
||||
JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().expire(key, (int) seconds),
|
||||
JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
return JedisConverters.toBoolean(connection.getJedis().expire(key, (int) seconds));
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#expireAt(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public Boolean expireAt(byte[] key, long unixTime) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().expireAt(key, unixTime),
|
||||
JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().expireAt(key, unixTime),
|
||||
JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
return JedisConverters.toBoolean(connection.getJedis().expireAt(key, unixTime));
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#pExpire(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public Boolean pExpire(byte[] key, long millis) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(
|
||||
connection.newJedisResult(connection.getPipeline().pexpire(key, millis), JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().pexpire(key, millis),
|
||||
JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
return JedisConverters.toBoolean(connection.getJedis().pexpire(key, millis));
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#pExpireAt(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public Boolean pExpireAt(byte[] key, long unixTimeInMillis) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().pexpireAt(key, unixTimeInMillis),
|
||||
JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().pexpireAt(key, unixTimeInMillis),
|
||||
JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
return JedisConverters.toBoolean(connection.getJedis().pexpireAt(key, unixTimeInMillis));
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#persist(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean persist(byte[] key) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().persist(key), JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(
|
||||
connection.newJedisResult(connection.getTransaction().persist(key), JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
return JedisConverters.toBoolean(connection.getJedis().persist(key));
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#move(byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public Boolean move(byte[] key, int dbIndex) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(
|
||||
connection.newJedisResult(connection.getPipeline().move(key, dbIndex), JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(
|
||||
connection.newJedisResult(connection.getTransaction().move(key, dbIndex), JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
return JedisConverters.toBoolean(connection.getJedis().move(key, dbIndex));
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#ttl(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long ttl(byte[] key) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().ttl(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().ttl(key)));
|
||||
return null;
|
||||
}
|
||||
|
||||
return connection.getJedis().ttl(key);
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#ttl(byte[], java.util.concurrent.TimeUnit)
|
||||
*/
|
||||
@Override
|
||||
public Long ttl(byte[] key, TimeUnit timeUnit) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().ttl(key), Converters.secondsToTimeUnit(timeUnit)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(
|
||||
connection.newJedisResult(connection.getTransaction().ttl(key), Converters.secondsToTimeUnit(timeUnit)));
|
||||
return null;
|
||||
}
|
||||
|
||||
return Converters.secondsToTimeUnit(connection.getJedis().ttl(key), timeUnit);
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#pTtl(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long pTtl(byte[] key) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().pttl(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().pttl(key)));
|
||||
return null;
|
||||
}
|
||||
|
||||
return connection.getJedis().pttl(key);
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#pTtl(byte[], java.util.concurrent.TimeUnit)
|
||||
*/
|
||||
@Override
|
||||
public Long pTtl(byte[] key, TimeUnit timeUnit) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(
|
||||
connection.newJedisResult(connection.getPipeline().pttl(key), Converters.millisecondsToTimeUnit(timeUnit)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().pttl(key),
|
||||
Converters.millisecondsToTimeUnit(timeUnit)));
|
||||
return null;
|
||||
}
|
||||
|
||||
return Converters.millisecondsToTimeUnit(connection.getJedis().pttl(key), timeUnit);
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#sort(byte[], org.springframework.data.redis.connection.SortParameters)
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> sort(byte[] key, SortParameters params) {
|
||||
|
||||
SortingParams sortParams = JedisConverters.toSortingParams(params);
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
if (sortParams != null) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().sort(key, sortParams)));
|
||||
} else {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().sort(key)));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
if (sortParams != null) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().sort(key, sortParams)));
|
||||
} else {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().sort(key)));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
return (sortParams != null ? connection.getJedis().sort(key, sortParams) : connection.getJedis().sort(key));
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#sort(byte[], org.springframework.data.redis.connection.SortParameters, byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long sort(byte[] key, SortParameters params, byte[] storeKey) {
|
||||
|
||||
SortingParams sortParams = JedisConverters.toSortingParams(params);
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
if (sortParams != null) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().sort(key, sortParams, storeKey)));
|
||||
} else {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().sort(key, storeKey)));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
if (sortParams != null) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().sort(key, sortParams, storeKey)));
|
||||
} else {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().sort(key, storeKey)));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
return (sortParams != null ? connection.getJedis().sort(key, sortParams, storeKey)
|
||||
: connection.getJedis().sort(key, storeKey));
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#dump(byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] dump(byte[] key) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().dump(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().dump(key)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().dump(key);
|
||||
} catch (Exception ex) {
|
||||
throw connection.convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#restore(byte[], long, byte[])
|
||||
*/
|
||||
@Override
|
||||
public void restore(byte[] key, long ttlInMillis, byte[] serializedValue) {
|
||||
|
||||
if (ttlInMillis > Integer.MAX_VALUE) {
|
||||
throw new IllegalArgumentException("TtlInMillis must be less than Integer.MAX_VALUE for restore in Jedis.");
|
||||
}
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newStatusResult(connection.getPipeline().restore(key, (int) ttlInMillis, serializedValue)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(
|
||||
connection.newStatusResult(connection.getTransaction().restore(key, (int) ttlInMillis, serializedValue)));
|
||||
return;
|
||||
}
|
||||
connection.getJedis().restore(key, (int) ttlInMillis, serializedValue);
|
||||
} catch (Exception ex) {
|
||||
throw connection.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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,443 @@
|
||||
/*
|
||||
* 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.Protocol;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.redis.connection.RedisListCommands;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnection.JedisResult;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class JedisListCommands implements RedisListCommands {
|
||||
|
||||
private final JedisConnection connection;
|
||||
|
||||
public JedisListCommands(JedisConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#rPush(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long rPush(byte[] key, byte[]... values) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().rpush(key, values)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().rpush(key, values)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().rpush(key, values);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lPush(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long lPush(byte[] key, byte[]... values) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().lpush(key, values)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().lpush(key, values)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().lpush(key, values);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#rPushX(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long rPushX(byte[] key, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().rpushx(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().rpushx(key, value)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().rpushx(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lPushX(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long lPushX(byte[] key, byte[] value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().lpushx(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().lpushx(key, value)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().lpushx(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lLen(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long lLen(byte[] key) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().llen(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().llen(key)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().llen(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lRange(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> lRange(byte[] key, long start, long end) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().lrange(key, start, end)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().lrange(key, start, end)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().lrange(key, start, end);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lTrim(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public void lTrim(byte[] key, long start, long end) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newStatusResult(connection.getPipeline().ltrim(key, start, end)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newStatusResult(connection.getTransaction().ltrim(key, start, end)));
|
||||
return;
|
||||
}
|
||||
connection.getJedis().ltrim(key, start, end);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lIndex(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public byte[] lIndex(byte[] key, long index) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().lindex(key, index)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().lindex(key, index)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().lindex(key, index);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lInsert(byte[], org.springframework.data.redis.connection.RedisListCommands.Position, byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long lInsert(byte[] key, Position where, byte[] pivot, byte[] value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(
|
||||
connection.getPipeline().linsert(key, JedisConverters.toListPosition(where), pivot, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(
|
||||
connection.getTransaction().linsert(key, JedisConverters.toListPosition(where), pivot, value)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().linsert(key, JedisConverters.toListPosition(where), pivot, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lSet(byte[], long, byte[])
|
||||
*/
|
||||
@Override
|
||||
public void lSet(byte[] key, long index, byte[] value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newStatusResult(connection.getPipeline().lset(key, index, value)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newStatusResult(connection.getTransaction().lset(key, index, value)));
|
||||
return;
|
||||
}
|
||||
connection.getJedis().lset(key, index, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lRem(byte[], long, byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long lRem(byte[] key, long count, byte[] value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().lrem(key, count, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().lrem(key, count, value)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().lrem(key, count, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lPop(byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] lPop(byte[] key) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().lpop(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().lpop(key)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().lpop(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#rPop(byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] rPop(byte[] key) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().rpop(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().rpop(key)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().rpop(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#bLPop(int, byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> bLPop(int timeout, byte[]... keys) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().blpop(bXPopArgs(timeout, keys))));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().blpop(bXPopArgs(timeout, keys))));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().blpop(timeout, keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#bRPop(int, byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> bRPop(int timeout, byte[]... keys) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().brpop(bXPopArgs(timeout, keys))));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().brpop(bXPopArgs(timeout, keys))));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().brpop(timeout, keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#rPopLPush(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] rPopLPush(byte[] srcKey, byte[] dstKey) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().rpoplpush(srcKey, dstKey)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().rpoplpush(srcKey, dstKey)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().rpoplpush(srcKey, dstKey);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#bRPopLPush(int, byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] bRPopLPush(int timeout, byte[] srcKey, byte[] dstKey) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().brpoplpush(srcKey, dstKey, timeout)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().brpoplpush(srcKey, dstKey, timeout)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().brpoplpush(srcKey, dstKey, timeout);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[][] bXPopArgs(int timeout, byte[]... keys) {
|
||||
|
||||
final List<byte[]> args = new ArrayList<>();
|
||||
for (final byte[] arg : keys) {
|
||||
args.add(arg);
|
||||
}
|
||||
args.add(Protocol.toByteArray(timeout));
|
||||
return args.toArray(new byte[args.size()][]);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
* 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.Set;
|
||||
|
||||
import org.springframework.data.redis.connection.RedisSetCommands;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnection.JedisResult;
|
||||
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
|
||||
* @since 2.0
|
||||
*/
|
||||
class JedisSetCommands implements RedisSetCommands {
|
||||
|
||||
private final JedisConnection connection;
|
||||
|
||||
public JedisSetCommands(JedisConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sAdd(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sAdd(byte[] key, byte[]... values) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().sadd(key, values)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().sadd(key, values)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().sadd(key, values);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sCard(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long sCard(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().scard(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().scard(key)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().scard(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sDiff(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> sDiff(byte[]... keys) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().sdiff(keys)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().sdiff(keys)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().sdiff(keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sDiffStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sDiffStore(byte[] destKey, byte[]... keys) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().sdiffstore(destKey, keys)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().sdiffstore(destKey, keys)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().sdiffstore(destKey, keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sInter(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> sInter(byte[]... keys) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().sinter(keys)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().sinter(keys)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().sinter(keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sInterStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sInterStore(byte[] destKey, byte[]... keys) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().sinterstore(destKey, keys)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().sinterstore(destKey, keys)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().sinterstore(destKey, keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sIsMember(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean sIsMember(byte[] key, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().sismember(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().sismember(key, value)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().sismember(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sMembers(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> sMembers(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().smembers(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().smembers(key)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().smembers(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sMove(byte[], byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean sMove(byte[] srcKey, byte[] destKey, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
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()));
|
||||
return null;
|
||||
}
|
||||
return JedisConverters.toBoolean(connection.getJedis().smove(srcKey, destKey, value));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sPop(byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] sPop(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().spop(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().spop(key)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().spop(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sRandMember(byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] sRandMember(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().srandmember(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().srandmember(key)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().srandmember(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sRandMember(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> sRandMember(byte[] key, long count) {
|
||||
|
||||
if (count > Integer.MAX_VALUE) {
|
||||
throw new IllegalArgumentException("Count must be less than Integer.MAX_VALUE for sRandMember in Jedis.");
|
||||
}
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().srandmember(key, (int) count)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().srandmember(key, (int) count)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().srandmember(key, (int) count);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sRem(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sRem(byte[] key, byte[]... values) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().srem(key, values)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().srem(key, values)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().srem(key, values);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sUnion(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> sUnion(byte[]... keys) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().sunion(keys)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().sunion(keys)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().sunion(keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sUnionStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sUnionStore(byte[] destKey, byte[]... keys) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().sunionstore(destKey, keys)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().sunionstore(destKey, keys)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().sunionstore(destKey, keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sScan(byte[], org.springframework.data.redis.core.ScanOptions)
|
||||
*/
|
||||
@Override
|
||||
public Cursor<byte[]> sScan(byte[] key, ScanOptions options) {
|
||||
return sScan(key, 0, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.4
|
||||
* @param key
|
||||
* @param cursorId
|
||||
* @param options
|
||||
* @return
|
||||
*/
|
||||
public Cursor<byte[]> sScan(byte[] key, long cursorId, ScanOptions options) {
|
||||
|
||||
return new KeyBoundCursor<byte[]>(key, cursorId, options) {
|
||||
|
||||
@Override
|
||||
protected ScanIteration<byte[]> doScan(byte[] key, long cursorId, ScanOptions options) {
|
||||
|
||||
if (isQueueing() || isPipelined()) {
|
||||
throw new UnsupportedOperationException("'SSCAN' cannot be called in pipeline / transaction mode.");
|
||||
}
|
||||
|
||||
ScanParams params = JedisConverters.toScanParams(options);
|
||||
|
||||
redis.clients.jedis.ScanResult<byte[]> result = connection.getJedis().sscan(key, JedisConverters.toBytes(cursorId), params);
|
||||
return new ScanIteration<>(Long.valueOf(result.getStringCursor()), result.getResult());
|
||||
}
|
||||
|
||||
protected void doClose() {
|
||||
JedisSetCommands.this.connection.close();
|
||||
};
|
||||
}.open();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,580 @@
|
||||
/*
|
||||
* 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.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.data.redis.connection.RedisStringCommands;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnection.JedisResult;
|
||||
import org.springframework.data.redis.core.types.Expiration;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class JedisStringCommands implements RedisStringCommands {
|
||||
|
||||
private final JedisConnection connection;
|
||||
|
||||
public JedisStringCommands(JedisConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] get(byte[] key) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().get(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().get(key)));
|
||||
return null;
|
||||
}
|
||||
|
||||
return connection.getJedis().get(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getSet(byte[] key, byte[] value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().getSet(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().getSet(key, value)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().getSet(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<byte[]> mGet(byte[]... keys) {
|
||||
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().mget(keys)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().mget(keys)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().mget(keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(byte[] key, byte[] value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newStatusResult(connection.getPipeline().set(key, value)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newStatusResult(connection.getTransaction().set(key, value)));
|
||||
return;
|
||||
}
|
||||
connection.getJedis().set(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(byte[] key, byte[] value, Expiration expiration, SetOption option) {
|
||||
|
||||
if (expiration == null || expiration.isPersistent()) {
|
||||
|
||||
if (option == null || ObjectUtils.nullSafeEquals(SetOption.UPSERT, option)) {
|
||||
set(key, value);
|
||||
} else {
|
||||
|
||||
try {
|
||||
|
||||
byte[] nxxx = JedisConverters.toSetCommandNxXxArgument(option);
|
||||
|
||||
if (isPipelined()) {
|
||||
|
||||
pipeline(connection.newStatusResult(connection.getPipeline().set(key, value, nxxx)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
|
||||
transaction(connection.newStatusResult(connection.getTransaction().set(key, value, nxxx)));
|
||||
return;
|
||||
}
|
||||
|
||||
connection.getJedis().set(key, value, nxxx);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (option == null || ObjectUtils.nullSafeEquals(SetOption.UPSERT, option)) {
|
||||
|
||||
if (ObjectUtils.nullSafeEquals(TimeUnit.MILLISECONDS, expiration.getTimeUnit())) {
|
||||
pSetEx(key, expiration.getExpirationTime(), value);
|
||||
} else {
|
||||
setEx(key, expiration.getExpirationTime(), value);
|
||||
}
|
||||
} else {
|
||||
|
||||
byte[] nxxx = JedisConverters.toSetCommandNxXxArgument(option);
|
||||
byte[] expx = JedisConverters.toSetCommandExPxArgument(expiration);
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
|
||||
if (expiration.getExpirationTime() > Integer.MAX_VALUE) {
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
"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())));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
|
||||
if (expiration.getExpirationTime() > Integer.MAX_VALUE) {
|
||||
throw new IllegalArgumentException(
|
||||
"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())));
|
||||
return;
|
||||
}
|
||||
|
||||
connection.getJedis().set(key, value, nxxx, expx, expiration.getExpirationTime());
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean setNX(byte[] key, byte[] value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().setnx(key, value), JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().setnx(key, value), JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
return JedisConverters.toBoolean(connection.getJedis().setnx(key, value));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEx(byte[] key, long seconds, byte[] value) {
|
||||
if (seconds > Integer.MAX_VALUE) {
|
||||
throw new IllegalArgumentException("Time must be less than Integer.MAX_VALUE for setEx in Jedis.");
|
||||
}
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newStatusResult(connection.getPipeline().setex(key, (int) seconds, value)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newStatusResult(connection.getTransaction().setex(key, (int) seconds, value)));
|
||||
return;
|
||||
}
|
||||
connection.getJedis().setex(key, (int) seconds, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pSetEx(byte[] key, long milliseconds, byte[] value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newStatusResult(connection.getPipeline().psetex(key, milliseconds, value)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newStatusResult(connection.getTransaction().psetex(key, milliseconds, value)));
|
||||
return;
|
||||
}
|
||||
connection.getJedis().psetex(key, milliseconds, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mSet(Map<byte[], byte[]> tuples) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newStatusResult(connection.getPipeline().mset(JedisConverters.toByteArrays(tuples))));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newStatusResult(connection.getTransaction().mset(JedisConverters.toByteArrays(tuples))));
|
||||
return;
|
||||
}
|
||||
connection.getJedis().mset(JedisConverters.toByteArrays(tuples));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean mSetNX(Map<byte[], byte[]> tuples) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
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()));
|
||||
return null;
|
||||
}
|
||||
return JedisConverters.toBoolean(connection.getJedis().msetnx(JedisConverters.toByteArrays(tuples)));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long incr(byte[] key) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().incr(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().incr(key)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().incr(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long incrBy(byte[] key, long value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().incrBy(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().incrBy(key, value)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().incrBy(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double incrBy(byte[] key, double value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().incrByFloat(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().incrByFloat(key, value)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().incrByFloat(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long decr(byte[] key) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().decr(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().decr(key)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().decr(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long decrBy(byte[] key, long value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().decrBy(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().decrBy(key, value)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().decrBy(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long append(byte[] key, byte[] value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().append(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().append(key, value)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().append(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getRange(byte[] key, long start, long end) {
|
||||
|
||||
if (start > Integer.MAX_VALUE || end > Integer.MAX_VALUE) {
|
||||
throw new IllegalArgumentException("Start and end must be less than Integer.MAX_VALUE for getRange in Jedis.");
|
||||
}
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
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()));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().substr(key, (int) start, (int) end);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRange(byte[] key, byte[] value, long start) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newStatusResult(connection.getPipeline().setrange(key, start, value)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newStatusResult(connection.getTransaction().setrange(key, start, value)));
|
||||
return;
|
||||
}
|
||||
connection.getJedis().setrange(key, start, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getBit(byte[] key, long offset) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().getbit(key, offset)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().getbit(key, offset)));
|
||||
return null;
|
||||
}
|
||||
// compatibility check for Jedis 2.0.0
|
||||
Object getBit = connection.getJedis().getbit(key, offset);
|
||||
// Jedis 2.0
|
||||
if (getBit instanceof Long) {
|
||||
return (((Long) getBit) == 0 ? Boolean.FALSE : Boolean.TRUE);
|
||||
}
|
||||
// Jedis 2.1
|
||||
return ((Boolean) getBit);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean setBit(byte[] key, long offset, boolean value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().setbit(key, offset, JedisConverters.toBit(value))));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().setbit(key, offset, JedisConverters.toBit(value))));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().setbit(key, offset, JedisConverters.toBit(value));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long bitCount(byte[] key) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().bitcount(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().bitcount(key)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().bitcount(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long bitCount(byte[] key, long begin, long end) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().bitcount(key, begin, end)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().bitcount(key, begin, end)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().bitcount(key, begin, end);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@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)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().bitop(JedisConverters.toBitOp(op), destination, keys)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().bitop(JedisConverters.toBitOp(op), destination, keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long strLen(byte[] key) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().strlen(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().strlen(key)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().strlen(key);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,853 @@
|
||||
/*
|
||||
* 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.ScanParams;
|
||||
import redis.clients.jedis.ScanResult;
|
||||
import redis.clients.jedis.ZParams;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnection.JedisResult;
|
||||
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 org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class JedisZSetCommands implements RedisZSetCommands {
|
||||
|
||||
private final JedisConnection connection;
|
||||
|
||||
public JedisZSetCommands(JedisConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], double, byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean zAdd(byte[] key, double score, byte[] value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zadd(key, score, value),
|
||||
JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zadd(key, score, value),
|
||||
JedisConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
return JedisConverters.toBoolean(connection.getJedis().zadd(key, score, value));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], java.util.Set)
|
||||
*/
|
||||
@Override
|
||||
public Long zAdd(byte[] key, Set<Tuple> tuples) {
|
||||
|
||||
if (isPipelined() || isQueueing()) {
|
||||
throw new UnsupportedOperationException("zAdd of multiple fields not supported " + "in pipeline or transaction");
|
||||
}
|
||||
|
||||
Map<byte[], Double> args = zAddArgs(tuples);
|
||||
try {
|
||||
return connection.getJedis().zadd(key, args);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zCard(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long zCard(byte[] key) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zcard(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zcard(key)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().zcard(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zCount(byte[], double, double)
|
||||
*/
|
||||
@Override
|
||||
public Long zCount(byte[] key, double min, double max) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zcount(key, min, max)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zcount(key, min, max)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().zcount(key, min, max);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zCount(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
|
||||
*/
|
||||
@Override
|
||||
public Long zCount(byte[] key, Range range) {
|
||||
|
||||
if (isPipelined() || isQueueing()) {
|
||||
throw new UnsupportedOperationException(
|
||||
"ZCOUNT not implemented in jedis for binary protocol on transaction and pipeline");
|
||||
}
|
||||
|
||||
byte[] min = JedisConverters.boundaryToBytesForZRange(range.getMin(), JedisConverters.NEGATIVE_INFINITY_BYTES);
|
||||
byte[] max = JedisConverters.boundaryToBytesForZRange(range.getMax(), JedisConverters.POSITIVE_INFINITY_BYTES);
|
||||
|
||||
return connection.getJedis().zcount(key, min, max);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zIncrBy(byte[], double, byte[])
|
||||
*/
|
||||
@Override
|
||||
public Double zIncrBy(byte[] key, double increment, byte[] value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zincrby(key, increment, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zincrby(key, increment, value)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().zincrby(key, increment, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zInterStore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Aggregate, int[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long zInterStore(byte[] destKey, Aggregate aggregate, int[] weights, byte[]... sets) {
|
||||
|
||||
try {
|
||||
ZParams zparams = new ZParams().weights(weights).aggregate(ZParams.Aggregate.valueOf(aggregate.name()));
|
||||
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zinterstore(destKey, zparams, sets)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zinterstore(destKey, zparams, sets)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().zinterstore(destKey, zparams, sets);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zInterStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long zInterStore(byte[] destKey, byte[]... sets) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zinterstore(destKey, sets)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zinterstore(destKey, sets)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().zinterstore(destKey, sets);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRange(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRange(byte[] key, long start, long end) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zrange(key, start, end)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zrange(key, start, end)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().zrange(key, start, end);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeWithScores(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public Set<Tuple> zRangeWithScores(byte[] key, long start, long end) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zrangeWithScores(key, start, end),
|
||||
JedisConverters.tupleSetToTupleSet()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zrangeWithScores(key, start, end),
|
||||
JedisConverters.tupleSetToTupleSet()));
|
||||
return null;
|
||||
}
|
||||
return JedisConverters.toTupleSet(connection.getJedis().zrangeWithScores(key, start, end));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByLex(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)
|
||||
*/
|
||||
public Set<byte[]> zRangeByLex(byte[] key, Range range, Limit limit) {
|
||||
|
||||
Assert.notNull(range, "Range cannot be null for ZRANGEBYLEX.");
|
||||
|
||||
byte[] min = JedisConverters.boundaryToBytesForZRangeByLex(range.getMin(), JedisConverters.MINUS_BYTES);
|
||||
byte[] max = JedisConverters.boundaryToBytesForZRangeByLex(range.getMax(), JedisConverters.PLUS_BYTES);
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
if (limit != null) {
|
||||
pipeline(connection.newJedisResult(
|
||||
connection.getPipeline().zrangeByLex(key, min, max, limit.getOffset(), limit.getCount())));
|
||||
} else {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zrangeByLex(key, min, max)));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isQueueing()) {
|
||||
if (limit != null) {
|
||||
transaction(connection.newJedisResult(
|
||||
connection.getTransaction().zrangeByLex(key, min, max, limit.getOffset(), limit.getCount())));
|
||||
} else {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zrangeByLex(key, min, max)));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (limit != null) {
|
||||
return connection.getJedis().zrangeByLex(key, min, max, limit.getOffset(), limit.getCount());
|
||||
}
|
||||
return connection.getJedis().zrangeByLex(key, min, max);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByScore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRangeByScore(byte[] key, Range range, Limit limit) {
|
||||
|
||||
Assert.notNull(range, "Range cannot be null for ZRANGEBYSCORE.");
|
||||
|
||||
byte[] min = JedisConverters.boundaryToBytesForZRange(range.getMin(), JedisConverters.NEGATIVE_INFINITY_BYTES);
|
||||
byte[] max = JedisConverters.boundaryToBytesForZRange(range.getMax(), JedisConverters.POSITIVE_INFINITY_BYTES);
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
if (limit != null) {
|
||||
pipeline(connection.newJedisResult(
|
||||
connection.getPipeline().zrangeByScore(key, min, max, limit.getOffset(), limit.getCount())));
|
||||
} else {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zrangeByScore(key, min, max)));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isQueueing()) {
|
||||
if (limit != null) {
|
||||
transaction(connection.newJedisResult(
|
||||
connection.getTransaction().zrangeByScore(key, min, max, limit.getOffset(), limit.getCount())));
|
||||
} else {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zrangeByScore(key, min, max)));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (limit != null) {
|
||||
return connection.getJedis().zrangeByScore(key, min, max, limit.getOffset(), limit.getCount());
|
||||
}
|
||||
return connection.getJedis().zrangeByScore(key, min, max);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByScoreWithScores(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)
|
||||
*/
|
||||
@Override
|
||||
public Set<Tuple> zRangeByScoreWithScores(byte[] key, Range range, Limit limit) {
|
||||
|
||||
Assert.notNull(range, "Range cannot be null for ZRANGEBYSCOREWITHSCORES.");
|
||||
|
||||
byte[] min = JedisConverters.boundaryToBytesForZRange(range.getMin(), JedisConverters.NEGATIVE_INFINITY_BYTES);
|
||||
byte[] max = JedisConverters.boundaryToBytesForZRange(range.getMax(), JedisConverters.POSITIVE_INFINITY_BYTES);
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
if (limit != null) {
|
||||
pipeline(connection.newJedisResult(
|
||||
connection.getPipeline().zrangeByScoreWithScores(key, min, max, limit.getOffset(), limit.getCount()),
|
||||
JedisConverters.tupleSetToTupleSet()));
|
||||
} else {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zrangeByScoreWithScores(key, min, max),
|
||||
JedisConverters.tupleSetToTupleSet()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isQueueing()) {
|
||||
if (limit != null) {
|
||||
transaction(connection.newJedisResult(
|
||||
connection.getTransaction().zrangeByScoreWithScores(key, min, max, limit.getOffset(), limit.getCount()),
|
||||
JedisConverters.tupleSetToTupleSet()));
|
||||
} else {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zrangeByScoreWithScores(key, min, max),
|
||||
JedisConverters.tupleSetToTupleSet()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (limit != null) {
|
||||
return JedisConverters.toTupleSet(
|
||||
connection.getJedis().zrangeByScoreWithScores(key, min, max, limit.getOffset(), limit.getCount()));
|
||||
}
|
||||
return JedisConverters.toTupleSet(connection.getJedis().zrangeByScoreWithScores(key, min, max));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRangeWithScores(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public Set<Tuple> zRevRangeWithScores(byte[] key, long start, long end) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zrevrangeWithScores(key, start, end),
|
||||
JedisConverters.tupleSetToTupleSet()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zrevrangeWithScores(key, start, end),
|
||||
JedisConverters.tupleSetToTupleSet()));
|
||||
return null;
|
||||
}
|
||||
return JedisConverters.toTupleSet(connection.getJedis().zrevrangeWithScores(key, start, end));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRangeByScore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRevRangeByScore(byte[] key, Range range, Limit limit) {
|
||||
|
||||
Assert.notNull(range, "Range cannot be null for ZREVRANGEBYSCORE.");
|
||||
|
||||
byte[] min = JedisConverters.boundaryToBytesForZRange(range.getMin(), JedisConverters.NEGATIVE_INFINITY_BYTES);
|
||||
byte[] max = JedisConverters.boundaryToBytesForZRange(range.getMax(), JedisConverters.POSITIVE_INFINITY_BYTES);
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
if (limit != null) {
|
||||
pipeline(connection.newJedisResult(
|
||||
connection.getPipeline().zrevrangeByScore(key, max, min, limit.getOffset(), limit.getCount())));
|
||||
} else {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zrevrangeByScore(key, max, min)));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isQueueing()) {
|
||||
if (limit != null) {
|
||||
transaction(connection.newJedisResult(
|
||||
connection.getTransaction().zrevrangeByScore(key, max, min, limit.getOffset(), limit.getCount())));
|
||||
} else {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zrevrangeByScore(key, max, min)));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (limit != null) {
|
||||
return connection.getJedis().zrevrangeByScore(key, max, min, limit.getOffset(), limit.getCount());
|
||||
}
|
||||
return connection.getJedis().zrevrangeByScore(key, max, min);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRangeByScoreWithScores(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)
|
||||
*/
|
||||
@Override
|
||||
public Set<Tuple> zRevRangeByScoreWithScores(byte[] key, Range range, Limit limit) {
|
||||
|
||||
Assert.notNull(range, "Range cannot be null for ZREVRANGEBYSCOREWITHSCORES.");
|
||||
|
||||
byte[] min = JedisConverters.boundaryToBytesForZRange(range.getMin(), JedisConverters.NEGATIVE_INFINITY_BYTES);
|
||||
byte[] max = JedisConverters.boundaryToBytesForZRange(range.getMax(), JedisConverters.POSITIVE_INFINITY_BYTES);
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
if (limit != null) {
|
||||
pipeline(connection.newJedisResult(
|
||||
connection.getPipeline().zrevrangeByScoreWithScores(key, max, min, limit.getOffset(), limit.getCount()),
|
||||
JedisConverters.tupleSetToTupleSet()));
|
||||
} else {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zrevrangeByScoreWithScores(key, max, min),
|
||||
JedisConverters.tupleSetToTupleSet()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isQueueing()) {
|
||||
if (limit != null) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zrevrangeByScoreWithScores(key, max, min,
|
||||
limit.getOffset(), limit.getCount()), JedisConverters.tupleSetToTupleSet()));
|
||||
} else {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zrevrangeByScoreWithScores(key, max, min),
|
||||
JedisConverters.tupleSetToTupleSet()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (limit != null) {
|
||||
return JedisConverters.toTupleSet(
|
||||
connection.getJedis().zrevrangeByScoreWithScores(key, max, min, limit.getOffset(), limit.getCount()));
|
||||
}
|
||||
return JedisConverters.toTupleSet(connection.getJedis().zrevrangeByScoreWithScores(key, max, min));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRank(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long zRank(byte[] key, byte[] value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zrank(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zrank(key, value)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().zrank(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRem(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long zRem(byte[] key, byte[]... values) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zrem(key, values)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zrem(key, values)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().zrem(key, values);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRange(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public Long zRemRange(byte[] key, long start, long end) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zremrangeByRank(key, start, end)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zremrangeByRank(key, start, end)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().zremrangeByRank(key, start, end);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRangeByScore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
|
||||
*/
|
||||
@Override
|
||||
public Long zRemRangeByScore(byte[] key, Range range) {
|
||||
|
||||
Assert.notNull(range, "Range cannot be null for ZREMRANGEBYSCORE.");
|
||||
|
||||
byte[] min = JedisConverters.boundaryToBytesForZRange(range.getMin(), JedisConverters.NEGATIVE_INFINITY_BYTES);
|
||||
byte[] max = JedisConverters.boundaryToBytesForZRange(range.getMax(), JedisConverters.POSITIVE_INFINITY_BYTES);
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zremrangeByScore(key, min, max)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zremrangeByScore(key, min, max)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().zremrangeByScore(key, min, max);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRange(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRevRange(byte[] key, long start, long end) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zrevrange(key, start, end)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zrevrange(key, start, end)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().zrevrange(key, start, end);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRank(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long zRevRank(byte[] key, byte[] value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zrevrank(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zrevrank(key, value)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().zrevrank(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zScore(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Double zScore(byte[] key, byte[] value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zscore(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zscore(key, value)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().zscore(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zUnionStore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Aggregate, int[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long zUnionStore(byte[] destKey, Aggregate aggregate, int[] weights, byte[]... sets) {
|
||||
|
||||
try {
|
||||
ZParams zparams = new ZParams().weights(weights).aggregate(ZParams.Aggregate.valueOf(aggregate.name()));
|
||||
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zunionstore(destKey, zparams, sets)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zunionstore(destKey, zparams, sets)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().zunionstore(destKey, zparams, sets);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zUnionStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long zUnionStore(byte[] destKey, byte[]... sets) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zunionstore(destKey, sets)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zunionstore(destKey, sets)));
|
||||
return null;
|
||||
}
|
||||
return connection.getJedis().zunionstore(destKey, sets);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zScan(byte[], org.springframework.data.redis.core.ScanOptions)
|
||||
*/
|
||||
@Override
|
||||
public Cursor<Tuple> zScan(byte[] key, ScanOptions options) {
|
||||
return zScan(key, 0L, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.4
|
||||
* @param key
|
||||
* @param cursorId
|
||||
* @param options
|
||||
* @return
|
||||
*/
|
||||
public Cursor<Tuple> zScan(byte[] key, Long cursorId, ScanOptions options) {
|
||||
|
||||
return new KeyBoundCursor<Tuple>(key, cursorId, options) {
|
||||
|
||||
@Override
|
||||
protected ScanIteration<Tuple> doScan(byte[] key, long cursorId, ScanOptions options) {
|
||||
|
||||
if (isQueueing() || isPipelined()) {
|
||||
throw new UnsupportedOperationException("'ZSCAN' cannot be called in pipeline / transaction mode.");
|
||||
}
|
||||
|
||||
ScanParams params = JedisConverters.toScanParams(options);
|
||||
|
||||
ScanResult<redis.clients.jedis.Tuple> result = connection.getJedis().zscan(key,
|
||||
JedisConverters.toBytes(cursorId), params);
|
||||
return new ScanIteration<>(Long.valueOf(result.getStringCursor()),
|
||||
JedisConverters.tuplesToTuples().convert(result.getResult()));
|
||||
}
|
||||
|
||||
protected void doClose() {
|
||||
JedisZSetCommands.this.connection.close();
|
||||
};
|
||||
|
||||
}.open();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByScore(byte[], java.lang.String, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRangeByScore(byte[] key, String min, String max) {
|
||||
|
||||
try {
|
||||
String keyStr = new String(key, "UTF-8");
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newJedisResult(connection.getPipeline().zrangeByScore(keyStr, min, max)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newJedisResult(connection.getTransaction().zrangeByScore(keyStr, min, max)));
|
||||
return null;
|
||||
}
|
||||
return JedisConverters.stringSetToByteSet().convert(connection.getJedis().zrangeByScore(keyStr, min, max));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByScore(byte[], java.lang.String, java.lang.String, long, long)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRangeByScore(byte[] key, String min, String max, long offset, long count) {
|
||||
|
||||
if (offset > Integer.MAX_VALUE || count > Integer.MAX_VALUE) {
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
"Offset and count must be less than Integer.MAX_VALUE for zRangeByScore in Jedis.");
|
||||
}
|
||||
|
||||
try {
|
||||
String keyStr = new String(key, "UTF-8");
|
||||
if (isPipelined()) {
|
||||
pipeline(connection
|
||||
.newJedisResult(connection.getPipeline().zrangeByScore(keyStr, min, max, (int) offset, (int) count)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection
|
||||
.newJedisResult(connection.getTransaction().zrangeByScore(keyStr, min, max, (int) offset, (int) count)));
|
||||
return null;
|
||||
}
|
||||
return JedisConverters.stringSetToByteSet()
|
||||
.convert(connection.getJedis().zrangeByScore(keyStr, min, max, (int) offset, (int) count));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<byte[], Double> zAddArgs(Set<Tuple> tuples) {
|
||||
|
||||
Map<byte[], Double> args = new LinkedHashMap<>(tuples.size(), 1);
|
||||
Set<Double> scores = new HashSet<Double>(tuples.size(), 1);
|
||||
|
||||
boolean isAtLeastJedis24 = JedisVersionUtil.atLeastJedis24();
|
||||
|
||||
for (Tuple tuple : tuples) {
|
||||
|
||||
if (!isAtLeastJedis24) {
|
||||
if (scores.contains(tuple.getScore())) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Bulk add of multiple elements with the same score is not supported. Add the elements individually.");
|
||||
}
|
||||
scores.add(tuple.getScore());
|
||||
}
|
||||
|
||||
args.put(tuple.getValue(), tuple.getScore());
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import io.lettuce.core.KeyValue;
|
||||
import io.lettuce.core.RedisException;
|
||||
import io.lettuce.core.api.StatefulConnection;
|
||||
import io.lettuce.core.cluster.RedisClusterClient;
|
||||
@@ -27,17 +26,13 @@ import io.lettuce.core.codec.ByteArrayCodec;
|
||||
import io.lettuce.core.codec.RedisCodec;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
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.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
@@ -51,18 +46,20 @@ import org.springframework.data.redis.connection.ClusterCommandExecutor.MultiKey
|
||||
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.ClusterSlotHashUtil;
|
||||
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.SortParameters;
|
||||
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.connection.util.ByteArraySet;
|
||||
import org.springframework.data.redis.core.Cursor;
|
||||
import org.springframework.data.redis.core.ScanOptions;
|
||||
import org.springframework.data.redis.core.types.RedisClientInfo;
|
||||
import org.springframework.data.redis.util.ByteUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
@@ -119,39 +116,48 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
clusterCommandExecutor = executor;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#scan(long, org.springframework.data.redis.core.ScanOptions)
|
||||
*/
|
||||
@Override
|
||||
public Cursor<byte[]> scan(long cursorId, ScanOptions options) {
|
||||
throw new InvalidDataAccessApiUsageException("Scan is not supported accros multiple nodes within a cluster.");
|
||||
public RedisGeoCommands geoCommands() {
|
||||
return new LettuceClusterGeoCommands(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#keys(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> keys(final byte[] pattern) {
|
||||
public RedisHashCommands hashCommands() {
|
||||
return new LettuceClusterHashCommands(this);
|
||||
}
|
||||
|
||||
Assert.notNull(pattern, "Pattern must not be null!");
|
||||
@Override
|
||||
public RedisHyperLogLogCommands hyperLogLogCommands() {
|
||||
return new LettuceClusterHyperLogLogCommands(this);
|
||||
}
|
||||
|
||||
Collection<List<byte[]>> keysPerNode = clusterCommandExecutor
|
||||
.executeCommandOnAllNodes(new LettuceClusterCommandCallback<List<byte[]>>() {
|
||||
@Override
|
||||
public RedisKeyCommands keyCommands() {
|
||||
return doGetClusterKeyCommands();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<byte[]> doInCluster(RedisClusterCommands<byte[], byte[]> connection) {
|
||||
return connection.keys(pattern);
|
||||
}
|
||||
}).resultsAsList();
|
||||
private LettuceClusterKeyCommands doGetClusterKeyCommands() {
|
||||
return new LettuceClusterKeyCommands(this);
|
||||
}
|
||||
|
||||
Set<byte[]> keys = new HashSet<byte[]>();
|
||||
@Override
|
||||
public RedisListCommands listCommands() {
|
||||
return new LettuceClusterListCommands(this);
|
||||
}
|
||||
|
||||
for (List<byte[]> keySet : keysPerNode) {
|
||||
keys.addAll(keySet);
|
||||
}
|
||||
return keys;
|
||||
@Override
|
||||
public RedisStringCommands stringCommands() {
|
||||
return new LettuceClusterStringCommands(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RedisSetCommands setCommands() {
|
||||
return new LettuceClusterSetCommands(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RedisZSetCommands zSetCommands() {
|
||||
return new LettuceClusterZSetCommands(this);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -280,28 +286,6 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
}, node).getValue());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#move(byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public Boolean move(byte[] key, int dbIndex) {
|
||||
throw new UnsupportedOperationException("MOVE not supported in CLUSTER mode!");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#del(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long del(byte[]... keys) {
|
||||
|
||||
Assert.noNullElements(keys, "Keys must not be null or contain null key!");
|
||||
|
||||
// Routing for mget is handled by lettuce.
|
||||
return super.del(keys);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisClusterCommands#getClusterSlaves(org.springframework.data.redis.connection.RedisClusterNode)
|
||||
@@ -722,102 +706,11 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> keys(RedisClusterNode node, final byte[] pattern) {
|
||||
|
||||
return LettuceConverters.toBytesSet(
|
||||
clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<List<byte[]>>() {
|
||||
|
||||
@Override
|
||||
public List<byte[]> doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.keys(pattern);
|
||||
}
|
||||
}, node).getValue());
|
||||
return doGetClusterKeyCommands().keys(node, pattern);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisClusterConnection#randomKey(org.springframework.data.redis.connection.RedisClusterNode)
|
||||
*/
|
||||
@Override
|
||||
public byte[] randomKey(RedisClusterNode node) {
|
||||
|
||||
return clusterCommandExecutor.executeCommandOnSingleNode(new LettuceClusterCommandCallback<byte[]>() {
|
||||
|
||||
@Override
|
||||
public byte[] doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.randomkey();
|
||||
}
|
||||
}, node).getValue();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#randomKey()
|
||||
*/
|
||||
@Override
|
||||
public byte[] randomKey() {
|
||||
|
||||
List<RedisClusterNode> nodes = clusterGetNodes();
|
||||
Set<RedisClusterNode> inspectedNodes = new HashSet<RedisClusterNode>(nodes.size());
|
||||
|
||||
do {
|
||||
|
||||
RedisClusterNode node = nodes.get(new Random().nextInt(nodes.size()));
|
||||
|
||||
while (inspectedNodes.contains(node)) {
|
||||
node = nodes.get(new Random().nextInt(nodes.size()));
|
||||
}
|
||||
inspectedNodes.add(node);
|
||||
byte[] key = randomKey(node);
|
||||
|
||||
if (key != null && key.length > 0) {
|
||||
return key;
|
||||
}
|
||||
} while (nodes.size() != inspectedNodes.size());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#rename(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public void rename(byte[] oldName, byte[] newName) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(oldName, newName)) {
|
||||
super.rename(oldName, newName);
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] value = dump(oldName);
|
||||
|
||||
if (value != null && value.length > 0) {
|
||||
|
||||
restore(newName, 0, value);
|
||||
del(oldName);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#renameNX(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean renameNX(byte[] oldName, byte[] newName) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(oldName, newName)) {
|
||||
return super.renameNX(oldName, newName);
|
||||
}
|
||||
|
||||
byte[] value = dump(oldName);
|
||||
|
||||
if (value != null && value.length > 0 && !exists(newName)) {
|
||||
|
||||
restore(newName, 0, value);
|
||||
del(oldName);
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
return doGetClusterKeyCommands().randomKey(node);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -837,176 +730,6 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
}, node);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#sort(byte[], org.springframework.data.redis.connection.SortParameters, byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long sort(byte[] key, SortParameters params, byte[] storeKey) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(key, storeKey)) {
|
||||
return super.sort(key, params, storeKey);
|
||||
}
|
||||
|
||||
List<byte[]> sorted = sort(key, params);
|
||||
if (!CollectionUtils.isEmpty(sorted)) {
|
||||
|
||||
byte[][] arr = new byte[sorted.size()][];
|
||||
switch (type(key)) {
|
||||
|
||||
case SET:
|
||||
sAdd(storeKey, sorted.toArray(arr));
|
||||
return 1L;
|
||||
case LIST:
|
||||
lPush(storeKey, sorted.toArray(arr));
|
||||
return 1L;
|
||||
default:
|
||||
throw new IllegalArgumentException("sort and store is only supported for SET and LIST");
|
||||
}
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#mGet(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> mGet(byte[]... keys) {
|
||||
|
||||
Assert.notNull(keys, "Keys must not be null!");
|
||||
|
||||
// Routing for mget is handled by lettuce.
|
||||
return super.mGet(keys);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#mSet(java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public void mSet(Map<byte[], byte[]> tuples) {
|
||||
|
||||
Assert.notNull(tuples, "Tuples must not be null!");
|
||||
|
||||
// Routing for mset is handled by lettuce.
|
||||
super.mSet(tuples);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#mSetNX(java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public Boolean mSetNX(Map<byte[], byte[]> tuples) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(tuples.keySet().toArray(new byte[tuples.keySet().size()][]))) {
|
||||
return super.mSetNX(tuples);
|
||||
}
|
||||
|
||||
boolean result = true;
|
||||
for (Map.Entry<byte[], byte[]> entry : tuples.entrySet()) {
|
||||
if (!setNX(entry.getKey(), entry.getValue()) && result) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#bLPop(int, byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> bLPop(final int timeout, byte[]... keys) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
return super.bLPop(timeout, keys);
|
||||
}
|
||||
|
||||
List<KeyValue<byte[], byte[]>> resultList = this.clusterCommandExecutor
|
||||
.executeMuliKeyCommand(new LettuceMultiKeyClusterCommandCallback<KeyValue<byte[], byte[]>>() {
|
||||
|
||||
@Override
|
||||
public KeyValue<byte[], byte[]> doInCluster(RedisClusterCommands<byte[], byte[]> client, byte[] key) {
|
||||
return client.blpop(timeout, key);
|
||||
}
|
||||
}, Arrays.asList(keys)).resultsAsList();
|
||||
|
||||
for (KeyValue<byte[], byte[]> kv : resultList) {
|
||||
if (kv != null) {
|
||||
return LettuceConverters.toBytesList(kv);
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#bRPop(int, byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> bRPop(final int timeout, byte[]... keys) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
return super.bRPop(timeout, keys);
|
||||
}
|
||||
|
||||
List<KeyValue<byte[], byte[]>> resultList = this.clusterCommandExecutor
|
||||
.executeMuliKeyCommand(new LettuceMultiKeyClusterCommandCallback<KeyValue<byte[], byte[]>>() {
|
||||
|
||||
@Override
|
||||
public KeyValue<byte[], byte[]> doInCluster(RedisClusterCommands<byte[], byte[]> client, byte[] key) {
|
||||
return client.brpop(timeout, key);
|
||||
}
|
||||
}, Arrays.asList(keys)).resultsAsList();
|
||||
|
||||
for (KeyValue<byte[], byte[]> kv : resultList) {
|
||||
if (kv != null) {
|
||||
return LettuceConverters.toBytesList(kv);
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#rPopLPush(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] rPopLPush(byte[] srcKey, byte[] dstKey) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(srcKey, dstKey)) {
|
||||
return super.rPopLPush(srcKey, dstKey);
|
||||
}
|
||||
|
||||
byte[] val = rPop(srcKey);
|
||||
lPush(dstKey, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#bRPopLPush(int, byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] bRPopLPush(int timeout, byte[] srcKey, byte[] dstKey) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(srcKey, dstKey)) {
|
||||
return super.bRPopLPush(timeout, srcKey, dstKey);
|
||||
}
|
||||
|
||||
List<byte[]> val = bRPop(timeout, srcKey);
|
||||
if (!CollectionUtils.isEmpty(val)) {
|
||||
lPush(dstKey, val.get(1));
|
||||
return val.get(1);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisConnectionCommands#select(int)
|
||||
@@ -1019,194 +742,6 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#sMove(byte[], byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean sMove(byte[] srcKey, byte[] destKey, byte[] value) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(srcKey, destKey)) {
|
||||
return super.sMove(srcKey, destKey, value);
|
||||
}
|
||||
|
||||
if (exists(srcKey)) {
|
||||
if (sRem(srcKey, value) > 0 && !sIsMember(destKey, value)) {
|
||||
return LettuceConverters.toBoolean(sAdd(destKey, value));
|
||||
}
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#sInter(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> sInter(byte[]... keys) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
return super.sInter(keys);
|
||||
}
|
||||
|
||||
Collection<Set<byte[]>> nodeResult = this.clusterCommandExecutor
|
||||
.executeMuliKeyCommand(new LettuceMultiKeyClusterCommandCallback<Set<byte[]>>() {
|
||||
|
||||
@Override
|
||||
public Set<byte[]> doInCluster(RedisClusterCommands<byte[], byte[]> client, byte[] key) {
|
||||
return client.smembers(key);
|
||||
}
|
||||
}, Arrays.asList(keys)).resultsAsList();
|
||||
|
||||
ByteArraySet result = null;
|
||||
for (Set<byte[]> entry : nodeResult) {
|
||||
|
||||
ByteArraySet tmp = new ByteArraySet(entry);
|
||||
if (result == null) {
|
||||
result = tmp;
|
||||
} else {
|
||||
result.retainAll(tmp);
|
||||
if (result.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
return result.asRawSet();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#sInterStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sInterStore(byte[] destKey, byte[]... keys) {
|
||||
|
||||
byte[][] allKeys = ByteUtils.mergeArrays(destKey, keys);
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(allKeys)) {
|
||||
return super.sInterStore(destKey, keys);
|
||||
}
|
||||
|
||||
Set<byte[]> result = sInter(keys);
|
||||
if (result.isEmpty()) {
|
||||
return 0L;
|
||||
}
|
||||
return sAdd(destKey, result.toArray(new byte[result.size()][]));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#sUnion(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> sUnion(byte[]... keys) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
return super.sUnion(keys);
|
||||
}
|
||||
|
||||
Collection<Set<byte[]>> nodeResult = this.clusterCommandExecutor
|
||||
.executeMuliKeyCommand(new LettuceMultiKeyClusterCommandCallback<Set<byte[]>>() {
|
||||
|
||||
@Override
|
||||
public Set<byte[]> doInCluster(RedisClusterCommands<byte[], byte[]> client, byte[] key) {
|
||||
return client.smembers(key);
|
||||
}
|
||||
}, Arrays.asList(keys)).resultsAsList();
|
||||
|
||||
ByteArraySet result = new ByteArraySet();
|
||||
for (Set<byte[]> entry : nodeResult) {
|
||||
result.addAll(entry);
|
||||
}
|
||||
|
||||
if (result.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
return result.asRawSet();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#sUnionStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sUnionStore(byte[] destKey, byte[]... keys) {
|
||||
|
||||
byte[][] allKeys = ByteUtils.mergeArrays(destKey, keys);
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(allKeys)) {
|
||||
return super.sUnionStore(destKey, keys);
|
||||
}
|
||||
|
||||
Set<byte[]> result = sUnion(keys);
|
||||
if (result.isEmpty()) {
|
||||
return 0L;
|
||||
}
|
||||
return sAdd(destKey, result.toArray(new byte[result.size()][]));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#sDiff(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> sDiff(byte[]... keys) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
return super.sDiff(keys);
|
||||
}
|
||||
|
||||
byte[] source = keys[0];
|
||||
byte[][] others = Arrays.copyOfRange(keys, 1, keys.length - 1);
|
||||
|
||||
ByteArraySet values = new ByteArraySet(sMembers(source));
|
||||
Collection<Set<byte[]>> nodeResult = clusterCommandExecutor
|
||||
.executeMuliKeyCommand(new LettuceMultiKeyClusterCommandCallback<Set<byte[]>>() {
|
||||
|
||||
@Override
|
||||
public Set<byte[]> doInCluster(RedisClusterCommands<byte[], byte[]> client, byte[] key) {
|
||||
return client.smembers(key);
|
||||
}
|
||||
}, Arrays.asList(others)).resultsAsList();
|
||||
|
||||
if (values.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
for (Set<byte[]> toSubstract : nodeResult) {
|
||||
values.removeAll(toSubstract);
|
||||
}
|
||||
|
||||
return values.asRawSet();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#sDiffStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sDiffStore(byte[] destKey, byte[]... keys) {
|
||||
|
||||
byte[][] allKeys = ByteUtils.mergeArrays(destKey, keys);
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(allKeys)) {
|
||||
return super.sDiffStore(destKey, keys);
|
||||
}
|
||||
|
||||
Set<byte[]> diff = sDiff(keys);
|
||||
if (diff.isEmpty()) {
|
||||
return 0L;
|
||||
}
|
||||
|
||||
return sAdd(destKey, diff.toArray(new byte[diff.size()][]));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#getAsyncDedicatedConnection()
|
||||
@@ -1227,46 +762,6 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
return LettuceConverters.partitionsToClusterNodes(clusterClient.getPartitions());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#pfCount(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long pfCount(byte[]... keys) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
|
||||
try {
|
||||
return super.pfCount(keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
throw new InvalidDataAccessApiUsageException("All keys must map to same slot for pfcount in cluster mode.");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#pfMerge(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public void pfMerge(byte[] destinationKey, byte[]... sourceKeys) {
|
||||
|
||||
byte[][] allKeys = ByteUtils.mergeArrays(destinationKey, sourceKeys);
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(allKeys)) {
|
||||
try {
|
||||
super.pfMerge(destinationKey, sourceKeys);
|
||||
return;
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
throw new InvalidDataAccessApiUsageException("All keys must map to same slot for pfmerge in cluster mode.");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#watch(byte[][])
|
||||
@@ -1513,6 +1008,10 @@ public class LettuceClusterConnection extends LettuceConnection
|
||||
return result;
|
||||
}
|
||||
|
||||
public ClusterCommandExecutor getClusterCommandExecutor() {
|
||||
return clusterCommandExecutor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lettuce specific implementation of {@link ClusterCommandCallback}.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class LettuceClusterGeoCommands extends LettuceGeoCommands {
|
||||
|
||||
public LettuceClusterGeoCommands(LettuceClusterConnection connection) {
|
||||
super(connection);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class LettuceClusterHashCommands extends LettuceHashCommands {
|
||||
|
||||
public LettuceClusterHashCommands(LettuceClusterConnection connection) {
|
||||
super(connection);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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 org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.redis.connection.ClusterSlotHashUtil;
|
||||
import org.springframework.data.redis.util.ByteUtils;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class LettuceClusterHyperLogLogCommands extends LettuceHyperLogLogCommands {
|
||||
|
||||
public LettuceClusterHyperLogLogCommands(LettuceClusterConnection connection) {
|
||||
super(connection);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#pfCount(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long pfCount(byte[]... keys) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
|
||||
try {
|
||||
return super.pfCount(keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
throw new InvalidDataAccessApiUsageException("All keys must map to same slot for pfcount in cluster mode.");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#pfMerge(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public void pfMerge(byte[] destinationKey, byte[]... sourceKeys) {
|
||||
|
||||
byte[][] allKeys = ByteUtils.mergeArrays(destinationKey, sourceKeys);
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(allKeys)) {
|
||||
try {
|
||||
super.pfMerge(destinationKey, sourceKeys);
|
||||
return;
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
throw new InvalidDataAccessApiUsageException("All keys must map to same slot for pfmerge in cluster mode.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* 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.sync.RedisClusterCommands;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.redis.connection.ClusterSlotHashUtil;
|
||||
import org.springframework.data.redis.connection.RedisClusterNode;
|
||||
import org.springframework.data.redis.connection.SortParameters;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceClusterConnection.LettuceClusterCommandCallback;
|
||||
import org.springframework.data.redis.core.Cursor;
|
||||
import org.springframework.data.redis.core.ScanOptions;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class LettuceClusterKeyCommands extends LettuceKeyCommands {
|
||||
|
||||
private final LettuceClusterConnection connection;
|
||||
|
||||
public LettuceClusterKeyCommands(LettuceClusterConnection connection) {
|
||||
|
||||
super(connection);
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#scan(long, org.springframework.data.redis.core.ScanOptions)
|
||||
*/
|
||||
@Override
|
||||
public Cursor<byte[]> scan(long cursorId, ScanOptions options) {
|
||||
throw new InvalidDataAccessApiUsageException("Scan is not supported accros multiple nodes within a cluster.");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#randomKey()
|
||||
*/
|
||||
@Override
|
||||
public byte[] randomKey() {
|
||||
|
||||
List<RedisClusterNode> nodes = connection.clusterGetNodes();
|
||||
Set<RedisClusterNode> inspectedNodes = new HashSet<>(nodes.size());
|
||||
|
||||
do {
|
||||
|
||||
RedisClusterNode node = nodes.get(new Random().nextInt(nodes.size()));
|
||||
|
||||
while (inspectedNodes.contains(node)) {
|
||||
node = nodes.get(new Random().nextInt(nodes.size()));
|
||||
}
|
||||
inspectedNodes.add(node);
|
||||
byte[] key = randomKey(node);
|
||||
|
||||
if (key != null && key.length > 0) {
|
||||
return key;
|
||||
}
|
||||
} while (nodes.size() != inspectedNodes.size());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#keys(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> keys(final byte[] pattern) {
|
||||
|
||||
Assert.notNull(pattern, "Pattern must not be null!");
|
||||
|
||||
Collection<List<byte[]>> keysPerNode = connection.getClusterCommandExecutor()
|
||||
.executeCommandOnAllNodes((LettuceClusterCommandCallback<List<byte[]>>) connection -> connection.keys(pattern))
|
||||
.resultsAsList();
|
||||
|
||||
Set<byte[]> keys = new HashSet<>();
|
||||
|
||||
for (List<byte[]> keySet : keysPerNode) {
|
||||
keys.addAll(keySet);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#rename(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public void rename(byte[] oldName, byte[] newName) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(oldName, newName)) {
|
||||
super.rename(oldName, newName);
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] value = dump(oldName);
|
||||
|
||||
if (value != null && value.length > 0) {
|
||||
|
||||
restore(newName, 0, value);
|
||||
del(oldName);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#renameNX(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean renameNX(byte[] oldName, byte[] newName) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(oldName, newName)) {
|
||||
return super.renameNX(oldName, newName);
|
||||
}
|
||||
|
||||
byte[] value = dump(oldName);
|
||||
|
||||
if (value != null && value.length > 0 && !exists(newName)) {
|
||||
|
||||
restore(newName, 0, value);
|
||||
del(oldName);
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#move(byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public Boolean move(byte[] key, int dbIndex) {
|
||||
throw new UnsupportedOperationException("MOVE not supported in CLUSTER mode!");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#del(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long del(byte[]... keys) {
|
||||
|
||||
Assert.noNullElements(keys, "Keys must not be null or contain null key!");
|
||||
|
||||
// Routing for mget is handled by lettuce.
|
||||
return super.del(keys);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisClusterConnection#randomKey(org.springframework.data.redis.connection.RedisClusterNode)
|
||||
*/
|
||||
public byte[] randomKey(RedisClusterNode node) {
|
||||
|
||||
return connection.getClusterCommandExecutor()
|
||||
.executeCommandOnSingleNode(new LettuceClusterCommandCallback<byte[]>() {
|
||||
|
||||
@Override
|
||||
public byte[] doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.randomkey();
|
||||
}
|
||||
}, node).getValue();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisClusterConnection#keys(org.springframework.data.redis.connection.RedisClusterNode, byte[])
|
||||
*/
|
||||
public Set<byte[]> keys(RedisClusterNode node, final byte[] pattern) {
|
||||
|
||||
return LettuceConverters.toBytesSet(connection.getClusterCommandExecutor()
|
||||
.executeCommandOnSingleNode(new LettuceClusterCommandCallback<List<byte[]>>() {
|
||||
|
||||
@Override
|
||||
public List<byte[]> doInCluster(RedisClusterCommands<byte[], byte[]> client) {
|
||||
return client.keys(pattern);
|
||||
}
|
||||
}, node).getValue());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#sort(byte[], org.springframework.data.redis.connection.SortParameters, byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long sort(byte[] key, SortParameters params, byte[] storeKey) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(key, storeKey)) {
|
||||
return super.sort(key, params, storeKey);
|
||||
}
|
||||
|
||||
List<byte[]> sorted = sort(key, params);
|
||||
if (!CollectionUtils.isEmpty(sorted)) {
|
||||
|
||||
byte[][] arr = new byte[sorted.size()][];
|
||||
switch (type(key)) {
|
||||
|
||||
case SET:
|
||||
connection.setCommands().sAdd(storeKey, sorted.toArray(arr));
|
||||
return 1L;
|
||||
case LIST:
|
||||
connection.listCommands().lPush(storeKey, sorted.toArray(arr));
|
||||
return 1L;
|
||||
default:
|
||||
throw new IllegalArgumentException("sort and store is only supported for SET and LIST");
|
||||
}
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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.KeyValue;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.redis.connection.ClusterSlotHashUtil;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceClusterConnection.LettuceMultiKeyClusterCommandCallback;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class LettuceClusterListCommands extends LettuceListCommands {
|
||||
|
||||
private final LettuceClusterConnection connection;
|
||||
|
||||
public LettuceClusterListCommands(LettuceClusterConnection connection) {
|
||||
|
||||
super(connection);
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#bLPop(int, byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> bLPop(final int timeout, byte[]... keys) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
return super.bLPop(timeout, keys);
|
||||
}
|
||||
|
||||
List<KeyValue<byte[], byte[]>> resultList = connection.getClusterCommandExecutor().executeMuliKeyCommand(
|
||||
(LettuceMultiKeyClusterCommandCallback<KeyValue<byte[], byte[]>>) (client, key) -> client.blpop(timeout, key),
|
||||
Arrays.asList(keys)).resultsAsList();
|
||||
|
||||
for (KeyValue<byte[], byte[]> kv : resultList) {
|
||||
if (kv != null) {
|
||||
return LettuceConverters.toBytesList(kv);
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#bRPop(int, byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> bRPop(final int timeout, byte[]... keys) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
return super.bRPop(timeout, keys);
|
||||
}
|
||||
|
||||
List<KeyValue<byte[], byte[]>> resultList = connection.getClusterCommandExecutor().executeMuliKeyCommand(
|
||||
(LettuceMultiKeyClusterCommandCallback<KeyValue<byte[], byte[]>>) (client, key) -> client.brpop(timeout, key),
|
||||
Arrays.asList(keys)).resultsAsList();
|
||||
|
||||
for (KeyValue<byte[], byte[]> kv : resultList) {
|
||||
if (kv != null) {
|
||||
return LettuceConverters.toBytesList(kv);
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#rPopLPush(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] rPopLPush(byte[] srcKey, byte[] dstKey) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(srcKey, dstKey)) {
|
||||
return super.rPopLPush(srcKey, dstKey);
|
||||
}
|
||||
|
||||
byte[] val = rPop(srcKey);
|
||||
lPush(dstKey, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#bRPopLPush(int, byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] bRPopLPush(int timeout, byte[] srcKey, byte[] dstKey) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(srcKey, dstKey)) {
|
||||
return super.bRPopLPush(timeout, srcKey, dstKey);
|
||||
}
|
||||
|
||||
List<byte[]> val = bRPop(timeout, srcKey);
|
||||
if (!CollectionUtils.isEmpty(val)) {
|
||||
lPush(dstKey, val.get(1));
|
||||
return val.get(1);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.redis.connection.ClusterSlotHashUtil;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceClusterConnection.LettuceMultiKeyClusterCommandCallback;
|
||||
import org.springframework.data.redis.connection.util.ByteArraySet;
|
||||
import org.springframework.data.redis.util.ByteUtils;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class LettuceClusterSetCommands extends LettuceSetCommands {
|
||||
|
||||
private final LettuceClusterConnection connection;
|
||||
|
||||
public LettuceClusterSetCommands(LettuceClusterConnection connection) {
|
||||
|
||||
super(connection);
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#sMove(byte[], byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean sMove(byte[] srcKey, byte[] destKey, byte[] value) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(srcKey, destKey)) {
|
||||
return super.sMove(srcKey, destKey, value);
|
||||
}
|
||||
|
||||
if (connection.keyCommands().exists(srcKey)) {
|
||||
if (sRem(srcKey, value) > 0 && !sIsMember(destKey, value)) {
|
||||
return LettuceConverters.toBoolean(sAdd(destKey, value));
|
||||
}
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#sInter(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> sInter(byte[]... keys) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
return super.sInter(keys);
|
||||
}
|
||||
|
||||
Collection<Set<byte[]>> nodeResult = connection.getClusterCommandExecutor()
|
||||
.executeMuliKeyCommand(
|
||||
(LettuceMultiKeyClusterCommandCallback<Set<byte[]>>) (client, key) -> client.smembers(key),
|
||||
Arrays.asList(keys))
|
||||
.resultsAsList();
|
||||
|
||||
ByteArraySet result = null;
|
||||
for (Set<byte[]> entry : nodeResult) {
|
||||
|
||||
ByteArraySet tmp = new ByteArraySet(entry);
|
||||
if (result == null) {
|
||||
result = tmp;
|
||||
} else {
|
||||
result.retainAll(tmp);
|
||||
if (result.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
return result.asRawSet();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#sInterStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sInterStore(byte[] destKey, byte[]... keys) {
|
||||
|
||||
byte[][] allKeys = ByteUtils.mergeArrays(destKey, keys);
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(allKeys)) {
|
||||
return super.sInterStore(destKey, keys);
|
||||
}
|
||||
|
||||
Set<byte[]> result = sInter(keys);
|
||||
if (result.isEmpty()) {
|
||||
return 0L;
|
||||
}
|
||||
return sAdd(destKey, result.toArray(new byte[result.size()][]));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#sUnion(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> sUnion(byte[]... keys) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
return super.sUnion(keys);
|
||||
}
|
||||
|
||||
Collection<Set<byte[]>> nodeResult = connection.getClusterCommandExecutor()
|
||||
.executeMuliKeyCommand(
|
||||
(LettuceMultiKeyClusterCommandCallback<Set<byte[]>>) (client, key) -> client.smembers(key),
|
||||
Arrays.asList(keys))
|
||||
.resultsAsList();
|
||||
|
||||
ByteArraySet result = new ByteArraySet();
|
||||
for (Set<byte[]> entry : nodeResult) {
|
||||
result.addAll(entry);
|
||||
}
|
||||
|
||||
if (result.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
return result.asRawSet();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#sUnionStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sUnionStore(byte[] destKey, byte[]... keys) {
|
||||
|
||||
byte[][] allKeys = ByteUtils.mergeArrays(destKey, keys);
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(allKeys)) {
|
||||
return super.sUnionStore(destKey, keys);
|
||||
}
|
||||
|
||||
Set<byte[]> result = sUnion(keys);
|
||||
if (result.isEmpty()) {
|
||||
return 0L;
|
||||
}
|
||||
return sAdd(destKey, result.toArray(new byte[result.size()][]));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#sDiff(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> sDiff(byte[]... keys) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
|
||||
return super.sDiff(keys);
|
||||
}
|
||||
|
||||
byte[] source = keys[0];
|
||||
byte[][] others = Arrays.copyOfRange(keys, 1, keys.length - 1);
|
||||
|
||||
ByteArraySet values = new ByteArraySet(sMembers(source));
|
||||
Collection<Set<byte[]>> nodeResult = connection.getClusterCommandExecutor()
|
||||
.executeMuliKeyCommand(
|
||||
(LettuceMultiKeyClusterCommandCallback<Set<byte[]>>) (client, key) -> client.smembers(key),
|
||||
Arrays.asList(others))
|
||||
.resultsAsList();
|
||||
|
||||
if (values.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
for (Set<byte[]> toSubstract : nodeResult) {
|
||||
values.removeAll(toSubstract);
|
||||
}
|
||||
|
||||
return values.asRawSet();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#sDiffStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sDiffStore(byte[] destKey, byte[]... keys) {
|
||||
|
||||
byte[][] allKeys = ByteUtils.mergeArrays(destKey, keys);
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(allKeys)) {
|
||||
return super.sDiffStore(destKey, keys);
|
||||
}
|
||||
|
||||
Set<byte[]> diff = sDiff(keys);
|
||||
if (diff.isEmpty()) {
|
||||
return 0L;
|
||||
}
|
||||
|
||||
return sAdd(destKey, diff.toArray(new byte[diff.size()][]));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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 java.util.Map;
|
||||
|
||||
import org.springframework.data.redis.connection.ClusterSlotHashUtil;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class LettuceClusterStringCommands extends LettuceStringCommands {
|
||||
|
||||
private final LettuceClusterConnection connection;
|
||||
|
||||
public LettuceClusterStringCommands(LettuceClusterConnection connection) {
|
||||
|
||||
super(connection);
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#mSetNX(java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public Boolean mSetNX(Map<byte[], byte[]> tuples) {
|
||||
|
||||
if (ClusterSlotHashUtil.isSameSlotForAllKeys(tuples.keySet().toArray(new byte[tuples.keySet().size()][]))) {
|
||||
return super.mSetNX(tuples);
|
||||
}
|
||||
|
||||
boolean result = true;
|
||||
for (Map.Entry<byte[], byte[]> entry : tuples.entrySet()) {
|
||||
if (!setNX(entry.getKey(), entry.getValue()) && result) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class LettuceClusterZSetCommands extends LettuceZSetCommands {
|
||||
|
||||
public LettuceClusterZSetCommands(LettuceClusterConnection connection) {
|
||||
super(connection);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,452 @@
|
||||
/*
|
||||
* 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.GeoArgs;
|
||||
import io.lettuce.core.GeoCoordinates;
|
||||
import io.lettuce.core.GeoWithin;
|
||||
import io.lettuce.core.cluster.api.async.RedisClusterAsyncCommands;
|
||||
import io.lettuce.core.cluster.api.sync.RedisClusterCommands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.geo.Circle;
|
||||
import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.GeoResults;
|
||||
import org.springframework.data.geo.Metric;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands;
|
||||
import org.springframework.data.redis.connection.convert.ListConverter;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceResult;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceTxResult;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class LettuceGeoCommands implements RedisGeoCommands {
|
||||
|
||||
private final LettuceConnection connection;
|
||||
|
||||
public LettuceGeoCommands(LettuceConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoAdd(byte[], org.springframework.data.geo.Point, byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long geoAdd(byte[] key, Point point, byte[] member) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(point, "Point must not be null!");
|
||||
Assert.notNull(member, "Member must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().geoadd(key, point.getX(), point.getY(), member)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().geoadd(key, point.getX(), point.getY(), member)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().geoadd(key, point.getX(), point.getY(), member);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoAdd(byte[], org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation)
|
||||
*/
|
||||
@Override
|
||||
public Long geoAdd(byte[] key, GeoLocation<byte[]> location) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(location, "Location must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().geoadd(key, location.getPoint().getX(),
|
||||
location.getPoint().getY(), location.getName())));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(
|
||||
getConnection().geoadd(key, location.getPoint().getX(), location.getPoint().getY(), location.getName())));
|
||||
return null;
|
||||
}
|
||||
return getConnection().geoadd(key, location.getPoint().getX(), location.getPoint().getY(), location.getName());
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoAdd(byte[], java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public Long geoAdd(byte[] key, Map<byte[], Point> memberCoordinateMap) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(memberCoordinateMap, "MemberCoordinateMap must not be null!");
|
||||
|
||||
List<Object> values = new ArrayList<Object>();
|
||||
for (Entry<byte[], Point> entry : memberCoordinateMap.entrySet()) {
|
||||
|
||||
values.add(entry.getValue().getX());
|
||||
values.add(entry.getValue().getY());
|
||||
values.add(entry.getKey());
|
||||
}
|
||||
|
||||
return geoAdd(key, values);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoAdd(byte[], java.lang.Iterable)
|
||||
*/
|
||||
@Override
|
||||
public Long geoAdd(byte[] key, Iterable<GeoLocation<byte[]>> locations) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(locations, "Locations must not be null!");
|
||||
|
||||
List<Object> values = new ArrayList<Object>();
|
||||
for (GeoLocation<byte[]> location : locations) {
|
||||
|
||||
values.add(location.getPoint().getX());
|
||||
values.add(location.getPoint().getY());
|
||||
values.add(location.getName());
|
||||
}
|
||||
|
||||
return geoAdd(key, values);
|
||||
}
|
||||
|
||||
private Long geoAdd(byte[] key, Collection<Object> values) {
|
||||
|
||||
try {
|
||||
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().geoadd(key, values.toArray())));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().geoadd(key, values.toArray())));
|
||||
return null;
|
||||
}
|
||||
return getConnection().geoadd(key, values.toArray());
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoDist(byte[], byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Distance geoDist(byte[] key, byte[] member1, byte[] member2) {
|
||||
return geoDist(key, member1, member2, DistanceUnit.METERS);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoDist(byte[], byte[], byte[], org.springframework.data.geo.Metric)
|
||||
*/
|
||||
@Override
|
||||
public Distance geoDist(byte[] key, byte[] member1, byte[] member2, Metric metric) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(member1, "Member1 must not be null!");
|
||||
Assert.notNull(member2, "Member2 must not be null!");
|
||||
Assert.notNull(metric, "Metric must not be null!");
|
||||
|
||||
GeoArgs.Unit geoUnit = LettuceConverters.toGeoArgsUnit(metric);
|
||||
Converter<Double, Distance> distanceConverter = LettuceConverters.distanceConverterForMetric(metric);
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().geodist(key, member1, member2, geoUnit),
|
||||
distanceConverter));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(
|
||||
connection.newLettuceTxResult(getConnection().geodist(key, member1, member2, geoUnit), distanceConverter));
|
||||
return null;
|
||||
}
|
||||
return distanceConverter.convert(getConnection().geodist(key, member1, member2, geoUnit));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoHash(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<String> geoHash(byte[] key, byte[]... members) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(members, "Members must not be null!");
|
||||
Assert.noNullElements(members, "Members must not contain null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().geohash(key, members)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().geohash(key, members)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().geohash(key, members).stream().map(value -> value.getValueOrElse(null))
|
||||
.collect(Collectors.toList());
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoPos(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<Point> geoPos(byte[] key, byte[]... members) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(members, "Members must not be null!");
|
||||
Assert.noNullElements(members, "Members must not contain null!");
|
||||
|
||||
ListConverter<GeoCoordinates, Point> converter = LettuceConverters.geoCoordinatesToPointConverter();
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().geopos(key, members), converter));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().geopos(key, members), converter));
|
||||
return null;
|
||||
}
|
||||
return converter.convert(getConnection().geopos(key, members));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoRadius(byte[], org.springframework.data.geo.Circle)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<byte[]>> geoRadius(byte[] key, Circle within) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(within, "Within must not be null!");
|
||||
|
||||
Converter<Set<byte[]>, GeoResults<GeoLocation<byte[]>>> geoResultsConverter = LettuceConverters
|
||||
.bytesSetToGeoResultsConverter();
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(
|
||||
getAsyncConnection().georadius(key, within.getCenter().getX(), within.getCenter().getY(),
|
||||
within.getRadius().getValue(), LettuceConverters.toGeoArgsUnit(within.getRadius().getMetric())),
|
||||
geoResultsConverter));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(
|
||||
getConnection().georadius(key, within.getCenter().getX(), within.getCenter().getY(),
|
||||
within.getRadius().getValue(), LettuceConverters.toGeoArgsUnit(within.getRadius().getMetric())),
|
||||
geoResultsConverter));
|
||||
return null;
|
||||
}
|
||||
return geoResultsConverter
|
||||
.convert(getConnection().georadius(key, within.getCenter().getX(), within.getCenter().getY(),
|
||||
within.getRadius().getValue(), LettuceConverters.toGeoArgsUnit(within.getRadius().getMetric())));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoRadius(byte[], org.springframework.data.geo.Circle, org.springframework.data.redis.core.GeoRadiusCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<byte[]>> geoRadius(byte[] key, Circle within, GeoRadiusCommandArgs args) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(within, "Within must not be null!");
|
||||
Assert.notNull(args, "Args must not be null!");
|
||||
|
||||
GeoArgs geoArgs = LettuceConverters.toGeoArgs(args);
|
||||
Converter<List<GeoWithin<byte[]>>, GeoResults<GeoLocation<byte[]>>> geoResultsConverter = LettuceConverters
|
||||
.geoRadiusResponseToGeoResultsConverter(within.getRadius().getMetric());
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().georadius(key, within.getCenter().getX(),
|
||||
within.getCenter().getY(), within.getRadius().getValue(),
|
||||
LettuceConverters.toGeoArgsUnit(within.getRadius().getMetric()), geoArgs), geoResultsConverter));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().georadius(key, within.getCenter().getX(),
|
||||
within.getCenter().getY(), within.getRadius().getValue(),
|
||||
LettuceConverters.toGeoArgsUnit(within.getRadius().getMetric()), geoArgs), geoResultsConverter));
|
||||
return null;
|
||||
}
|
||||
return geoResultsConverter
|
||||
.convert(getConnection().georadius(key, within.getCenter().getX(), within.getCenter().getY(),
|
||||
within.getRadius().getValue(), LettuceConverters.toGeoArgsUnit(within.getRadius().getMetric()), geoArgs));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoRadiusByMember(byte[], byte[], double)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<byte[]>> geoRadiusByMember(byte[] key, byte[] member, double radius) {
|
||||
return geoRadiusByMember(key, member, new Distance(radius, DistanceUnit.METERS));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoRadiusByMember(byte[], byte[], double, org.springframework.data.geo.Metric)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<byte[]>> geoRadiusByMember(byte[] key, byte[] member, Distance radius) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(member, "Member must not be null!");
|
||||
Assert.notNull(radius, "Radius must not be null!");
|
||||
|
||||
GeoArgs.Unit geoUnit = LettuceConverters.toGeoArgsUnit(radius.getMetric());
|
||||
Converter<Set<byte[]>, GeoResults<GeoLocation<byte[]>>> converter = LettuceConverters
|
||||
.bytesSetToGeoResultsConverter();
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(
|
||||
getAsyncConnection().georadiusbymember(key, member, radius.getValue(), geoUnit), converter));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection
|
||||
.newLettuceTxResult(getConnection().georadiusbymember(key, member, radius.getValue(), geoUnit), converter));
|
||||
return null;
|
||||
}
|
||||
return converter.convert(getConnection().georadiusbymember(key, member, radius.getValue(), geoUnit));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoRadiusByMember(byte[], byte[], org.springframework.data.geo.Distance, org.springframework.data.redis.core.GeoRadiusCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<byte[]>> geoRadiusByMember(byte[] key, byte[] member, Distance radius,
|
||||
GeoRadiusCommandArgs args) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(member, "Member must not be null!");
|
||||
Assert.notNull(radius, "Radius must not be null!");
|
||||
Assert.notNull(args, "Args must not be null!");
|
||||
|
||||
GeoArgs.Unit geoUnit = LettuceConverters.toGeoArgsUnit(radius.getMetric());
|
||||
GeoArgs geoArgs = LettuceConverters.toGeoArgs(args);
|
||||
Converter<List<GeoWithin<byte[]>>, GeoResults<GeoLocation<byte[]>>> geoResultsConverter = LettuceConverters
|
||||
.geoRadiusResponseToGeoResultsConverter(radius.getMetric());
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(
|
||||
getAsyncConnection().georadiusbymember(key, member, radius.getValue(), geoUnit, geoArgs),
|
||||
geoResultsConverter));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(
|
||||
getConnection().georadiusbymember(key, member, radius.getValue(), geoUnit, geoArgs), geoResultsConverter));
|
||||
return null;
|
||||
}
|
||||
return geoResultsConverter
|
||||
.convert(getConnection().georadiusbymember(key, member, radius.getValue(), geoUnit, geoArgs));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoRemove(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long geoRemove(byte[] key, byte[]... values) {
|
||||
return connection.zSetCommands().zRem(key, values);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
RedisClusterAsyncCommands<byte[], byte[]> getAsyncConnection() {
|
||||
return connection.getAsyncConnection();
|
||||
}
|
||||
|
||||
public RedisClusterCommands<byte[], byte[]> getConnection() {
|
||||
return connection.getConnection();
|
||||
}
|
||||
|
||||
private DataAccessException convertLettuceAccessException(Exception ex) {
|
||||
return connection.convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
* 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.MapScanCursor;
|
||||
import io.lettuce.core.ScanArgs;
|
||||
import io.lettuce.core.cluster.api.async.RedisClusterAsyncCommands;
|
||||
import io.lettuce.core.cluster.api.sync.RedisClusterCommands;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.connection.RedisHashCommands;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceResult;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceTxResult;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class LettuceHashCommands implements RedisHashCommands {
|
||||
|
||||
private final LettuceConnection connection;
|
||||
|
||||
public LettuceHashCommands(LettuceConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hSet(byte[], byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean hSet(byte[] key, byte[] field, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().hset(key, field, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().hset(key, field, value)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().hset(key, field, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hSetNX(byte[], byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean hSetNX(byte[] key, byte[] field, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().hsetnx(key, field, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().hsetnx(key, field, value)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().hsetnx(key, field, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hDel(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long hDel(byte[] key, byte[]... fields) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().hdel(key, fields)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().hdel(key, fields)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().hdel(key, fields);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hExists(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean hExists(byte[] key, byte[] field) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().hexists(key, field)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().hexists(key, field)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().hexists(key, field);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hGet(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] hGet(byte[] key, byte[] field) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().hget(key, field)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().hget(key, field)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().hget(key, field);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hGetAll(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Map<byte[], byte[]> hGetAll(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().hgetall(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().hgetall(key)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().hgetall(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hIncrBy(byte[], byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public Long hIncrBy(byte[] key, byte[] field, long delta) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().hincrby(key, field, delta)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().hincrby(key, field, delta)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().hincrby(key, field, delta);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hIncrBy(byte[], byte[], double)
|
||||
*/
|
||||
@Override
|
||||
public Double hIncrBy(byte[] key, byte[] field, double delta) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().hincrbyfloat(key, field, delta)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().hincrbyfloat(key, field, delta)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().hincrbyfloat(key, field, delta);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hKeys(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> hKeys(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().hkeys(key), LettuceConverters.bytesListToBytesSet()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().hkeys(key), LettuceConverters.bytesListToBytesSet()));
|
||||
return null;
|
||||
}
|
||||
return LettuceConverters.toBytesSet(getConnection().hkeys(key));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hLen(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long hLen(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().hlen(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().hlen(key)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().hlen(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hMGet(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> hMGet(byte[] key, byte[]... fields) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().hmget(key, fields),
|
||||
LettuceConverters.keyValueListUnwrapper()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().hmget(key, fields),
|
||||
LettuceConverters.keyValueListUnwrapper()));
|
||||
return null;
|
||||
}
|
||||
return LettuceConverters.<byte[], byte[]> keyValueListUnwrapper().convert(getConnection().hmget(key, fields));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hMSet(byte[], java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public void hMSet(byte[] key, Map<byte[], byte[]> tuple) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceStatusResult(getAsyncConnection().hmset(key, tuple)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxStatusResult(getConnection().hmset(key, tuple)));
|
||||
return;
|
||||
}
|
||||
getConnection().hmset(key, tuple);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hVals(byte[])
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> hVals(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().hvals(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().hvals(key)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().hvals(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHashCommands#hScan(byte[], org.springframework.data.redis.core.ScanOptions)
|
||||
*/
|
||||
@Override
|
||||
public Cursor<Entry<byte[], byte[]>> hScan(byte[] key, ScanOptions options) {
|
||||
return hScan(key, 0, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.4
|
||||
* @param key
|
||||
* @param cursorId
|
||||
* @param options
|
||||
* @return
|
||||
*/
|
||||
public Cursor<Entry<byte[], byte[]>> hScan(byte[] key, long cursorId, ScanOptions options) {
|
||||
|
||||
return new KeyBoundCursor<Entry<byte[], byte[]>>(key, cursorId, options) {
|
||||
|
||||
@Override
|
||||
protected ScanIteration<Entry<byte[], byte[]>> doScan(byte[] key, long cursorId, ScanOptions options) {
|
||||
|
||||
if (isQueueing() || isPipelined()) {
|
||||
throw new UnsupportedOperationException("'HSCAN' cannot be called in pipeline / transaction mode.");
|
||||
}
|
||||
|
||||
io.lettuce.core.ScanCursor scanCursor = connection.getScanCursor(cursorId);
|
||||
ScanArgs scanArgs = connection.getScanArgs(options);
|
||||
|
||||
MapScanCursor<byte[], byte[]> mapScanCursor = getConnection().hscan(key, scanCursor, scanArgs);
|
||||
String nextCursorId = mapScanCursor.getCursor();
|
||||
|
||||
Map<byte[], byte[]> values = mapScanCursor.getMap();
|
||||
return new ScanIteration<>(Long.valueOf(nextCursorId), values.entrySet());
|
||||
}
|
||||
|
||||
protected void doClose() {
|
||||
LettuceHashCommands.this.connection.close();
|
||||
}
|
||||
|
||||
}.open();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
RedisClusterAsyncCommands<byte[], byte[]> getAsyncConnection() {
|
||||
return connection.getAsyncConnection();
|
||||
}
|
||||
|
||||
public RedisClusterCommands<byte[], byte[]> getConnection() {
|
||||
return connection.getConnection();
|
||||
}
|
||||
|
||||
private DataAccessException convertLettuceAccessException(Exception ex) {
|
||||
return connection.convertLettuceAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* 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.async.RedisHLLAsyncCommands;
|
||||
import io.lettuce.core.api.sync.RedisHLLCommands;
|
||||
import io.lettuce.core.cluster.api.async.RedisClusterAsyncCommands;
|
||||
import io.lettuce.core.cluster.api.sync.RedisClusterCommands;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.connection.RedisHyperLogLogCommands;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceResult;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceTxResult;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class LettuceHyperLogLogCommands implements RedisHyperLogLogCommands {
|
||||
|
||||
private final LettuceConnection connection;
|
||||
|
||||
public LettuceHyperLogLogCommands(LettuceConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHyperLogLogCommands#pfAdd(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long pfAdd(byte[] key, byte[]... values) {
|
||||
|
||||
Assert.notEmpty(values, "PFADD requires at least one non 'null' value.");
|
||||
Assert.noNullElements(values, "Values for PFADD must not contain 'null'.");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
RedisHLLAsyncCommands<byte[], byte[]> asyncConnection = getAsyncConnection();
|
||||
pipeline(connection.newLettuceResult(asyncConnection.pfadd(key, values)));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isQueueing()) {
|
||||
RedisHLLAsyncCommands<byte[], byte[]> asyncConnection = getAsyncConnection();
|
||||
transaction(connection.newLettuceTxResult(asyncConnection.pfadd(key, values)));
|
||||
return null;
|
||||
}
|
||||
|
||||
RedisHLLCommands<byte[], byte[]> connection = getConnection();
|
||||
return connection.pfadd(key, values);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHyperLogLogCommands#pfCount(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long pfCount(byte[]... keys) {
|
||||
|
||||
Assert.notEmpty(keys, "PFCOUNT requires at least one non 'null' key.");
|
||||
Assert.noNullElements(keys, "Keys for PFCOUNT must not contain 'null'.");
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
RedisHLLAsyncCommands<byte[], byte[]> asyncConnection = getAsyncConnection();
|
||||
pipeline(connection.newLettuceResult(asyncConnection.pfcount(keys)));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isQueueing()) {
|
||||
RedisHLLAsyncCommands<byte[], byte[]> asyncConnection = getAsyncConnection();
|
||||
transaction(connection.newLettuceTxResult(asyncConnection.pfcount(keys)));
|
||||
return null;
|
||||
}
|
||||
|
||||
RedisHLLCommands<byte[], byte[]> connection = getConnection();
|
||||
return connection.pfcount(keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisHyperLogLogCommands#pfMerge(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public void pfMerge(byte[] destinationKey, byte[]... sourceKeys) {
|
||||
|
||||
Assert.notEmpty(sourceKeys, "PFMERGE requires at least one non 'null' source key.");
|
||||
Assert.noNullElements(sourceKeys, "source key for PFMERGE must not contain 'null'.");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
RedisHLLAsyncCommands<byte[], byte[]> asyncConnection = getAsyncConnection();
|
||||
pipeline(connection.newLettuceResult(asyncConnection.pfmerge(destinationKey, sourceKeys)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (isQueueing()) {
|
||||
RedisHLLAsyncCommands<byte[], byte[]> asyncConnection = getAsyncConnection();
|
||||
transaction(connection.newLettuceTxResult(asyncConnection.pfmerge(destinationKey, sourceKeys)));
|
||||
return;
|
||||
}
|
||||
|
||||
RedisHLLCommands<byte[], byte[]> connection = getConnection();
|
||||
connection.pfmerge(destinationKey, sourceKeys);
|
||||
} 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);
|
||||
}
|
||||
|
||||
RedisClusterAsyncCommands<byte[], byte[]> getAsyncConnection() {
|
||||
return connection.getAsyncConnection();
|
||||
}
|
||||
|
||||
public RedisClusterCommands<byte[], byte[]> getConnection() {
|
||||
return connection.getConnection();
|
||||
}
|
||||
|
||||
protected DataAccessException convertLettuceAccessException(Exception ex) {
|
||||
return connection.convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,604 @@
|
||||
/*
|
||||
* 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.KeyScanCursor;
|
||||
import io.lettuce.core.ScanArgs;
|
||||
import io.lettuce.core.SortArgs;
|
||||
import io.lettuce.core.cluster.api.async.RedisClusterAsyncCommands;
|
||||
import io.lettuce.core.cluster.api.sync.RedisClusterCommands;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.connection.DataType;
|
||||
import org.springframework.data.redis.connection.RedisKeyCommands;
|
||||
import org.springframework.data.redis.connection.SortParameters;
|
||||
import org.springframework.data.redis.connection.convert.Converters;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceResult;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceTxResult;
|
||||
import org.springframework.data.redis.core.Cursor;
|
||||
import org.springframework.data.redis.core.ScanCursor;
|
||||
import org.springframework.data.redis.core.ScanIteration;
|
||||
import org.springframework.data.redis.core.ScanOptions;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class LettuceKeyCommands implements RedisKeyCommands {
|
||||
|
||||
private final LettuceConnection connection;
|
||||
|
||||
public LettuceKeyCommands(LettuceConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#dump(byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] dump(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().dump(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().dump(key)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().dump(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#restore(byte[], long, byte[])
|
||||
*/
|
||||
@Override
|
||||
public void restore(byte[] key, long ttlInMillis, byte[] serializedValue) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceStatusResult(getAsyncConnection().restore(key, ttlInMillis, serializedValue)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxStatusResult(getConnection().restore(key, ttlInMillis, serializedValue)));
|
||||
return;
|
||||
}
|
||||
getConnection().restore(key, ttlInMillis, serializedValue);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#keys(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> keys(byte[] pattern) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(
|
||||
connection.newLettuceResult(getAsyncConnection().keys(pattern), LettuceConverters.bytesListToBytesSet()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(
|
||||
connection.newLettuceTxResult(getConnection().keys(pattern), LettuceConverters.bytesListToBytesSet()));
|
||||
return null;
|
||||
}
|
||||
return LettuceConverters.toBytesSet(getConnection().keys(pattern));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#exists(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean exists(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().exists(new byte[][] { key }),
|
||||
LettuceConverters.longToBooleanConverter()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getAsyncConnection().exists(new byte[][] { key }),
|
||||
LettuceConverters.longToBooleanConverter()));
|
||||
return null;
|
||||
}
|
||||
return LettuceConverters.longToBooleanConverter().convert(getConnection().exists(new byte[][] { key }));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#expire(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public Boolean expire(byte[] key, long seconds) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().expire(key, seconds)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().expire(key, seconds)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().expire(key, seconds);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#expireAt(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public Boolean expireAt(byte[] key, long unixTime) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().expireat(key, unixTime)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().expireat(key, unixTime)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().expireat(key, unixTime);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#pExpire(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public Boolean pExpire(byte[] key, long millis) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().pexpire(key, millis)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().pexpire(key, millis)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().pexpire(key, millis);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#pExpireAt(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public Boolean pExpireAt(byte[] key, long unixTimeInMillis) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().pexpireat(key, unixTimeInMillis)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().pexpireat(key, unixTimeInMillis)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().pexpireat(key, unixTimeInMillis);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#pTtl(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long pTtl(byte[] key) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().pttl(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().pttl(key)));
|
||||
return null;
|
||||
}
|
||||
|
||||
return getConnection().pttl(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#pTtl(byte[], java.util.concurrent.TimeUnit)
|
||||
*/
|
||||
@Override
|
||||
public Long pTtl(byte[] key, TimeUnit timeUnit) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(
|
||||
connection.newLettuceResult(getAsyncConnection().pttl(key), Converters.millisecondsToTimeUnit(timeUnit)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(
|
||||
connection.newLettuceTxResult(getConnection().pttl(key), Converters.millisecondsToTimeUnit(timeUnit)));
|
||||
return null;
|
||||
}
|
||||
|
||||
return Converters.millisecondsToTimeUnit(getConnection().pttl(key), timeUnit);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#del(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long del(byte[]... keys) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().del(keys)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().del(keys)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().del(keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#sort(byte[], org.springframework.data.redis.connection.SortParameters)
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> sort(byte[] key, SortParameters params) {
|
||||
|
||||
SortArgs args = LettuceConverters.toSortArgs(params);
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().sort(key, args)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().sort(key, args)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().sort(key, args);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#sort(byte[], org.springframework.data.redis.connection.SortParameters, byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long sort(byte[] key, SortParameters params, byte[] sortKey) {
|
||||
|
||||
SortArgs args = LettuceConverters.toSortArgs(params);
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().sortStore(key, args, sortKey)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().sortStore(key, args, sortKey)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().sortStore(key, args, sortKey);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#persist(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean persist(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().persist(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().persist(key)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().persist(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#move(byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public Boolean move(byte[] key, int dbIndex) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().move(key, dbIndex)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().move(key, dbIndex)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().move(key, dbIndex);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#randomKey()
|
||||
*/
|
||||
@Override
|
||||
public byte[] randomKey() {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().randomkey()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().randomkey()));
|
||||
return null;
|
||||
}
|
||||
return getConnection().randomkey();
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#rename(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public void rename(byte[] oldName, byte[] newName) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceStatusResult(getAsyncConnection().rename(oldName, newName)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxStatusResult(getConnection().rename(oldName, newName)));
|
||||
return;
|
||||
}
|
||||
getConnection().rename(oldName, newName);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#renameNX(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean renameNX(byte[] oldName, byte[] newName) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().renamenx(oldName, newName)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().renamenx(oldName, newName)));
|
||||
return null;
|
||||
}
|
||||
return (getConnection().renamenx(oldName, newName));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#ttl(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long ttl(byte[] key) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().ttl(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().ttl(key)));
|
||||
return null;
|
||||
}
|
||||
|
||||
return getConnection().ttl(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#ttl(byte[], java.util.concurrent.TimeUnit)
|
||||
*/
|
||||
@Override
|
||||
public Long ttl(byte[] key, TimeUnit timeUnit) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().ttl(key), Converters.secondsToTimeUnit(timeUnit)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().ttl(key), Converters.secondsToTimeUnit(timeUnit)));
|
||||
return null;
|
||||
}
|
||||
|
||||
return Converters.secondsToTimeUnit(getConnection().ttl(key), timeUnit);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#type(byte[])
|
||||
*/
|
||||
@Override
|
||||
public DataType type(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().type(key), LettuceConverters.stringToDataType()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().type(key), LettuceConverters.stringToDataType()));
|
||||
return null;
|
||||
}
|
||||
return LettuceConverters.toDataType(getConnection().type(key));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.4
|
||||
* @return
|
||||
*/
|
||||
public Cursor<byte[]> scan() {
|
||||
return scan(0, ScanOptions.NONE);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisKeyCommands#scan(org.springframework.data.redis.core.ScanOptions)
|
||||
*/
|
||||
@Override
|
||||
public Cursor<byte[]> scan(ScanOptions options) {
|
||||
return scan(0, options != null ? options : ScanOptions.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.4
|
||||
* @param cursorId
|
||||
* @param options
|
||||
* @return
|
||||
*/
|
||||
public Cursor<byte[]> scan(long cursorId, ScanOptions options) {
|
||||
|
||||
return new ScanCursor<byte[]>(cursorId, options) {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected ScanIteration<byte[]> doScan(long cursorId, ScanOptions options) {
|
||||
|
||||
if (isQueueing() || isPipelined()) {
|
||||
throw new UnsupportedOperationException("'SCAN' cannot be called in pipeline / transaction mode.");
|
||||
}
|
||||
|
||||
io.lettuce.core.ScanCursor scanCursor = connection.getScanCursor(cursorId);
|
||||
ScanArgs scanArgs = connection.getScanArgs(options);
|
||||
|
||||
KeyScanCursor<byte[]> keyScanCursor = getConnection().scan(scanCursor, scanArgs);
|
||||
String nextCursorId = keyScanCursor.getCursor();
|
||||
|
||||
List<byte[]> keys = keyScanCursor.getKeys();
|
||||
|
||||
return new ScanIteration<>(Long.valueOf(nextCursorId), (keys));
|
||||
}
|
||||
|
||||
protected void doClose() {
|
||||
LettuceKeyCommands.this.connection.close();
|
||||
}
|
||||
|
||||
}.open();
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
RedisClusterAsyncCommands<byte[], byte[]> getAsyncConnection() {
|
||||
return connection.getAsyncConnection();
|
||||
}
|
||||
|
||||
public RedisClusterCommands<byte[], byte[]> getConnection() {
|
||||
return connection.getConnection();
|
||||
}
|
||||
|
||||
private DataAccessException convertLettuceAccessException(Exception ex) {
|
||||
return connection.convertLettuceAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,433 @@
|
||||
/*
|
||||
* 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 org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.connection.RedisListCommands;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceResult;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceTxResult;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class LettuceListCommands implements RedisListCommands {
|
||||
|
||||
private final LettuceConnection connection;
|
||||
|
||||
public LettuceListCommands(LettuceConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lPush(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long lPush(byte[] key, byte[]... values) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().lpush(key, values)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().lpush(key, values)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().lpush(key, values);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#rPush(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long rPush(byte[] key, byte[]... values) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().rpush(key, values)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().rpush(key, values)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().rpush(key, values);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#bLPop(int, byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> bLPop(int timeout, byte[]... keys) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(connection.getAsyncDedicatedConnection().blpop(timeout, keys),
|
||||
LettuceConverters.keyValueToBytesList()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(connection.getDedicatedConnection().blpop(timeout, keys),
|
||||
LettuceConverters.keyValueToBytesList()));
|
||||
return null;
|
||||
}
|
||||
return LettuceConverters.toBytesList(connection.getDedicatedConnection().blpop(timeout, keys));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#bRPop(int, byte[][])
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> bRPop(int timeout, byte[]... keys) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(connection.getAsyncDedicatedConnection().brpop(timeout, keys),
|
||||
LettuceConverters.keyValueToBytesList()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(connection.getDedicatedConnection().brpop(timeout, keys),
|
||||
LettuceConverters.keyValueToBytesList()));
|
||||
return null;
|
||||
}
|
||||
return LettuceConverters.toBytesList(connection.getDedicatedConnection().brpop(timeout, keys));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lIndex(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public byte[] lIndex(byte[] key, long index) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().lindex(key, index)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().lindex(key, index)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().lindex(key, index);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lInsert(byte[], org.springframework.data.redis.connection.RedisListCommands.Position, byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long lInsert(byte[] key, Position where, byte[] pivot, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection
|
||||
.newLettuceResult(getAsyncConnection().linsert(key, LettuceConverters.toBoolean(where), pivot, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection
|
||||
.newLettuceTxResult(getConnection().linsert(key, LettuceConverters.toBoolean(where), pivot, value)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().linsert(key, LettuceConverters.toBoolean(where), pivot, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lLen(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long lLen(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().llen(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().llen(key)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().llen(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lPop(byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] lPop(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().lpop(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().lpop(key)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().lpop(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lRange(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> lRange(byte[] key, long start, long end) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().lrange(key, start, end)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().lrange(key, start, end)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().lrange(key, start, end);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lRem(byte[], long, byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long lRem(byte[] key, long count, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().lrem(key, count, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().lrem(key, count, value)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().lrem(key, count, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lSet(byte[], long, byte[])
|
||||
*/
|
||||
@Override
|
||||
public void lSet(byte[] key, long index, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceStatusResult(getAsyncConnection().lset(key, index, value)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxStatusResult(getConnection().lset(key, index, value)));
|
||||
return;
|
||||
}
|
||||
getConnection().lset(key, index, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lTrim(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public void lTrim(byte[] key, long start, long end) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceStatusResult(getAsyncConnection().ltrim(key, start, end)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxStatusResult(getConnection().ltrim(key, start, end)));
|
||||
return;
|
||||
}
|
||||
getConnection().ltrim(key, start, end);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#rPop(byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] rPop(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().rpop(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().rpop(key)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().rpop(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#rPopLPush(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] rPopLPush(byte[] srcKey, byte[] dstKey) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().rpoplpush(srcKey, dstKey)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().rpoplpush(srcKey, dstKey)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().rpoplpush(srcKey, dstKey);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#bRPopLPush(int, byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] bRPopLPush(int timeout, byte[] srcKey, byte[] dstKey) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(
|
||||
connection.newLettuceResult(connection.getAsyncDedicatedConnection().brpoplpush(timeout, srcKey, dstKey)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(
|
||||
connection.newLettuceTxResult(connection.getDedicatedConnection().brpoplpush(timeout, srcKey, dstKey)));
|
||||
return null;
|
||||
}
|
||||
return connection.getDedicatedConnection().brpoplpush(timeout, srcKey, dstKey);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lPushX(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long lPushX(byte[] key, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().lpushx(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().lpushx(key, value)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().lpushx(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#rPushX(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long rPushX(byte[] key, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().rpushx(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().rpushx(key, value)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().rpushx(key, value);
|
||||
} 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);
|
||||
}
|
||||
|
||||
RedisClusterAsyncCommands<byte[], byte[]> getAsyncConnection() {
|
||||
return connection.getAsyncConnection();
|
||||
}
|
||||
|
||||
public RedisClusterCommands<byte[], byte[]> getConnection() {
|
||||
return connection.getConnection();
|
||||
}
|
||||
|
||||
private DataAccessException convertLettuceAccessException(Exception ex) {
|
||||
return connection.convertLettuceAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,437 @@
|
||||
/*
|
||||
* 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.RedisFuture;
|
||||
import io.lettuce.core.ScanArgs;
|
||||
import io.lettuce.core.ValueScanCursor;
|
||||
import io.lettuce.core.cluster.api.async.RedisClusterAsyncCommands;
|
||||
import io.lettuce.core.cluster.api.sync.RedisClusterCommands;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.connection.RedisSetCommands;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceResult;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceTxResult;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class LettuceSetCommands implements RedisSetCommands {
|
||||
|
||||
private final LettuceConnection connection;
|
||||
|
||||
public LettuceSetCommands(LettuceConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sAdd(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sAdd(byte[] key, byte[]... values) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().sadd(key, values)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().sadd(key, values)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().sadd(key, values);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sCard(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long sCard(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().scard(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().scard(key)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().scard(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sDiff(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> sDiff(byte[]... keys) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().sdiff(keys)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().sdiff(keys)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().sdiff(keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sDiffStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sDiffStore(byte[] destKey, byte[]... keys) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().sdiffstore(destKey, keys)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().sdiffstore(destKey, keys)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().sdiffstore(destKey, keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sInter(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> sInter(byte[]... keys) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().sinter(keys)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().sinter(keys)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().sinter(keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sInterStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sInterStore(byte[] destKey, byte[]... keys) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().sinterstore(destKey, keys)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().sinterstore(destKey, keys)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().sinterstore(destKey, keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sIsMember(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean sIsMember(byte[] key, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().sismember(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().sismember(key, value)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().sismember(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sMembers(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> sMembers(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().smembers(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().smembers(key)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().smembers(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sMove(byte[], byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean sMove(byte[] srcKey, byte[] destKey, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().smove(srcKey, destKey, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().smove(srcKey, destKey, value)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().smove(srcKey, destKey, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sPop(byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] sPop(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().spop(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().spop(key)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().spop(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sRandMember(byte[])
|
||||
*/
|
||||
@Override
|
||||
public byte[] sRandMember(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().srandmember(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().srandmember(key)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().srandmember(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sRandMember(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public List<byte[]> sRandMember(byte[] key, long count) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult((RedisFuture) getAsyncConnection().srandmember(key, count),
|
||||
LettuceConverters.bytesCollectionToBytesList()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().srandmember(key, count),
|
||||
LettuceConverters.bytesCollectionToBytesList()));
|
||||
return null;
|
||||
}
|
||||
return LettuceConverters.toBytesList(getConnection().srandmember(key, count));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sRem(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sRem(byte[] key, byte[]... values) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().srem(key, values)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().srem(key, values)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().srem(key, values);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sUnion(byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> sUnion(byte[]... keys) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().sunion(keys)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().sunion(keys)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().sunion(keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sUnionStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long sUnionStore(byte[] destKey, byte[]... keys) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().sunionstore(destKey, keys)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().sunionstore(destKey, keys)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().sunionstore(destKey, keys);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisSetCommands#sScan(byte[], org.springframework.data.redis.core.ScanOptions)
|
||||
*/
|
||||
@Override
|
||||
public Cursor<byte[]> sScan(byte[] key, ScanOptions options) {
|
||||
return sScan(key, 0, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.4
|
||||
* @param key
|
||||
* @param cursorId
|
||||
* @param options
|
||||
* @return
|
||||
*/
|
||||
public Cursor<byte[]> sScan(byte[] key, long cursorId, ScanOptions options) {
|
||||
|
||||
return new KeyBoundCursor<byte[]>(key, cursorId, options) {
|
||||
|
||||
@Override
|
||||
protected ScanIteration<byte[]> doScan(byte[] key, long cursorId, ScanOptions options) {
|
||||
|
||||
if (isQueueing() || isPipelined()) {
|
||||
throw new UnsupportedOperationException("'SSCAN' cannot be called in pipeline / transaction mode.");
|
||||
}
|
||||
|
||||
io.lettuce.core.ScanCursor scanCursor = connection.getScanCursor(cursorId);
|
||||
ScanArgs scanArgs = connection.getScanArgs(options);
|
||||
|
||||
ValueScanCursor<byte[]> valueScanCursor = getConnection().sscan(key, scanCursor, scanArgs);
|
||||
String nextCursorId = valueScanCursor.getCursor();
|
||||
|
||||
List<byte[]> values = connection.failsafeReadScanValues(valueScanCursor.getValues(), null);
|
||||
return new ScanIteration<>(Long.valueOf(nextCursorId), values);
|
||||
}
|
||||
|
||||
protected void doClose() {
|
||||
LettuceSetCommands.this.connection.close();
|
||||
}
|
||||
|
||||
}.open();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
RedisClusterAsyncCommands<byte[], byte[]> getAsyncConnection() {
|
||||
return connection.getAsyncConnection();
|
||||
}
|
||||
|
||||
public RedisClusterCommands<byte[], byte[]> getConnection() {
|
||||
return connection.getConnection();
|
||||
}
|
||||
|
||||
private DataAccessException convertLettuceAccessException(Exception ex) {
|
||||
return connection.convertLettuceAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,514 @@
|
||||
/*
|
||||
* 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.Map;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.connection.RedisStringCommands;
|
||||
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.Expiration;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class LettuceStringCommands implements RedisStringCommands {
|
||||
|
||||
private final LettuceConnection connection;
|
||||
|
||||
public LettuceStringCommands(LettuceConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
public byte[] get(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().get(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().get(key)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().get(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void set(byte[] key, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceStatusResult(getAsyncConnection().set(key, value)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxStatusResult(getConnection().set(key, value)));
|
||||
return;
|
||||
}
|
||||
getConnection().set(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#set(byte[], byte[], org.springframework.data.redis.core.types.Expiration, org.springframework.data.redis.connection.RedisStringCommands.SetOption)
|
||||
*/
|
||||
@Override
|
||||
public void set(byte[] key, byte[] value, Expiration expiration, SetOption option) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceStatusResult(
|
||||
getAsyncConnection().set(key, value, LettuceConverters.toSetArgs(expiration, option))));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxStatusResult(
|
||||
getConnection().set(key, value, LettuceConverters.toSetArgs(expiration, option))));
|
||||
return;
|
||||
}
|
||||
getConnection().set(key, value, LettuceConverters.toSetArgs(expiration, option));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getSet(byte[] key, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().getset(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().getset(key, value)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().getset(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Long append(byte[] key, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().append(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().append(key, value)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().append(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public List<byte[]> mGet(byte[]... keys) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(
|
||||
connection.newLettuceResult(getAsyncConnection().mget(keys), LettuceConverters.keyValueListUnwrapper()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(
|
||||
connection.newLettuceTxResult(getConnection().mget(keys), LettuceConverters.keyValueListUnwrapper()));
|
||||
return null;
|
||||
}
|
||||
|
||||
return LettuceConverters.<byte[], byte[]> keyValueListUnwrapper().convert(getConnection().mget(keys));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void mSet(Map<byte[], byte[]> tuples) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceStatusResult(getAsyncConnection().mset(tuples)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxStatusResult(getConnection().mset(tuples)));
|
||||
return;
|
||||
}
|
||||
getConnection().mset(tuples);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean mSetNX(Map<byte[], byte[]> tuples) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().msetnx(tuples)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().msetnx(tuples)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().msetnx(tuples);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void setEx(byte[] key, long time, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceStatusResult(getAsyncConnection().setex(key, time, value)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxStatusResult(getConnection().setex(key, time, value)));
|
||||
return;
|
||||
}
|
||||
getConnection().setex(key, time, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.3
|
||||
* @see org.springframework.data.redis.connection.RedisStringCommands#pSetEx(byte[], long, byte[])
|
||||
*/
|
||||
@Override
|
||||
public void pSetEx(byte[] key, long milliseconds, byte[] value) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceStatusResult(getAsyncConnection().psetex(key, milliseconds, value)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxStatusResult(getConnection().psetex(key, milliseconds, value)));
|
||||
return;
|
||||
}
|
||||
getConnection().psetex(key, milliseconds, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean setNX(byte[] key, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().setnx(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().setnx(key, value)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().setnx(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getRange(byte[] key, long start, long end) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().getrange(key, start, end)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().getrange(key, start, end)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().getrange(key, start, end);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Long decr(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().decr(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().decr(key)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().decr(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Long decrBy(byte[] key, long value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().decrby(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().decrby(key, value)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().decrby(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Long incr(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().incr(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().incr(key)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().incr(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Long incrBy(byte[] key, long value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().incrby(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().incrby(key, value)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().incrby(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Double incrBy(byte[] key, double value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().incrbyfloat(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().incrbyfloat(key, value)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().incrbyfloat(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean getBit(byte[] key, long offset) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(
|
||||
connection.newLettuceResult(getAsyncConnection().getbit(key, offset), LettuceConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(
|
||||
connection.newLettuceTxResult(getConnection().getbit(key, offset), LettuceConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
return LettuceConverters.toBoolean(getConnection().getbit(key, offset));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean setBit(byte[] key, long offset, boolean value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().setbit(key, offset, LettuceConverters.toInt(value)),
|
||||
LettuceConverters.longToBooleanConverter()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().setbit(key, offset, LettuceConverters.toInt(value)),
|
||||
LettuceConverters.longToBooleanConverter()));
|
||||
return null;
|
||||
}
|
||||
return LettuceConverters.longToBooleanConverter()
|
||||
.convert(getConnection().setbit(key, offset, LettuceConverters.toInt(value)));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void setRange(byte[] key, byte[] value, long start) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceStatusResult(getAsyncConnection().setrange(key, start, value)));
|
||||
return;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxStatusResult(getConnection().setrange(key, start, value)));
|
||||
return;
|
||||
}
|
||||
getConnection().setrange(key, start, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Long strLen(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().strlen(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().strlen(key)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().strlen(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Long bitCount(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().bitcount(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().bitcount(key)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().bitcount(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Long bitCount(byte[] key, long begin, long end) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().bitcount(key, begin, end)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().bitcount(key, begin, end)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().bitcount(key, begin, end);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Long bitOp(BitOperation op, byte[] destination, byte[]... keys) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(asyncBitOp(op, destination, keys)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(syncBitOp(op, destination, keys)));
|
||||
return null;
|
||||
}
|
||||
return syncBitOp(op, destination, keys);
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
throw ex;
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private Future<Long> asyncBitOp(BitOperation op, byte[] destination, byte[]... keys) {
|
||||
switch (op) {
|
||||
case AND:
|
||||
return getAsyncConnection().bitopAnd(destination, keys);
|
||||
case OR:
|
||||
return getAsyncConnection().bitopOr(destination, keys);
|
||||
case XOR:
|
||||
return getAsyncConnection().bitopXor(destination, keys);
|
||||
case NOT:
|
||||
if (keys.length != 1) {
|
||||
throw new UnsupportedOperationException("Bitop NOT should only be performed against one key");
|
||||
}
|
||||
return getAsyncConnection().bitopNot(destination, keys[0]);
|
||||
default:
|
||||
throw new UnsupportedOperationException("Bit operation " + op + " is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
private Long syncBitOp(BitOperation op, byte[] destination, byte[]... keys) {
|
||||
switch (op) {
|
||||
case AND:
|
||||
return getConnection().bitopAnd(destination, keys);
|
||||
case OR:
|
||||
return getConnection().bitopOr(destination, keys);
|
||||
case XOR:
|
||||
return getConnection().bitopXor(destination, keys);
|
||||
case NOT:
|
||||
if (keys.length != 1) {
|
||||
throw new UnsupportedOperationException("Bitop NOT should only be performed against one key");
|
||||
}
|
||||
return getConnection().bitopNot(destination, keys[0]);
|
||||
default:
|
||||
throw new UnsupportedOperationException("Bit operation " + op + " is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
RedisClusterAsyncCommands<byte[], byte[]> getAsyncConnection() {
|
||||
return connection.getAsyncConnection();
|
||||
}
|
||||
|
||||
public RedisClusterCommands<byte[], byte[]> getConnection() {
|
||||
return connection.getConnection();
|
||||
}
|
||||
|
||||
private DataAccessException convertLettuceAccessException(Exception ex) {
|
||||
return connection.convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,841 @@
|
||||
/*
|
||||
* 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.ScanArgs;
|
||||
import io.lettuce.core.ScoredValue;
|
||||
import io.lettuce.core.ScoredValueScanCursor;
|
||||
import io.lettuce.core.ZStoreArgs;
|
||||
import io.lettuce.core.cluster.api.async.RedisClusterAsyncCommands;
|
||||
import io.lettuce.core.cluster.api.sync.RedisClusterCommands;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceResult;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceTxResult;
|
||||
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 org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
class LettuceZSetCommands implements RedisZSetCommands {
|
||||
|
||||
private final LettuceConnection connection;
|
||||
|
||||
public LettuceZSetCommands(LettuceConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], double, byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean zAdd(byte[] key, double score, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zadd(key, score, value),
|
||||
LettuceConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(
|
||||
connection.newLettuceTxResult(getConnection().zadd(key, score, value), LettuceConverters.longToBoolean()));
|
||||
return null;
|
||||
}
|
||||
return LettuceConverters.toBoolean(getConnection().zadd(key, score, value));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], java.util.Set)
|
||||
*/
|
||||
@Override
|
||||
public Long zAdd(byte[] key, Set<Tuple> tuples) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(
|
||||
connection.newLettuceResult(getAsyncConnection().zadd(key, LettuceConverters.toObjects(tuples).toArray())));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(
|
||||
connection.newLettuceTxResult(getConnection().zadd(key, LettuceConverters.toObjects(tuples).toArray())));
|
||||
return null;
|
||||
}
|
||||
return getConnection().zadd(key, LettuceConverters.toObjects(tuples).toArray());
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zCard(byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long zCard(byte[] key) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zcard(key)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zcard(key)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().zcard(key);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zCount(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
|
||||
*/
|
||||
@Override
|
||||
public Long zCount(byte[] key, Range range) {
|
||||
|
||||
Assert.notNull(range, "Range for ZCOUNT must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zcount(key, LettuceConverters.toRange(range))));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zcount(key, LettuceConverters.toRange(range))));
|
||||
return null;
|
||||
}
|
||||
return getConnection().zcount(key, LettuceConverters.toRange(range));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zIncrBy(byte[], double, byte[])
|
||||
*/
|
||||
@Override
|
||||
public Double zIncrBy(byte[] key, double increment, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zincrby(key, increment, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zincrby(key, increment, value)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().zincrby(key, increment, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zInterStore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Aggregate, int[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long zInterStore(byte[] destKey, Aggregate aggregate, int[] weights, byte[]... sets) {
|
||||
|
||||
ZStoreArgs storeArgs = zStoreArgs(aggregate, weights);
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zinterstore(destKey, storeArgs, sets)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zinterstore(destKey, storeArgs, sets)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().zinterstore(destKey, storeArgs, sets);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zInterStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long zInterStore(byte[] destKey, byte[]... sets) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zinterstore(destKey, sets)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zinterstore(destKey, sets)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().zinterstore(destKey, sets);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRange(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRange(byte[] key, long start, long end) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zrange(key, start, end),
|
||||
LettuceConverters.bytesListToBytesSet()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zrange(key, start, end),
|
||||
LettuceConverters.bytesListToBytesSet()));
|
||||
return null;
|
||||
}
|
||||
return LettuceConverters.toBytesSet(getConnection().zrange(key, start, end));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeWithScores(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public Set<Tuple> zRangeWithScores(byte[] key, long start, long end) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zrangeWithScores(key, start, end),
|
||||
LettuceConverters.scoredValuesToTupleSet()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zrangeWithScores(key, start, end),
|
||||
LettuceConverters.scoredValuesToTupleSet()));
|
||||
return null;
|
||||
}
|
||||
return LettuceConverters.toTupleSet(getConnection().zrangeWithScores(key, start, end));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByScore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRangeByScore(byte[] key, Range range, Limit limit) {
|
||||
|
||||
Assert.notNull(range, "Range for ZRANGEBYSCORE must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
if (limit != null) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zrangebyscore(key, LettuceConverters.toRange(range),
|
||||
LettuceConverters.toLimit(limit)), LettuceConverters.bytesListToBytesSet()));
|
||||
} else {
|
||||
pipeline(
|
||||
connection.newLettuceResult(getAsyncConnection().zrangebyscore(key, LettuceConverters.toRange(range)),
|
||||
LettuceConverters.bytesListToBytesSet()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
if (limit != null) {
|
||||
transaction(connection.newLettuceTxResult(
|
||||
getConnection().zrangebyscore(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)),
|
||||
LettuceConverters.bytesListToBytesSet()));
|
||||
} else {
|
||||
transaction(
|
||||
connection.newLettuceTxResult(getConnection().zrangebyscore(key, LettuceConverters.toRange(range)),
|
||||
LettuceConverters.bytesListToBytesSet()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (limit != null) {
|
||||
return LettuceConverters.toBytesSet(
|
||||
getConnection().zrangebyscore(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)));
|
||||
}
|
||||
return LettuceConverters.toBytesSet(getConnection().zrangebyscore(key, LettuceConverters.toRange(range)));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByScoreWithScores(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)
|
||||
*/
|
||||
@Override
|
||||
public Set<Tuple> zRangeByScoreWithScores(byte[] key, Range range, Limit limit) {
|
||||
|
||||
Assert.notNull(range, "Range for ZRANGEBYSCOREWITHSCORES must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
if (limit != null) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zrangebyscoreWithScores(key,
|
||||
LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)),
|
||||
LettuceConverters.scoredValuesToTupleSet()));
|
||||
} else {
|
||||
pipeline(connection.newLettuceResult(
|
||||
getAsyncConnection().zrangebyscoreWithScores(key, LettuceConverters.toRange(range)),
|
||||
LettuceConverters.scoredValuesToTupleSet()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
if (limit != null) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zrangebyscoreWithScores(key,
|
||||
LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)),
|
||||
LettuceConverters.scoredValuesToTupleSet()));
|
||||
} else {
|
||||
transaction(connection.newLettuceTxResult(
|
||||
getConnection().zrangebyscoreWithScores(key, LettuceConverters.toRange(range)),
|
||||
LettuceConverters.scoredValuesToTupleSet()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (limit != null) {
|
||||
return LettuceConverters.toTupleSet(getConnection().zrangebyscoreWithScores(key,
|
||||
LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)));
|
||||
}
|
||||
return LettuceConverters
|
||||
.toTupleSet(getConnection().zrangebyscoreWithScores(key, LettuceConverters.toRange(range)));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRangeWithScores(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public Set<Tuple> zRevRangeWithScores(byte[] key, long start, long end) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zrevrangeWithScores(key, start, end),
|
||||
LettuceConverters.scoredValuesToTupleSet()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zrevrangeWithScores(key, start, end),
|
||||
LettuceConverters.scoredValuesToTupleSet()));
|
||||
return null;
|
||||
}
|
||||
return LettuceConverters.toTupleSet(getConnection().zrevrangeWithScores(key, start, end));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRangeByScore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRevRangeByScore(byte[] key, Range range, Limit limit) {
|
||||
|
||||
Assert.notNull(range, "Range for ZREVRANGEBYSCORE must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
if (limit != null) {
|
||||
pipeline(
|
||||
connection.newLettuceResult(getAsyncConnection().zrevrangebyscore(key, LettuceConverters.toRange(range),
|
||||
LettuceConverters.toLimit(limit)), LettuceConverters.bytesListToBytesSet()));
|
||||
} else {
|
||||
pipeline(
|
||||
connection.newLettuceResult(getAsyncConnection().zrevrangebyscore(key, LettuceConverters.toRange(range)),
|
||||
LettuceConverters.bytesListToBytesSet()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
if (limit != null) {
|
||||
transaction(connection.newLettuceTxResult(
|
||||
getConnection().zrevrangebyscore(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)),
|
||||
LettuceConverters.bytesListToBytesSet()));
|
||||
} else {
|
||||
transaction(
|
||||
connection.newLettuceTxResult(getConnection().zrevrangebyscore(key, LettuceConverters.toRange(range)),
|
||||
LettuceConverters.bytesListToBytesSet()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (limit != null) {
|
||||
return LettuceConverters.toBytesSet(
|
||||
getConnection().zrevrangebyscore(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)));
|
||||
}
|
||||
return LettuceConverters.toBytesSet(getConnection().zrevrangebyscore(key, LettuceConverters.toRange(range)));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRangeByScoreWithScores(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)
|
||||
*/
|
||||
@Override
|
||||
public Set<Tuple> zRevRangeByScoreWithScores(byte[] key, Range range, Limit limit) {
|
||||
|
||||
Assert.notNull(range, "Range for ZREVRANGEBYSCOREWITHSCORES must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
if (limit != null) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zrevrangebyscoreWithScores(key,
|
||||
LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)),
|
||||
LettuceConverters.scoredValuesToTupleSet()));
|
||||
} else {
|
||||
pipeline(connection.newLettuceResult(
|
||||
getAsyncConnection().zrevrangebyscoreWithScores(key, LettuceConverters.toRange(range)),
|
||||
LettuceConverters.scoredValuesToTupleSet()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
if (limit != null) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zrevrangebyscoreWithScores(key,
|
||||
LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)),
|
||||
LettuceConverters.scoredValuesToTupleSet()));
|
||||
} else {
|
||||
transaction(connection.newLettuceTxResult(
|
||||
getConnection().zrevrangebyscoreWithScores(key, LettuceConverters.toRange(range)),
|
||||
LettuceConverters.scoredValuesToTupleSet()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (limit != null) {
|
||||
return LettuceConverters.toTupleSet(getConnection().zrevrangebyscoreWithScores(key,
|
||||
LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)));
|
||||
}
|
||||
return LettuceConverters
|
||||
.toTupleSet(getConnection().zrevrangebyscoreWithScores(key, LettuceConverters.toRange(range)));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRank(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long zRank(byte[] key, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zrank(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zrank(key, value)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().zrank(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRem(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long zRem(byte[] key, byte[]... values) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zrem(key, values)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zrem(key, values)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().zrem(key, values);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRange(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public Long zRemRange(byte[] key, long start, long end) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zremrangebyrank(key, start, end)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zremrangebyrank(key, start, end)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().zremrangebyrank(key, start, end);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRangeByScore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
|
||||
*/
|
||||
@Override
|
||||
public Long zRemRangeByScore(byte[] key, Range range) {
|
||||
|
||||
Assert.notNull(range, "Range for ZREMRANGEBYSCORE must not be null!");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(
|
||||
connection.newLettuceResult(getAsyncConnection().zremrangebyscore(key, LettuceConverters.toRange(range))));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(
|
||||
connection.newLettuceTxResult(getConnection().zremrangebyscore(key, LettuceConverters.toRange(range))));
|
||||
return null;
|
||||
}
|
||||
return getConnection().zremrangebyscore(key, LettuceConverters.toRange(range));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRange(byte[], long, long)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRevRange(byte[] key, long start, long end) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zrevrange(key, start, end),
|
||||
LettuceConverters.bytesListToBytesSet()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zrevrange(key, start, end),
|
||||
LettuceConverters.bytesListToBytesSet()));
|
||||
return null;
|
||||
}
|
||||
return LettuceConverters.toBytesSet(getConnection().zrevrange(key, start, end));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRank(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Long zRevRank(byte[] key, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zrevrank(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zrevrank(key, value)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().zrevrank(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zScore(byte[], byte[])
|
||||
*/
|
||||
@Override
|
||||
public Double zScore(byte[] key, byte[] value) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zscore(key, value)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zscore(key, value)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().zscore(key, value);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zUnionStore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Aggregate, int[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long zUnionStore(byte[] destKey, Aggregate aggregate, int[] weights, byte[]... sets) {
|
||||
ZStoreArgs storeArgs = zStoreArgs(aggregate, weights);
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zunionstore(destKey, storeArgs, sets)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zunionstore(destKey, storeArgs, sets)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().zunionstore(destKey, storeArgs, sets);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zUnionStore(byte[], byte[][])
|
||||
*/
|
||||
@Override
|
||||
public Long zUnionStore(byte[] destKey, byte[]... sets) {
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zunionstore(destKey, sets)));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zunionstore(destKey, sets)));
|
||||
return null;
|
||||
}
|
||||
return getConnection().zunionstore(destKey, sets);
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zScan(byte[], org.springframework.data.redis.core.ScanOptions)
|
||||
*/
|
||||
@Override
|
||||
public Cursor<Tuple> zScan(byte[] key, ScanOptions options) {
|
||||
return zScan(key, 0L, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.4
|
||||
* @param key
|
||||
* @param cursorId
|
||||
* @param options
|
||||
* @return
|
||||
*/
|
||||
public Cursor<Tuple> zScan(byte[] key, long cursorId, ScanOptions options) {
|
||||
|
||||
return new KeyBoundCursor<Tuple>(key, cursorId, options) {
|
||||
|
||||
@Override
|
||||
protected ScanIteration<Tuple> doScan(byte[] key, long cursorId, ScanOptions options) {
|
||||
|
||||
if (isQueueing() || isPipelined()) {
|
||||
throw new UnsupportedOperationException("'ZSCAN' cannot be called in pipeline / transaction mode.");
|
||||
}
|
||||
|
||||
io.lettuce.core.ScanCursor scanCursor = connection.getScanCursor(cursorId);
|
||||
ScanArgs scanArgs = connection.getScanArgs(options);
|
||||
|
||||
ScoredValueScanCursor<byte[]> scoredValueScanCursor = getConnection().zscan(key, scanCursor, scanArgs);
|
||||
String nextCursorId = scoredValueScanCursor.getCursor();
|
||||
|
||||
List<ScoredValue<byte[]>> result = scoredValueScanCursor.getValues();
|
||||
|
||||
List<Tuple> values = connection.failsafeReadScanValues(result, LettuceConverters.scoredValuesToTupleList());
|
||||
return new ScanIteration<Tuple>(Long.valueOf(nextCursorId), values);
|
||||
}
|
||||
|
||||
protected void doClose() {
|
||||
LettuceZSetCommands.this.connection.close();
|
||||
}
|
||||
|
||||
}.open();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByScore(byte[], java.lang.String, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRangeByScore(byte[] key, String min, String max) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zrangebyscore(key, min, max),
|
||||
LettuceConverters.bytesListToBytesSet()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zrangebyscore(key, min, max),
|
||||
LettuceConverters.bytesListToBytesSet()));
|
||||
return null;
|
||||
}
|
||||
return LettuceConverters.toBytesSet(getConnection().zrangebyscore(key, min, max));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByScore(byte[], java.lang.String, java.lang.String, long, long)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRangeByScore(byte[] key, String min, String max, long offset, long count) {
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zrangebyscore(key, min, max, offset, count),
|
||||
LettuceConverters.bytesListToBytesSet()));
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zrangebyscore(key, min, max, offset, count),
|
||||
LettuceConverters.bytesListToBytesSet()));
|
||||
return null;
|
||||
}
|
||||
return LettuceConverters.toBytesSet(getConnection().zrangebyscore(key, min, max, offset, count));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByLex(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)
|
||||
*/
|
||||
@Override
|
||||
public Set<byte[]> zRangeByLex(byte[] key, Range range, Limit limit) {
|
||||
|
||||
Assert.notNull(range, "Range cannot be null for ZRANGEBYLEX.");
|
||||
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
if (limit != null) {
|
||||
pipeline(connection.newLettuceResult(
|
||||
getAsyncConnection().zrangebylex(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)),
|
||||
LettuceConverters.bytesListToBytesSet()));
|
||||
} else {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().zrangebylex(key, LettuceConverters.toRange(range)),
|
||||
LettuceConverters.bytesListToBytesSet()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
if (limit != null) {
|
||||
transaction(connection.newLettuceTxResult(
|
||||
getConnection().zrangebylex(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)),
|
||||
LettuceConverters.bytesListToBytesSet()));
|
||||
} else {
|
||||
transaction(connection.newLettuceTxResult(getConnection().zrangebylex(key, LettuceConverters.toRange(range)),
|
||||
LettuceConverters.bytesListToBytesSet()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (limit != null) {
|
||||
return LettuceConverters.bytesListToBytesSet().convert(
|
||||
getConnection().zrangebylex(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)));
|
||||
}
|
||||
|
||||
return LettuceConverters.bytesListToBytesSet()
|
||||
.convert(getConnection().zrangebylex(key, LettuceConverters.toRange(range)));
|
||||
} 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);
|
||||
}
|
||||
|
||||
RedisClusterAsyncCommands<byte[], byte[]> getAsyncConnection() {
|
||||
return connection.getAsyncConnection();
|
||||
}
|
||||
|
||||
public RedisClusterCommands<byte[], byte[]> getConnection() {
|
||||
return connection.getConnection();
|
||||
}
|
||||
|
||||
private DataAccessException convertLettuceAccessException(Exception ex) {
|
||||
return connection.convertLettuceAccessException(ex);
|
||||
}
|
||||
|
||||
private ZStoreArgs zStoreArgs(Aggregate aggregate, int[] weights) {
|
||||
ZStoreArgs args = new ZStoreArgs();
|
||||
if (aggregate != null) {
|
||||
switch (aggregate) {
|
||||
case MIN:
|
||||
args.min();
|
||||
break;
|
||||
case MAX:
|
||||
args.max();
|
||||
break;
|
||||
default:
|
||||
args.sum();
|
||||
break;
|
||||
}
|
||||
}
|
||||
double[] lg = new double[weights.length];
|
||||
for (int i = 0; i < lg.length; i++) {
|
||||
lg[i] = weights[i];
|
||||
}
|
||||
args.weights(lg);
|
||||
return args;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user