Skip to content

Commit 82c7896

Browse files
committed
DATAMONGO-1480 - Add support for noCursorTimeout in Query.
We now allow setting noCursorTimeout for queries using `Query` and `@Meta`. Query query = new Query().noCursorTimeout(); and interface PersonRepository extends CrudRepository<Person, String> { @meta(noCursorTimeout = true) Iterable<Person> findBy(); @meta(noCursorTimeout = true) Stream<Person> streamBy(); }
1 parent 66899a7 commit 82c7896

File tree

8 files changed

+99
-14
lines changed

8 files changed

+99
-14
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@
139139
* @author Christoph Strobl
140140
* @author Doménique Tilleuil
141141
* @author Niko Schmuck
142+
* @author Mark Paluch
142143
*/
143144
@SuppressWarnings("deprecation")
144145
public class MongoTemplate implements MongoOperations, ApplicationContextAware {
@@ -2249,7 +2250,7 @@ public DBObject doInCollection(DBCollection collection) throws MongoException, D
22492250
* @author Thomas Darimont
22502251
*/
22512252

2252-
static interface DbObjectCallback<T> {
2253+
interface DbObjectCallback<T> {
22532254

22542255
T doWith(DBObject object);
22552256
}
@@ -2347,23 +2348,33 @@ public DBCursor prepare(DBCursor cursor) {
23472348
DBCursor cursorToUse = cursor.copy();
23482349

23492350
try {
2351+
23502352
if (query.getSkip() > 0) {
23512353
cursorToUse = cursorToUse.skip(query.getSkip());
23522354
}
2355+
23532356
if (query.getLimit() > 0) {
23542357
cursorToUse = cursorToUse.limit(query.getLimit());
23552358
}
2359+
23562360
if (query.getSortObject() != null) {
23572361
DBObject sortDbo = type != null ? getMappedSortObject(query, type) : query.getSortObject();
23582362
cursorToUse = cursorToUse.sort(sortDbo);
23592363
}
2364+
23602365
if (StringUtils.hasText(query.getHint())) {
23612366
cursorToUse = cursorToUse.hint(query.getHint());
23622367
}
2368+
23632369
if (query.getMeta().hasValues()) {
2370+
23642371
for (Entry<String, Object> entry : query.getMeta().values()) {
23652372
cursorToUse = cursorToUse.addSpecial(entry.getKey(), entry.getValue());
23662373
}
2374+
2375+
if (query.getMeta().isNoCursorTimeout() != null && query.getMeta().isNoCursorTimeout().booleanValue()) {
2376+
cursorToUse = cursorToUse.addOption(Bytes.QUERYOPTION_NOTIMEOUT);
2377+
}
23672378
}
23682379

23692380
} catch (RuntimeException e) {

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Meta.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014 the original author or authors.
2+
* Copyright 2014-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.
@@ -30,6 +30,7 @@
3030
*
3131
* @author Christoph Strobl
3232
* @author Oliver Gierke
33+
* @author Mark Paluch
3334
* @since 1.6
3435
*/
3536
public class Meta {
@@ -39,12 +40,13 @@ private enum MetaKey {
3940

4041
private String key;
4142

42-
private MetaKey(String key) {
43+
MetaKey(String key) {
4344
this.key = key;
4445
}
4546
}
4647

4748
private final Map<String, Object> values = new LinkedHashMap<String, Object>(2);
49+
private Boolean noCursorTimeout;
4850

4951
/**
5052
* @return {@literal null} if not set.
@@ -120,11 +122,29 @@ public boolean getSnapshot() {
120122
return getValue(MetaKey.SNAPSHOT.key, false);
121123
}
122124

125+
/**
126+
* @return {@literal null} if not set.
127+
* @since 1.10
128+
*/
129+
public Boolean isNoCursorTimeout() {
130+
return this.noCursorTimeout;
131+
}
132+
133+
/**
134+
* Instructs the server to avoid closing a cursor automatically after a period of inactivity.
135+
*
136+
* @param noCursorTimeout
137+
* @since 1.10
138+
*/
139+
public void setNoCursorTimeout(boolean noCursorTimeout) {
140+
this.noCursorTimeout = noCursorTimeout;
141+
}
142+
123143
/**
124144
* @return
125145
*/
126146
public boolean hasValues() {
127-
return !this.values.isEmpty();
147+
return !this.values.isEmpty() || this.noCursorTimeout != null;
128148
}
129149

130150
/**

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2010-2015 the original author or authors.
2+
* Copyright 2010-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.
@@ -41,6 +41,7 @@
4141
* @author Oliver Gierke
4242
* @author Thomas Darimont
4343
* @author Christoph Strobl
44+
* @author Mark Paluch
4445
*/
4546
public class Query {
4647

@@ -336,6 +337,17 @@ public Query useSnapshot() {
336337
return this;
337338
}
338339

340+
/**
341+
* @return
342+
* @see Meta#setNoCursorTimeout(boolean)
343+
* @since 1.10
344+
*/
345+
public Query noCursorTimeout() {
346+
347+
meta.setNoCursorTimeout(true);
348+
return this;
349+
}
350+
339351
/**
340352
* @return never {@literal null}.
341353
* @since 1.6

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Meta.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,12 @@
7575
*/
7676
boolean snapshot() default false;
7777

78+
/**
79+
* Instructs the server to avoid closing a cursor automatically after a period of inactivity.
80+
*
81+
* @return
82+
* @since 1.10
83+
*/
84+
boolean noCursorTimeout() default false;
85+
7886
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryMethod.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,10 @@ public org.springframework.data.mongodb.core.query.Meta getQueryMetaAttributes()
248248
metaAttributes.setSnapshot(meta.snapshot());
249249
}
250250

251+
if (meta.noCursorTimeout()) {
252+
metaAttributes.setNoCursorTimeout(meta.noCursorTimeout());
253+
}
254+
251255
return metaAttributes;
252256
}
253257
}

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryCursorPreparerUnitTests.java

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2014 the original author or authors.
2+
* Copyright 2011-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.
@@ -32,13 +32,15 @@
3232
import org.springframework.data.mongodb.core.query.Meta;
3333
import org.springframework.data.mongodb.core.query.Query;
3434

35+
import com.mongodb.Bytes;
3536
import com.mongodb.DBCursor;
3637

3738
/**
3839
* Unit tests for {@link QueryCursorPreparer}.
3940
*
4041
* @author Oliver Gierke
4142
* @author Christoph Strobl
43+
* @author Mark Paluch
4244
*/
4345
@RunWith(MockitoJUnitRunner.class)
4446
public class QueryCursorPreparerUnitTests {
@@ -61,7 +63,7 @@ public void appliesHintsCorrectly() {
6163

6264
Query query = query(where("foo").is("bar")).withHint("hint");
6365

64-
pepare(query);
66+
prepare(query);
6567

6668
verify(cursorToUse).hint("hint");
6769
}
@@ -75,7 +77,7 @@ public void doesNotApplyMetaWhenEmpty() {
7577
Query query = query(where("foo").is("bar"));
7678
query.setMeta(new Meta());
7779

78-
pepare(query);
80+
prepare(query);
7981

8082
verify(cursor, never()).copy();
8183
verify(cursorToUse, never()).addSpecial(any(String.class), anyObject());
@@ -89,7 +91,7 @@ public void appliesMaxScanCorrectly() {
8991

9092
Query query = query(where("foo").is("bar")).maxScan(100);
9193

92-
pepare(query);
94+
prepare(query);
9395

9496
verify(cursorToUse).addSpecial(eq("$maxScan"), eq(100L));
9597
}
@@ -102,7 +104,7 @@ public void appliesMaxTimeCorrectly() {
102104

103105
Query query = query(where("foo").is("bar")).maxTime(1, TimeUnit.SECONDS);
104106

105-
pepare(query);
107+
prepare(query);
106108

107109
verify(cursorToUse).addSpecial(eq("$maxTimeMS"), eq(1000L));
108110
}
@@ -115,7 +117,7 @@ public void appliesCommentCorrectly() {
115117

116118
Query query = query(where("foo").is("bar")).comment("spring data");
117119

118-
pepare(query);
120+
prepare(query);
119121

120122
verify(cursorToUse).addSpecial(eq("$comment"), eq("spring data"));
121123
}
@@ -128,12 +130,25 @@ public void appliesSnapshotCorrectly() {
128130

129131
Query query = query(where("foo").is("bar")).useSnapshot();
130132

131-
pepare(query);
133+
prepare(query);
132134

133135
verify(cursorToUse).addSpecial(eq("$snapshot"), eq(true));
134136
}
135137

136-
private DBCursor pepare(Query query) {
138+
/**
139+
* @see DATAMONGO-1480
140+
*/
141+
@Test
142+
public void appliesNoCursorTimeoutCorrectly() {
143+
144+
Query query = query(where("foo").is("bar")).noCursorTimeout();
145+
146+
prepare(query);
147+
148+
verify(cursorToUse).addOption(Bytes.QUERYOPTION_NOTIMEOUT);
149+
}
150+
151+
private DBCursor prepare(Query query) {
137152

138153
CursorPreparer preparer = new MongoTemplate(factory).new QueryCursorPreparer(query, null);
139154
return preparer.prepare(cursor);

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractMongoQueryUnitTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ private interface Repo extends MongoRepository<Person, Long> {
347347

348348
List<Person> findByFirstname(String firstname);
349349

350-
@Meta(comment = "comment")
350+
@Meta(comment = "comment", noCursorTimeout = true)
351351
Page<Person> findByFirstname(String firstnanme, Pageable pageable);
352352

353353
@Meta(comment = "comment")

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryMethodUnitTests.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,18 @@ public void createsMongoQueryMethodWithSnapshotCorrectly() throws Exception {
201201
assertThat(method.getQueryMetaAttributes().getSnapshot(), is(true));
202202
}
203203

204+
/**
205+
* @see DATAMONGO-1480
206+
*/
207+
@Test
208+
public void createsMongoQueryMethodWithNoCursorTimeoutCorrectly() throws Exception {
209+
210+
MongoQueryMethod method = queryMethod(PersonRepository.class, "metaWithNoCursorTimeout");
211+
212+
assertThat(method.hasQueryMetaAttributes(), is(true));
213+
assertThat(method.getQueryMetaAttributes().isNoCursorTimeout(), is(true));
214+
}
215+
204216
/**
205217
* @see DATAMONGO-1266
206218
*/
@@ -250,6 +262,9 @@ interface PersonRepository extends Repository<User, Long> {
250262
@Meta(snapshot = true)
251263
List<User> metaWithSnapshotUsage();
252264

265+
@Meta(noCursorTimeout = true)
266+
List<User> metaWithNoCursorTimeout();
267+
253268
/**
254269
* @see DATAMONGO-1266
255270
*/

0 commit comments

Comments
 (0)