Skip to content

Commit 13ab2b9

Browse files
authored
Automatically close scroll context when returning streamed results.
Original Pull Request #1746 Closes #1745
1 parent 3500dad commit 13ab2b9

File tree

2 files changed

+44
-12
lines changed

2 files changed

+44
-12
lines changed

Diff for: src/main/java/org/springframework/data/elasticsearch/core/StreamQueries.java

+19-9
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,14 @@ static <T> SearchHitsIterator<T> streamResults(int maxCount, SearchScrollHits<T>
6666
private volatile Iterator<SearchHit<T>> currentScrollHits = searchHits.iterator();
6767
private volatile boolean continueScroll = currentScrollHits.hasNext();
6868
private volatile ScrollState scrollState = new ScrollState(searchHits.getScrollId());
69+
private volatile boolean isClosed = false;
6970

7071
@Override
7172
public void close() {
72-
clearScrollConsumer.accept(scrollState.getScrollIds());
73+
if (!isClosed) {
74+
clearScrollConsumer.accept(scrollState.getScrollIds());
75+
isClosed = true;
76+
}
7377
}
7478

7579
@Override
@@ -96,18 +100,24 @@ public TotalHitsRelation getTotalHitsRelation() {
96100
@Override
97101
public boolean hasNext() {
98102

99-
if (!continueScroll || (maxCount > 0 && currentCount.get() >= maxCount)) {
100-
return false;
103+
boolean hasNext = false;
104+
105+
if (!isClosed && continueScroll && (maxCount <= 0 || currentCount.get() < maxCount)) {
106+
107+
if (!currentScrollHits.hasNext()) {
108+
SearchScrollHits<T> nextPage = continueScrollFunction.apply(scrollState.getScrollId());
109+
currentScrollHits = nextPage.iterator();
110+
scrollState.updateScrollId(nextPage.getScrollId());
111+
continueScroll = currentScrollHits.hasNext();
112+
}
113+
hasNext = currentScrollHits.hasNext();
101114
}
102115

103-
if (!currentScrollHits.hasNext()) {
104-
SearchScrollHits<T> nextPage = continueScrollFunction.apply(scrollState.getScrollId());
105-
currentScrollHits = nextPage.iterator();
106-
scrollState.updateScrollId(nextPage.getScrollId());
107-
continueScroll = currentScrollHits.hasNext();
116+
if (!hasNext) {
117+
close();
108118
}
109119

110-
return currentScrollHits.hasNext();
120+
return hasNext;
111121
}
112122

113123
@Override

Diff for: src/test/java/org/springframework/data/elasticsearch/core/StreamQueriesTest.java

+25-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.List;
2525
import java.util.concurrent.atomic.AtomicBoolean;
2626

27+
import org.junit.jupiter.api.DisplayName;
2728
import org.junit.jupiter.api.Test;
2829
import org.springframework.data.util.StreamUtils;
2930

@@ -39,6 +40,8 @@ public void shouldCallClearScrollOnIteratorClose() {
3940
// given
4041
List<SearchHit<String>> hits = new ArrayList<>();
4142
hits.add(getOneSearchHit());
43+
hits.add(getOneSearchHit());
44+
hits.add(getOneSearchHit());
4245

4346
SearchScrollHits<String> searchHits = newSearchScrollHits(hits, "1234");
4447

@@ -51,16 +54,35 @@ public void shouldCallClearScrollOnIteratorClose() {
5154
scrollId -> newSearchScrollHits(Collections.emptyList(), scrollId), //
5255
scrollIds -> clearScrollCalled.set(true));
5356

54-
while (iterator.hasNext()) {
55-
iterator.next();
56-
}
57+
iterator.next();
5758
iterator.close();
5859

5960
// then
6061
assertThat(clearScrollCalled).isTrue();
6162

6263
}
6364

65+
@Test // #1745
66+
@DisplayName("should call clearScroll when no more data is available")
67+
void shouldCallClearScrollWhenNoMoreDataIsAvailable() {
68+
69+
List<SearchHit<String>> hits = new ArrayList<>();
70+
hits.add(getOneSearchHit());
71+
SearchScrollHits<String> searchHits = newSearchScrollHits(hits, "1234");
72+
AtomicBoolean clearScrollCalled = new AtomicBoolean(false);
73+
74+
SearchHitsIterator<String> iterator = StreamQueries.streamResults( //
75+
0, //
76+
searchHits, //
77+
scrollId -> newSearchScrollHits(Collections.emptyList(), scrollId), //
78+
scrollIds -> clearScrollCalled.set(true));
79+
80+
while (iterator.hasNext()) {
81+
iterator.next();
82+
}
83+
84+
assertThat(clearScrollCalled).isTrue();
85+
}
6486
private SearchHit<String> getOneSearchHit() {
6587
return new SearchHit<String>(null, null, null, 0, null, null, null, null, null, null, "one");
6688
}

0 commit comments

Comments
 (0)