Skip to content

Commit 6c8d15a

Browse files
committed
Add ScanOptions.pattern(…) accepting a byte[] pattern.
We now accept a byte array as pattern for scan operations in addition to String patterns. Also, use binary Jedis scan method to avoid bytes to String conversion. Closes #2006
1 parent eca4766 commit 6c8d15a

File tree

5 files changed

+48
-14
lines changed

5 files changed

+48
-14
lines changed

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -529,8 +529,9 @@ public static ScanParams toScanParams(ScanOptions options) {
529529
if (options.getCount() != null) {
530530
sp.count(options.getCount().intValue());
531531
}
532-
if (StringUtils.hasText(options.getPattern())) {
533-
sp.match(options.getPattern());
532+
byte[] pattern = options.getBytePattern();
533+
if (pattern != null) {
534+
sp.match(pattern);
534535
}
535536
}
536537
return sp;

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,10 @@ protected ScanIteration<byte[]> doScan(long cursorId, ScanOptions options) {
168168
}
169169

170170
ScanParams params = JedisConverters.toScanParams(options);
171-
redis.clients.jedis.ScanResult<String> result = connection.getJedis().scan(Long.toString(cursorId), params);
171+
redis.clients.jedis.ScanResult<byte[]> result = connection.getJedis().scan(Long.toString(cursorId).getBytes(),
172+
params);
172173
return new ScanIteration<>(Long.parseLong(result.getCursor()),
173-
JedisConverters.stringListToByteList().convert(result.getResult()));
174+
result.getResult());
174175
}
175176

176177
protected void doClose() {

src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConverters.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -868,8 +868,9 @@ static ScanArgs toScanArgs(@Nullable ScanOptions options) {
868868

869869
ScanArgs scanArgs = new ScanArgs();
870870

871-
if (options.getPattern() != null) {
872-
scanArgs.match(options.getPattern());
871+
byte[] pattern = options.getBytePattern();
872+
if (pattern != null) {
873+
scanArgs.match(pattern);
873874
}
874875

875876
if (options.getCount() != null) {

src/main/java/org/springframework/data/redis/core/ScanOptions.java

+35-4
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,16 @@ public class ScanOptions {
3131
/**
3232
* Constant to apply default {@link ScanOptions} without setting a limit or matching a pattern.
3333
*/
34-
public static ScanOptions NONE = new ScanOptions(null, null);
34+
public static ScanOptions NONE = new ScanOptions(null, null, null);
3535

3636
private final @Nullable Long count;
3737
private final @Nullable String pattern;
38+
private final @Nullable byte[] bytePattern;
3839

39-
private ScanOptions(@Nullable Long count, @Nullable String pattern) {
40+
private ScanOptions(@Nullable Long count, @Nullable String pattern, @Nullable byte[] bytePattern) {
4041
this.count = count;
4142
this.pattern = pattern;
43+
this.bytePattern = bytePattern;
4244
}
4345

4446
/**
@@ -57,9 +59,24 @@ public Long getCount() {
5759

5860
@Nullable
5961
public String getPattern() {
62+
63+
if (bytePattern != null && pattern == null) {
64+
return new String(bytePattern);
65+
}
66+
6067
return pattern;
6168
}
6269

70+
@Nullable
71+
public byte[] getBytePattern() {
72+
73+
if (bytePattern == null && pattern != null) {
74+
return pattern.getBytes();
75+
}
76+
77+
return bytePattern;
78+
}
79+
6380
public String toOptionString() {
6481

6582
if (this.equals(ScanOptions.NONE)) {
@@ -71,7 +88,8 @@ public String toOptionString() {
7188
if (this.count != null) {
7289
params += (", 'count', " + count);
7390
}
74-
if (StringUtils.hasText(this.pattern)) {
91+
String pattern = getPattern();
92+
if (StringUtils.hasText(pattern)) {
7593
params += (", 'match' , '" + this.pattern + "'");
7694
}
7795

@@ -87,6 +105,7 @@ public static class ScanOptionsBuilder {
87105

88106
private @Nullable Long count;
89107
private @Nullable String pattern;
108+
private @Nullable byte[] bytePattern;
90109

91110

92111
/**
@@ -111,13 +130,25 @@ public ScanOptionsBuilder match(String pattern) {
111130
return this;
112131
}
113132

133+
/**
134+
* Returns the current {@link ScanOptionsBuilder} configured with the given {@code pattern}.
135+
*
136+
* @param pattern
137+
* @return
138+
* @since 2.6
139+
*/
140+
public ScanOptionsBuilder match(byte[] pattern) {
141+
this.bytePattern = pattern;
142+
return this;
143+
}
144+
114145
/**
115146
* Builds a new {@link ScanOptions} objects.
116147
*
117148
* @return a new {@link ScanOptions} objects.
118149
*/
119150
public ScanOptions build() {
120-
return new ScanOptions(count, pattern);
151+
return new ScanOptions(count, pattern, bytePattern);
121152
}
122153
}
123154
}

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -157,21 +157,21 @@ void zRangeByScoreShouldThrowExceptionWhenCountExceedsIntegerRange() {
157157
Integer.MAX_VALUE, (long) Integer.MAX_VALUE + 1L));
158158
}
159159

160-
@Test // DATAREDIS-531
160+
@Test // DATAREDIS-531, GH-2006
161161
public void scanShouldKeepTheConnectionOpen() {
162162

163-
doReturn(new ScanResult<>("0", Collections.<String> emptyList())).when(jedisSpy).scan(anyString(),
163+
doReturn(new ScanResult<>("0", Collections.<String> emptyList())).when(jedisSpy).scan(any(byte[].class),
164164
any(ScanParams.class));
165165

166166
connection.scan(ScanOptions.NONE);
167167

168168
verify(jedisSpy, never()).quit();
169169
}
170170

171-
@Test // DATAREDIS-531
171+
@Test // DATAREDIS-531, GH-2006
172172
public void scanShouldCloseTheConnectionWhenCursorIsClosed() throws IOException {
173173

174-
doReturn(new ScanResult<>("0", Collections.<String> emptyList())).when(jedisSpy).scan(anyString(),
174+
doReturn(new ScanResult<>("0", Collections.<String> emptyList())).when(jedisSpy).scan(any(byte[].class),
175175
any(ScanParams.class));
176176

177177
Cursor<byte[]> cursor = connection.scan(ScanOptions.NONE);

0 commit comments

Comments
 (0)