Skip to content

Commit c1e0599

Browse files
Remove limit(long) from cursor and hint users to stream().limit(...)
1 parent ceba810 commit c1e0599

File tree

5 files changed

+16
-228
lines changed

5 files changed

+16
-228
lines changed

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

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,4 @@ public Cursor<T> open() {
119119
public long getPosition() {
120120
return delegate.getPosition();
121121
}
122-
123-
/*
124-
* (non-Javadoc)
125-
* @see org.springframework.data.redis.core.Cursor#limit(long)
126-
*/
127-
@Override
128-
public Cursor<T> limit(long count) {
129-
return new ConvertingCursor<>(delegate.limit(count), converter);
130-
}
131122
}

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

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

18-
import org.springframework.data.redis.util.BoundedIterator;
1918
import org.springframework.data.util.CloseableIterator;
2019

2120
/**
2221
* Cursor abstraction to scan over the keyspace or elements within a data structure using a variant of a {@code SCAN}
2322
* command.
23+
* <p />
24+
* Using a Java 8 {@link #stream() java.util.stream.Stream} allows to apply additional
25+
* {@link java.util.stream.Stream#filter(java.util.function.Predicate) filters} and {@link java.util.stream.Stream#limit(long) limits} to
26+
* the underlying {@link Cursor}.
27+
* <p />
28+
* Make sure to {@link CloseableIterator#close() close} the cursor when done as this allows implementations to clean up
29+
* any resources they need to keep open to iterate over elements (eg. by using a try-with-resource statement).
2430
*
2531
* @author Christoph Strobl
2632
* @author Mark Paluch
2733
* @param <T>
2834
* @since 1.4
2935
*/
30-
public interface Cursor<T> extends BoundedIterator<T>, CloseableIterator<T> {
36+
public interface Cursor<T> extends CloseableIterator<T> {
3137

3238
/**
3339
* Get the reference cursor. <br>
@@ -56,15 +62,4 @@ public interface Cursor<T> extends BoundedIterator<T>, CloseableIterator<T> {
5662
* @return the current position of the cursor.
5763
*/
5864
long getPosition();
59-
60-
/**
61-
* Limit the maximum number of elements to be returned from this cursor. The returned cursor object can be used to
62-
* iterate over the remaining items and to {@link #close() release} associated resources. The returned cursor is not
63-
* attached to the state of {@code this} cursor and this object should be no longer used.
64-
*
65-
* @return a new {@link Cursor} with detached iteration state.
66-
* @since 2.5
67-
*/
68-
@Override
69-
Cursor<T> limit(long count);
7065
}

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

Lines changed: 0 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -83,20 +83,6 @@ public ScanCursor(long cursorId, @Nullable ScanOptions options) {
8383
this.delegate = Collections.emptyIterator();
8484
}
8585

86-
/**
87-
* Crates a new {@link ScanCursor}.
88-
*
89-
* @param source source cursor.
90-
* @since 2.5
91-
*/
92-
private ScanCursor(ScanCursor<T> source) {
93-
94-
this.scanOptions = source.scanOptions;
95-
this.cursorId = source.cursorId;
96-
this.state = source.state;
97-
this.delegate = source.delegate;
98-
}
99-
10086
private void scan(long cursorId) {
10187

10288
ScanIteration<T> result = doScan(cursorId, this.scanOptions);
@@ -185,10 +171,6 @@ public boolean hasNext() {
185171

186172
assertCursorIsOpen();
187173

188-
if (limitReached(getPosition())) {
189-
return false;
190-
}
191-
192174
while (!delegate.hasNext() && !CursorState.FINISHED.equals(state)) {
193175
scan(cursorId);
194176
}
@@ -200,17 +182,6 @@ public boolean hasNext() {
200182
return cursorId > 0;
201183
}
202184

203-
/**
204-
* Evaluate if the current cursor position has reached a point where it should stop.
205-
*
206-
* @param currentPosition the current position.
207-
* @return {@literal false} by default.
208-
* @since 2.5
209-
*/
210-
protected boolean limitReached(long currentPosition) {
211-
return false;
212-
}
213-
214185
private void assertCursorIsOpen() {
215186

216187
if (isReady() || isClosed()) {
@@ -301,81 +272,10 @@ public long getPosition() {
301272
return position;
302273
}
303274

304-
/*
305-
* (non-Javadoc)
306-
* @see org.springframework.data.redis.core.Cursor#limit(long)
307-
*/
308-
@Override
309-
public ScanCursor<T> limit(long count) {
310-
311-
Assert.isTrue(count >= 0, "Count must be greater or equal to zero");
312-
313-
return new LimitingCursor<>(this, count);
314-
}
315-
316275
/**
317276
* @author Thomas Darimont
318277
*/
319278
enum CursorState {
320279
READY, OPEN, FINISHED, CLOSED;
321280
}
322-
323-
/**
324-
* Wrapper for a concrete {@link ScanCursor} forwarding {@link #doScan(long, ScanOptions)}, {@link #doClose()} and
325-
* {@link #isClosed()}.
326-
*
327-
* @param <T>
328-
* @author Mark Paluch
329-
* @author Christoph Strobl
330-
* @since 2.5
331-
*/
332-
private static class LimitingCursor<T> extends ScanCursor<T> {
333-
334-
private final ScanCursor<T> delegate;
335-
private final long limit;
336-
337-
LimitingCursor(ScanCursor<T> delegate, long limit) {
338-
339-
super(delegate);
340-
341-
this.delegate = delegate;
342-
this.limit = limit;
343-
}
344-
345-
/*
346-
* (non-Javadoc)
347-
* @see org.springframework.data.redis.core.ScanCursor#doScan(long, ScanOptions)
348-
*/
349-
@Override
350-
protected ScanIteration<T> doScan(long cursorId, ScanOptions options) {
351-
return delegate.doScan(cursorId, options);
352-
}
353-
354-
/*
355-
* (non-Javadoc)
356-
* @see org.springframework.data.redis.core.ScanCursor#doClose()
357-
*/
358-
@Override
359-
protected void doClose() {
360-
delegate.close();
361-
}
362-
363-
/*
364-
* (non-Javadoc)
365-
* @see org.springframework.data.redis.core.Cursor#isClosed()
366-
*/
367-
@Override
368-
public boolean isClosed() {
369-
return delegate.isClosed();
370-
}
371-
372-
/*
373-
* (non-Javadoc)
374-
* @see org.springframework.data.redis.core.ScanCursor#limitReached(long)
375-
*/
376-
@Override
377-
protected boolean limitReached(long currentPosition) {
378-
return delegate.limitReached(currentPosition) || (limit != -1 && currentPosition > limit - 1);
379-
}
380-
}
381281
}

src/main/java/org/springframework/data/redis/util/BoundedIterator.java

Lines changed: 0 additions & 36 deletions
This file was deleted.

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

Lines changed: 8 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import java.util.List;
2525
import java.util.NoSuchElementException;
2626
import java.util.Queue;
27+
import java.util.stream.Collectors;
28+
import java.util.stream.Stream;
2729

2830
import org.junit.jupiter.api.Test;
2931
import org.springframework.dao.InvalidDataAccessApiUsageException;
@@ -199,100 +201,36 @@ void hasNextShouldStopCorrectlyWhenWholeScanIterationDoesNotReturnResultsAndStat
199201
}
200202

201203
@Test // GH-1575
202-
void limitShouldApplyLimitation() {
204+
void streamLimitShouldApplyLimitation() {
203205

204206
LinkedList<ScanIteration<String>> values = new LinkedList<>();
205207
values.add(createIteration(1, "spring"));
206208
values.add(createIteration(2, "data"));
207209
values.add(createIteration(3, "redis"));
208210
values.add(createIteration(0));
209-
Cursor<String> cursor = initCursor(values).limit(2);
210211

211-
List<String> result = new ArrayList<>();
212-
while (cursor.hasNext()) {
213-
result.add(cursor.next());
214-
}
215-
216-
assertThat(result).hasSize(2).contains("spring", "data");
217-
}
218-
219-
@Test // GH-1575
220-
void limitShouldNotLimitOriginalCursor() {
221-
222-
LinkedList<ScanIteration<String>> values = new LinkedList<>();
223-
values.add(createIteration(1, "spring"));
224-
values.add(createIteration(2, "data"));
225-
values.add(createIteration(3, "redis"));
226-
values.add(createIteration(0));
227212
Cursor<String> cursor = initCursor(values);
228-
cursor.limit(1);
229-
230-
List<String> result = new ArrayList<>();
231-
while (cursor.hasNext()) {
232-
result.add(cursor.next());
233-
}
234-
235-
assertThat(result).hasSize(3);
236-
}
237-
238-
@Test // GH-1575
239-
void limitAlreadyLimitedCursorToLess() {
240-
241-
LinkedList<ScanIteration<String>> values = new LinkedList<>();
242-
values.add(createIteration(1, "spring"));
243-
values.add(createIteration(2, "data"));
244-
values.add(createIteration(3, "redis"));
245-
values.add(createIteration(0));
246-
Cursor<String> cursor = initCursor(values);
247-
Cursor<String> limitedTo3 = cursor.limit(3);
248-
Cursor<String> limitedTo2 = limitedTo3.limit(2);
249-
250-
List<String> result = new ArrayList<>();
251-
while (limitedTo2.hasNext()) {
252-
result.add(limitedTo2.next());
253-
}
254-
255-
assertThat(result).hasSize(2);
256-
}
257-
258-
@Test // GH-1575
259-
void limitAlreadyLimitedCursorToMore/*should not work obviously*/() {
260-
261-
LinkedList<ScanIteration<String>> values = new LinkedList<>();
262-
values.add(createIteration(1, "spring"));
263-
values.add(createIteration(2, "data"));
264-
values.add(createIteration(3, "redis"));
265-
values.add(createIteration(0));
266-
Cursor<String> cursor = initCursor(values);
267-
Cursor<String> limitedTo2 = cursor.limit(2);
268-
Cursor<String> limitedTo3 = limitedTo2.limit(3);
269-
270-
List<String> result = new ArrayList<>();
271-
while (limitedTo3.hasNext()) {
272-
result.add(limitedTo3.next());
273-
}
274213

275-
assertThat(result).hasSize(2);
214+
assertThat(cursor.stream().limit(2).collect(Collectors.toList())).hasSize(2).contains("spring", "data");
276215
}
277216

278217
@Test // GH-1575
279-
void decoratedCursorShouldForwardClose() {
218+
void streamingCursorShouldForwardClose() {
280219

281220
LinkedList<ScanIteration<String>> values = new LinkedList<>();
282221
values.add(createIteration(1, "spring"));
283222
values.add(createIteration(2, "data"));
284223
values.add(createIteration(3, "redis"));
285224
values.add(createIteration(0));
286225
Cursor<String> cursor = initCursor(values);
287-
Cursor<String> limited = cursor.limit(1);
288226

289227
assertThat(cursor.isClosed()).isFalse();
290-
assertThat(limited.isClosed()).isFalse();
291228

292-
limited.close();
229+
Stream<String> stream = cursor.stream();
230+
stream.collect(Collectors.toList());
231+
stream.close();
293232

294233
assertThat(cursor.isClosed()).isTrue();
295-
assertThat(limited.isClosed()).isTrue();
296234
}
297235

298236
private CapturingCursorDummy initCursor(Queue<ScanIteration<String>> values) {

0 commit comments

Comments
 (0)