Skip to content

Commit 77de777

Browse files
mp911dechristophstrobl
authored andcommitted
DATAREDIS-479 - Upgrade to jedis to 2.8.1.
Update jedis driver to 2.8.1. Use binary method for SSCAN and implement ZSCAN and HSCAN methods. Move ScanOptions to ScanParams conversion to JedisConverters. Original Pull Request: #178
1 parent 069954e commit 77de777

File tree

5 files changed

+107
-27
lines changed

5 files changed

+107
-27
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
<xstream>1.4.8</xstream>
2424
<pool>2.2</pool>
2525
<lettuce>3.4.2.Final</lettuce>
26-
<jedis>2.8.0</jedis>
26+
<jedis>2.8.1</jedis>
2727
<srp>0.7</srp>
2828
<jredis>06052013</jredis>
2929
<multithreadedtc>1.01</multithreadedtc>

src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterConnection.java

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2015 the original author or authors.
2+
* Copyright 2015-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -74,6 +74,7 @@
7474
import redis.clients.jedis.Jedis;
7575
import redis.clients.jedis.JedisCluster;
7676
import redis.clients.jedis.JedisPool;
77+
import redis.clients.jedis.ScanParams;
7778
import redis.clients.jedis.ZParams;
7879

7980
/**
@@ -1532,10 +1533,9 @@ public Cursor<byte[]> sScan(final byte[] key, ScanOptions options) {
15321533
@Override
15331534
protected ScanIteration<byte[]> doScan(long cursorId, ScanOptions options) {
15341535

1535-
redis.clients.jedis.ScanResult<String> result = cluster.sscan(JedisConverters.toString(key),
1536-
Long.toString(cursorId));
1537-
return new ScanIteration<byte[]>(Long.valueOf(result.getCursor()),
1538-
JedisConverters.stringListToByteList().convert(result.getResult()));
1536+
ScanParams params = JedisConverters.toScanParams(options);
1537+
redis.clients.jedis.ScanResult<byte[]> result = cluster.sscan(key, JedisConverters.toBytes(cursorId), params);
1538+
return new ScanIteration<byte[]>(Long.valueOf(result.getStringCursor()), result.getResult());
15391539
}
15401540
}.open();
15411541
}
@@ -2158,8 +2158,19 @@ public Long zInterStore(byte[] destKey, Aggregate aggregate, int[] weights, byte
21582158
}
21592159

21602160
@Override
2161-
public Cursor<Tuple> zScan(byte[] key, ScanOptions options) {
2162-
throw new UnsupportedOperationException("Jedis does currently not support binary zscan command.");
2161+
public Cursor<Tuple> zScan(final byte[] key, final ScanOptions options) {
2162+
return new ScanCursor<Tuple>(options) {
2163+
2164+
@Override
2165+
protected ScanIteration<Tuple> doScan(long cursorId, ScanOptions options) {
2166+
2167+
ScanParams params = JedisConverters.toScanParams(options);
2168+
2169+
redis.clients.jedis.ScanResult<redis.clients.jedis.Tuple> result = cluster.zscan(key, JedisConverters.toBytes(cursorId), params);
2170+
return new ScanIteration<Tuple>(Long.valueOf(result.getStringCursor()), JedisConverters
2171+
.tuplesToTuples().convert(result.getResult()));
2172+
}
2173+
}.open();
21632174
}
21642175

21652176
/*
@@ -2387,7 +2398,11 @@ public Cursor<Entry<byte[], byte[]>> hScan(final byte[] key, ScanOptions options
23872398

23882399
@Override
23892400
protected ScanIteration<Entry<byte[], byte[]>> doScan(long cursorId, ScanOptions options) {
2390-
throw new UnsupportedOperationException("Jedis does currently not support binary hscan");
2401+
2402+
ScanParams params = JedisConverters.toScanParams(options);
2403+
2404+
redis.clients.jedis.ScanResult<Map.Entry<byte[], byte[]>> result = cluster.hscan(key, JedisConverters.toBytes(cursorId), params);
2405+
return new ScanIteration<Map.Entry<byte[], byte[]>>(Long.valueOf(result.getStringCursor()), result.getResult());
23912406
}
23922407
}.open();
23932408
}

src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@
6060
import org.springframework.util.ClassUtils;
6161
import org.springframework.util.ObjectUtils;
6262
import org.springframework.util.ReflectionUtils;
63-
import org.springframework.util.StringUtils;
6463

6564
import redis.clients.jedis.BinaryJedis;
6665
import redis.clients.jedis.BinaryJedisPubSub;
@@ -92,6 +91,7 @@
9291
* @author Konstantin Shchepanovskyi
9392
* @author David Liu
9493
* @author Milan Agatonovic
94+
* @author Mark Paluch
9595
*/
9696
public class JedisConnection extends AbstractRedisConnection {
9797

@@ -3315,7 +3315,7 @@ protected ScanIteration<byte[]> doScan(long cursorId, ScanOptions options) {
33153315
throw new UnsupportedOperationException("'SCAN' cannot be called in pipeline / transaction mode.");
33163316
}
33173317

3318-
ScanParams params = prepareScanParams(options);
3318+
ScanParams params = JedisConverters.toScanParams(options);
33193319
redis.clients.jedis.ScanResult<String> result = jedis.scan(Long.toString(cursorId), params);
33203320
return new ScanIteration<byte[]>(Long.valueOf(result.getStringCursor()), JedisConverters.stringListToByteList()
33213321
.convert(result.getResult()));
@@ -3352,7 +3352,7 @@ protected ScanIteration<Tuple> doScan(byte[] key, long cursorId, ScanOptions opt
33523352
throw new UnsupportedOperationException("'ZSCAN' cannot be called in pipeline / transaction mode.");
33533353
}
33543354

3355-
ScanParams params = prepareScanParams(options);
3355+
ScanParams params = JedisConverters.toScanParams(options);
33563356

33573357
ScanResult<redis.clients.jedis.Tuple> result = jedis.zscan(key, JedisConverters.toBytes(cursorId), params);
33583358
return new ScanIteration<RedisZSetCommands.Tuple>(Long.valueOf(result.getStringCursor()), JedisConverters
@@ -3389,7 +3389,7 @@ protected ScanIteration<byte[]> doScan(byte[] key, long cursorId, ScanOptions op
33893389
throw new UnsupportedOperationException("'SSCAN' cannot be called in pipeline / transaction mode.");
33903390
}
33913391

3392-
ScanParams params = prepareScanParams(options);
3392+
ScanParams params = JedisConverters.toScanParams(options);
33933393

33943394
redis.clients.jedis.ScanResult<byte[]> result = jedis.sscan(key, JedisConverters.toBytes(cursorId), params);
33953395
return new ScanIteration<byte[]>(Long.valueOf(result.getStringCursor()), result.getResult());
@@ -3424,27 +3424,14 @@ protected ScanIteration<Entry<byte[], byte[]>> doScan(byte[] key, long cursorId,
34243424
throw new UnsupportedOperationException("'HSCAN' cannot be called in pipeline / transaction mode.");
34253425
}
34263426

3427-
ScanParams params = prepareScanParams(options);
3427+
ScanParams params = JedisConverters.toScanParams(options);
34283428

34293429
ScanResult<Entry<byte[], byte[]>> result = jedis.hscan(key, JedisConverters.toBytes(cursorId), params);
34303430
return new ScanIteration<Map.Entry<byte[], byte[]>>(Long.valueOf(result.getStringCursor()), result.getResult());
34313431
}
34323432
}.open();
34333433
}
34343434

3435-
private ScanParams prepareScanParams(ScanOptions options) {
3436-
ScanParams sp = new ScanParams();
3437-
if (!options.equals(ScanOptions.NONE)) {
3438-
if (options.getCount() != null) {
3439-
sp.count(options.getCount().intValue());
3440-
}
3441-
if (StringUtils.hasText(options.getPattern())) {
3442-
sp.match(options.getPattern());
3443-
}
3444-
}
3445-
return sp;
3446-
}
3447-
34483435
/**
34493436
* Specifies if pipelined results should be converted to the expected data type. If false, results of
34503437
* {@link #closePipeline()} and {@link #exec()} will be of the type returned by the Jedis driver

src/main/java/org/springframework/data/redis/connection/jedis/JedisConverters.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import org.springframework.data.redis.connection.convert.MapConverter;
4343
import org.springframework.data.redis.connection.convert.SetConverter;
4444
import org.springframework.data.redis.connection.convert.StringToRedisClientInfoConverter;
45+
import org.springframework.data.redis.core.ScanOptions;
4546
import org.springframework.data.redis.core.types.Expiration;
4647
import org.springframework.data.redis.core.types.RedisClientInfo;
4748
import org.springframework.util.Assert;
@@ -51,6 +52,7 @@
5152

5253
import redis.clients.jedis.BinaryClient.LIST_POSITION;
5354
import redis.clients.jedis.BitOP;
55+
import redis.clients.jedis.ScanParams;
5456
import redis.clients.jedis.SortingParams;
5557
import redis.clients.util.SafeEncoder;
5658

@@ -432,4 +434,26 @@ private static byte[] boundaryToBytes(Boundary boundary, byte[] inclPrefix, byte
432434
return buffer.array();
433435

434436
}
437+
438+
/**
439+
* Convert {@link ScanOptions} to Jedis {@link ScanParams}.
440+
*
441+
* @param options
442+
* @return
443+
*/
444+
public static ScanParams toScanParams(ScanOptions options) {
445+
446+
ScanParams sp = new ScanParams();
447+
448+
if (!options.equals(ScanOptions.NONE)) {
449+
if (options.getCount() != null) {
450+
sp.count(options.getCount().intValue());
451+
}
452+
if (StringUtils.hasText(options.getPattern())) {
453+
sp.match(options.getPattern());
454+
}
455+
}
456+
return sp;
457+
}
458+
435459
}

src/test/java/org/springframework/data/redis/connection/jedis/JedisClusterConnectionTests.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import static org.hamcrest.number.IsCloseTo.*;
2121
import static org.junit.Assert.*;
2222
import static org.springframework.data.redis.connection.ClusterTestVariables.*;
23+
import static org.springframework.data.redis.core.ScanOptions.scanOptions;
2324

2425
import java.io.IOException;
2526
import java.util.Arrays;
@@ -1769,6 +1770,33 @@ public void zInterStoreShouldWorkForSameSlotKeys() {
17691770
public void zInterStoreShouldThrowExceptionWhenKeysDoNotMapToSameSlots() {
17701771
clusterConnection.zInterStore(KEY_3_BYTES, KEY_1_BYTES, KEY_2_BYTES);
17711772
}
1773+
1774+
1775+
/**
1776+
* @see DATAREDIS-479
1777+
*/
1778+
@Test
1779+
public void zScanShouldReadEntireValueRange() {
1780+
1781+
nativeConnection.zadd(KEY_1_BYTES, 2, VALUE_1_BYTES);
1782+
nativeConnection.zadd(KEY_1_BYTES, 1, VALUE_2_BYTES);
1783+
nativeConnection.zadd(KEY_1_BYTES, 4, VALUE_3_BYTES);
1784+
1785+
Cursor<Tuple> tuples = clusterConnection.zScan(KEY_1_BYTES, ScanOptions.NONE);
1786+
1787+
int count = 0;
1788+
while (tuples.hasNext()) {
1789+
1790+
Tuple tuple = tuples.next();
1791+
1792+
assertThat(tuple.getValue(), anyOf(equalTo(VALUE_1_BYTES), equalTo(VALUE_2_BYTES), equalTo(VALUE_3_BYTES)));
1793+
assertThat(tuple.getScore(), anyOf(equalTo(1D), equalTo(2D), equalTo(4D)));
1794+
1795+
count++;
1796+
}
1797+
1798+
assertThat(count, equalTo(3));
1799+
}
17721800

17731801
/**
17741802
* @see DATAREDIS-315
@@ -1952,6 +1980,32 @@ public void hGetAllShouldRetrieveEntriesCorrectly() {
19521980
assertThat(hGetAll.containsKey(KEY_2_BYTES), is(true));
19531981
assertThat(hGetAll.containsKey(KEY_3_BYTES), is(true));
19541982
}
1983+
1984+
/**
1985+
* @see DATAREDIS-479
1986+
*/
1987+
@Test
1988+
public void hScanShouldReadEntireValueRange() {
1989+
1990+
clusterConnection.hSet(KEY_1_BYTES, KEY_1_BYTES, VALUE_1_BYTES);
1991+
clusterConnection.hSet(KEY_1_BYTES, KEY_2_BYTES, VALUE_2_BYTES);
1992+
clusterConnection.hSet(KEY_1_BYTES, KEY_3_BYTES, VALUE_3_BYTES);
1993+
1994+
Cursor<Map.Entry<byte[], byte[]>> cursor = clusterConnection
1995+
.hScan(KEY_1_BYTES, scanOptions().match("key*").build());
1996+
1997+
int i = 0;
1998+
while (cursor.hasNext()) {
1999+
2000+
byte[] key = cursor.next().getKey();
2001+
2002+
assertThat(key, anyOf(equalTo(KEY_1_BYTES), equalTo(KEY_2_BYTES), equalTo(KEY_3_BYTES)));
2003+
2004+
i++;
2005+
}
2006+
2007+
assertThat(i, is(3));
2008+
}
19552009

19562010
/**
19572011
* @see DATAREDIS-315

0 commit comments

Comments
 (0)