Skip to content

Commit f9ea11f

Browse files
committed
Polishing.
Let Cursor extend CloseableCursor. Refine nullability annotations and align nullability behavior in tests with actual nullability usage.
1 parent 9a0b4b3 commit f9ea11f

File tree

6 files changed

+61
-47
lines changed

6 files changed

+61
-47
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ protected ScanIteration<byte[]> doScan(long cursorId, ScanOptions options) {
452452
ScanParams params = JedisConverters.toScanParams(options);
453453
redis.clients.jedis.ScanResult<byte[]> result = connection.getCluster().sscan(key,
454454
JedisConverters.toBytes(cursorId), params);
455-
return new ScanIteration<>(Long.valueOf(result.getCursor()), result.getResult());
455+
return new ScanIteration<>(Long.parseLong(result.getCursor()), result.getResult());
456456
}
457457
}.open();
458458
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ protected ScanIteration<byte[]> doScan(long cursorId, ScanOptions options) {
169169

170170
ScanParams params = JedisConverters.toScanParams(options);
171171
redis.clients.jedis.ScanResult<String> result = connection.getJedis().scan(Long.toString(cursorId), params);
172-
return new ScanIteration<>(Long.valueOf(result.getCursor()),
172+
return new ScanIteration<>(Long.parseLong(result.getCursor()),
173173
JedisConverters.stringListToByteList().convert(result.getResult()));
174174
}
175175

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
*/
1616
package org.springframework.data.redis.core;
1717

18-
import java.io.IOException;
19-
2018
import org.springframework.core.convert.converter.Converter;
2119
import org.springframework.lang.Nullable;
2220
import org.springframework.util.Assert;
@@ -81,7 +79,7 @@ public void remove() {
8179
* @see java.io.Closeable#close()
8280
*/
8381
@Override
84-
public void close() throws IOException {
82+
public void close() {
8583
delegate.close();
8684
}
8785

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

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@
1515
*/
1616
package org.springframework.data.redis.core;
1717

18-
import java.io.Closeable;
19-
2018
import org.springframework.data.redis.util.BoundedIterator;
19+
import org.springframework.data.util.CloseableIterator;
2120

2221
/**
2322
* Cursor abstraction to scan over the keyspace or elements within a data structure using a variant of a {@code SCAN}
@@ -28,7 +27,7 @@
2827
* @param <T>
2928
* @since 1.4
3029
*/
31-
public interface Cursor<T> extends BoundedIterator<T>, Closeable {
30+
public interface Cursor<T> extends BoundedIterator<T>, CloseableIterator<T> {
3231

3332
/**
3433
* Get the reference cursor. <br>
@@ -39,19 +38,19 @@ public interface Cursor<T> extends BoundedIterator<T>, Closeable {
3938
long getCursorId();
4039

4140
/**
42-
* @return Returns true if cursor closed.
41+
* @return {@code true} if cursor closed.
4342
*/
4443
boolean isClosed();
4544

4645
/**
4746
* Opens cursor and returns itself.
4847
*
49-
* @return
48+
* @return the opened cursor.
5049
*/
5150
Cursor<T> open();
5251

5352
/**
54-
* @return Returns the current position of the cursor.
53+
* @return the current position of the cursor.
5554
*/
5655
long getPosition();
5756

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

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616
package org.springframework.data.redis.core;
1717

18-
import java.io.IOException;
1918
import java.util.Collections;
2019
import java.util.Iterator;
2120
import java.util.NoSuchElementException;
@@ -39,10 +38,10 @@
3938
*/
4039
public abstract class ScanCursor<T> implements Cursor<T> {
4140

42-
private @Nullable CursorState state;
41+
private CursorState state;
4342
private long cursorId;
44-
private @Nullable Iterator<T> delegate;
45-
private @Nullable final ScanOptions scanOptions;
43+
private Iterator<T> delegate;
44+
private final ScanOptions scanOptions;
4645
private long position;
4746
private final long limit;
4847

@@ -56,7 +55,7 @@ public ScanCursor() {
5655
/**
5756
* Crates new {@link ScanCursor} with {@code id=0}.
5857
*
59-
* @param options
58+
* @param options the scan options to apply.
6059
*/
6160
public ScanCursor(ScanOptions options) {
6261
this(0, options);
@@ -65,7 +64,7 @@ public ScanCursor(ScanOptions options) {
6564
/**
6665
* Crates new {@link ScanCursor} with {@link ScanOptions#NONE}
6766
*
68-
* @param cursorId
67+
* @param cursorId the cursor Id.
6968
*/
7069
public ScanCursor(long cursorId) {
7170
this(cursorId, ScanOptions.NONE);
@@ -74,22 +73,22 @@ public ScanCursor(long cursorId) {
7473
/**
7574
* Crates new {@link ScanCursor}
7675
*
77-
* @param cursorId
78-
* @param options Defaulted to {@link ScanOptions#NONE} if nulled.
76+
* @param cursorId the cursor Id.
77+
* @param options Defaulted to {@link ScanOptions#NONE} if {@code null}.
7978
*/
80-
public ScanCursor(long cursorId, ScanOptions options) {
79+
public ScanCursor(long cursorId, @Nullable ScanOptions options) {
8180

8281
this.scanOptions = options != null ? options : ScanOptions.NONE;
8382
this.cursorId = cursorId;
8483
this.state = CursorState.READY;
85-
this.delegate = Collections.<T> emptyList().iterator();
84+
this.delegate = Collections.emptyIterator();
8685
this.limit = -1;
8786
}
8887

8988
/**
9089
* Crates a new {@link ScanCursor}.
9190
*
92-
* @param source
91+
* @param source source cursor.
9392
* @param limit
9493
* @since 2.5
9594
*/
@@ -144,14 +143,7 @@ protected void doOpen(long cursorId) {
144143

145144
private void processScanResult(ScanIteration<T> result) {
146145

147-
if (result == null) {
148-
149-
resetDelegate();
150-
state = CursorState.FINISHED;
151-
return;
152-
}
153-
154-
cursorId = Long.valueOf(result.getCursorId());
146+
cursorId = result.getCursorId();
155147

156148
if (isFinished(cursorId)) {
157149
state = CursorState.FINISHED;
@@ -176,7 +168,7 @@ protected boolean isFinished(long cursorId) {
176168
}
177169

178170
private void resetDelegate() {
179-
delegate = Collections.<T> emptyList().iterator();
171+
delegate = Collections.emptyIterator();
180172
}
181173

182174
/*
@@ -209,11 +201,7 @@ public boolean hasNext() {
209201
return true;
210202
}
211203

212-
if (cursorId > 0) {
213-
return true;
214-
}
215-
216-
return false;
204+
return cursorId > 0;
217205
}
218206

219207
private void assertCursorIsOpen() {
@@ -266,7 +254,7 @@ public void remove() {
266254
* @see java.io.Closeable#close()
267255
*/
268256
@Override
269-
public final void close() throws IOException {
257+
public final void close() {
270258

271259
try {
272260
doClose();
@@ -326,7 +314,8 @@ enum CursorState {
326314
}
327315

328316
/**
329-
* Wrapper for a concrete {@link ScanCursor} forwarding {@link #doScan(long, ScanOptions)}.
317+
* Wrapper for a concrete {@link ScanCursor} forwarding {@link #doScan(long, ScanOptions)}, {@link #doClose()} and
318+
* {@link #isClosed()}.
330319
*
331320
* @param <T>
332321
* @since 2.5
@@ -344,5 +333,15 @@ public ScanCursorWrapper(ScanCursor<T> delegate, long limit) {
344333
protected ScanIteration<T> doScan(long cursorId, ScanOptions options) {
345334
return delegate.doScan(cursorId, options);
346335
}
336+
337+
@Override
338+
protected void doClose() {
339+
delegate.close();
340+
}
341+
342+
@Override
343+
public boolean isClosed() {
344+
return delegate.isClosed();
345+
}
347346
}
348347
}

src/test/java/org/springframework/data/redis/core/ScanCursorUnitTests.java

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import java.util.List;
2525
import java.util.NoSuchElementException;
2626
import java.util.Queue;
27-
import java.util.Stack;
2827

2928
import org.junit.jupiter.api.Test;
3029

@@ -237,6 +236,26 @@ void limitShouldNotLimitOriginalCursor() {
237236
assertThat(result).hasSize(3);
238237
}
239238

239+
@Test // GH-1575
240+
void decoratedCursorShouldForwardClose() {
241+
242+
LinkedList<ScanIteration<String>> values = new LinkedList<>();
243+
values.add(createIteration(1, "spring"));
244+
values.add(createIteration(2, "data"));
245+
values.add(createIteration(3, "redis"));
246+
values.add(createIteration(0));
247+
Cursor<String> cursor = initCursor(values);
248+
Cursor<String> limited = cursor.limit(1);
249+
250+
assertThat(cursor.isClosed()).isFalse();
251+
assertThat(limited.isClosed()).isFalse();
252+
253+
limited.close();
254+
255+
assertThat(cursor.isClosed()).isTrue();
256+
assertThat(limited.isClosed()).isTrue();
257+
}
258+
240259
private CapturingCursorDummy initCursor(Queue<ScanIteration<String>> values) {
241260
CapturingCursorDummy cursor = new CapturingCursorDummy(values);
242261
cursor.open();
@@ -247,11 +266,9 @@ private ScanIteration<String> createIteration(long cursorId, String... values) {
247266
return new ScanIteration<>(cursorId, values.length > 0 ? Arrays.asList(values) : Collections.<String> emptyList());
248267
}
249268

250-
private class CapturingCursorDummy extends ScanCursor<String> {
269+
private static class CapturingCursorDummy extends ScanCursor<String> {
251270

252-
private Queue<ScanIteration<String>> values;
253-
254-
private Stack<Long> cursors;
271+
private final Queue<ScanIteration<String>> values;
255272

256273
CapturingCursorDummy(Queue<ScanIteration<String>> values) {
257274
this.values = values;
@@ -260,11 +277,12 @@ private class CapturingCursorDummy extends ScanCursor<String> {
260277
@Override
261278
protected ScanIteration<String> doScan(long cursorId, ScanOptions options) {
262279

263-
if (cursors == null) {
264-
cursors = new Stack<>();
280+
ScanIteration<String> iteration = this.values.poll();
281+
282+
if (iteration == null) {
283+
iteration = new ScanIteration<>(0, Collections.emptyList());
265284
}
266-
this.cursors.push(cursorId);
267-
return this.values.poll();
285+
return iteration;
268286
}
269287
}
270288
}

0 commit comments

Comments
 (0)