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();
}
Original Pull Request: #390
This commit is contained in:
committed by
Christoph Strobl
parent
b6bc0ea316
commit
98dca5a65e
@@ -139,6 +139,7 @@ import com.mongodb.util.JSONParseException;
|
||||
* @author Christoph Strobl
|
||||
* @author Doménique Tilleuil
|
||||
* @author Niko Schmuck
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
@@ -2249,7 +2250,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
|
||||
static interface DbObjectCallback<T> {
|
||||
interface DbObjectCallback<T> {
|
||||
|
||||
T doWith(DBObject object);
|
||||
}
|
||||
@@ -2347,23 +2348,33 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DBCursor cursorToUse = cursor.copy();
|
||||
|
||||
try {
|
||||
|
||||
if (query.getSkip() > 0) {
|
||||
cursorToUse = cursorToUse.skip(query.getSkip());
|
||||
}
|
||||
|
||||
if (query.getLimit() > 0) {
|
||||
cursorToUse = cursorToUse.limit(query.getLimit());
|
||||
}
|
||||
|
||||
if (query.getSortObject() != null) {
|
||||
DBObject sortDbo = type != null ? getMappedSortObject(query, type) : query.getSortObject();
|
||||
cursorToUse = cursorToUse.sort(sortDbo);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(query.getHint())) {
|
||||
cursorToUse = cursorToUse.hint(query.getHint());
|
||||
}
|
||||
|
||||
if (query.getMeta().hasValues()) {
|
||||
|
||||
for (Entry<String, Object> entry : query.getMeta().values()) {
|
||||
cursorToUse = cursorToUse.addSpecial(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
if (query.getMeta().isNoCursorTimeout() != null && query.getMeta().isNoCursorTimeout().booleanValue()) {
|
||||
cursorToUse = cursorToUse.addOption(Bytes.QUERYOPTION_NOTIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (RuntimeException e) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,6 +30,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
* @since 1.6
|
||||
*/
|
||||
public class Meta {
|
||||
@@ -39,12 +40,13 @@ public class Meta {
|
||||
|
||||
private String key;
|
||||
|
||||
private MetaKey(String key) {
|
||||
MetaKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
|
||||
private final Map<String, Object> values = new LinkedHashMap<String, Object>(2);
|
||||
private Boolean noCursorTimeout;
|
||||
|
||||
/**
|
||||
* @return {@literal null} if not set.
|
||||
@@ -120,11 +122,29 @@ public class Meta {
|
||||
return getValue(MetaKey.SNAPSHOT.key, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal null} if not set.
|
||||
* @since 1.10
|
||||
*/
|
||||
public Boolean isNoCursorTimeout() {
|
||||
return this.noCursorTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the server to avoid closing a cursor automatically after a period of inactivity.
|
||||
*
|
||||
* @param noCursorTimeout
|
||||
* @since 1.10
|
||||
*/
|
||||
public void setNoCursorTimeout(boolean noCursorTimeout) {
|
||||
this.noCursorTimeout = noCursorTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public boolean hasValues() {
|
||||
return !this.values.isEmpty();
|
||||
return !this.values.isEmpty() || this.noCursorTimeout != null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 the original author or authors.
|
||||
* Copyright 2010-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -41,6 +41,7 @@ import com.mongodb.DBObject;
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class Query {
|
||||
|
||||
@@ -336,6 +337,17 @@ public class Query {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see Meta#setNoCursorTimeout(boolean)
|
||||
* @since 1.10
|
||||
*/
|
||||
public Query noCursorTimeout() {
|
||||
|
||||
meta.setNoCursorTimeout(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return never {@literal null}.
|
||||
* @since 1.6
|
||||
|
||||
@@ -75,4 +75,12 @@ public @interface Meta {
|
||||
*/
|
||||
boolean snapshot() default false;
|
||||
|
||||
/**
|
||||
* Instructs the server to avoid closing a cursor automatically after a period of inactivity.
|
||||
*
|
||||
* @return
|
||||
* @since 1.10
|
||||
*/
|
||||
boolean noCursorTimeout() default false;
|
||||
|
||||
}
|
||||
|
||||
@@ -248,6 +248,10 @@ public class MongoQueryMethod extends QueryMethod {
|
||||
metaAttributes.setSnapshot(meta.snapshot());
|
||||
}
|
||||
|
||||
if (meta.noCursorTimeout()) {
|
||||
metaAttributes.setNoCursorTimeout(meta.noCursorTimeout());
|
||||
}
|
||||
|
||||
return metaAttributes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
* Copyright 2011-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,6 +32,7 @@ import org.springframework.data.mongodb.core.MongoTemplate.QueryCursorPreparer;
|
||||
import org.springframework.data.mongodb.core.query.Meta;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
|
||||
import com.mongodb.Bytes;
|
||||
import com.mongodb.DBCursor;
|
||||
|
||||
/**
|
||||
@@ -39,6 +40,7 @@ import com.mongodb.DBCursor;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QueryCursorPreparerUnitTests {
|
||||
@@ -61,7 +63,7 @@ public class QueryCursorPreparerUnitTests {
|
||||
|
||||
Query query = query(where("foo").is("bar")).withHint("hint");
|
||||
|
||||
pepare(query);
|
||||
prepare(query);
|
||||
|
||||
verify(cursorToUse).hint("hint");
|
||||
}
|
||||
@@ -75,7 +77,7 @@ public class QueryCursorPreparerUnitTests {
|
||||
Query query = query(where("foo").is("bar"));
|
||||
query.setMeta(new Meta());
|
||||
|
||||
pepare(query);
|
||||
prepare(query);
|
||||
|
||||
verify(cursor, never()).copy();
|
||||
verify(cursorToUse, never()).addSpecial(any(String.class), anyObject());
|
||||
@@ -89,7 +91,7 @@ public class QueryCursorPreparerUnitTests {
|
||||
|
||||
Query query = query(where("foo").is("bar")).maxScan(100);
|
||||
|
||||
pepare(query);
|
||||
prepare(query);
|
||||
|
||||
verify(cursorToUse).addSpecial(eq("$maxScan"), eq(100L));
|
||||
}
|
||||
@@ -102,7 +104,7 @@ public class QueryCursorPreparerUnitTests {
|
||||
|
||||
Query query = query(where("foo").is("bar")).maxTime(1, TimeUnit.SECONDS);
|
||||
|
||||
pepare(query);
|
||||
prepare(query);
|
||||
|
||||
verify(cursorToUse).addSpecial(eq("$maxTimeMS"), eq(1000L));
|
||||
}
|
||||
@@ -115,7 +117,7 @@ public class QueryCursorPreparerUnitTests {
|
||||
|
||||
Query query = query(where("foo").is("bar")).comment("spring data");
|
||||
|
||||
pepare(query);
|
||||
prepare(query);
|
||||
|
||||
verify(cursorToUse).addSpecial(eq("$comment"), eq("spring data"));
|
||||
}
|
||||
@@ -128,12 +130,25 @@ public class QueryCursorPreparerUnitTests {
|
||||
|
||||
Query query = query(where("foo").is("bar")).useSnapshot();
|
||||
|
||||
pepare(query);
|
||||
prepare(query);
|
||||
|
||||
verify(cursorToUse).addSpecial(eq("$snapshot"), eq(true));
|
||||
}
|
||||
|
||||
private DBCursor pepare(Query query) {
|
||||
/**
|
||||
* @see DATAMONGO-1480
|
||||
*/
|
||||
@Test
|
||||
public void appliesNoCursorTimeoutCorrectly() {
|
||||
|
||||
Query query = query(where("foo").is("bar")).noCursorTimeout();
|
||||
|
||||
prepare(query);
|
||||
|
||||
verify(cursorToUse).addOption(Bytes.QUERYOPTION_NOTIMEOUT);
|
||||
}
|
||||
|
||||
private DBCursor prepare(Query query) {
|
||||
|
||||
CursorPreparer preparer = new MongoTemplate(factory).new QueryCursorPreparer(query, null);
|
||||
return preparer.prepare(cursor);
|
||||
|
||||
@@ -347,7 +347,7 @@ public class AbstractMongoQueryUnitTests {
|
||||
|
||||
List<Person> findByFirstname(String firstname);
|
||||
|
||||
@Meta(comment = "comment")
|
||||
@Meta(comment = "comment", noCursorTimeout = true)
|
||||
Page<Person> findByFirstname(String firstnanme, Pageable pageable);
|
||||
|
||||
@Meta(comment = "comment")
|
||||
|
||||
@@ -201,6 +201,18 @@ public class MongoQueryMethodUnitTests {
|
||||
assertThat(method.getQueryMetaAttributes().getSnapshot(), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1480
|
||||
*/
|
||||
@Test
|
||||
public void createsMongoQueryMethodWithNoCursorTimeoutCorrectly() throws Exception {
|
||||
|
||||
MongoQueryMethod method = queryMethod(PersonRepository.class, "metaWithNoCursorTimeout");
|
||||
|
||||
assertThat(method.hasQueryMetaAttributes(), is(true));
|
||||
assertThat(method.getQueryMetaAttributes().isNoCursorTimeout(), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1266
|
||||
*/
|
||||
@@ -250,6 +262,9 @@ public class MongoQueryMethodUnitTests {
|
||||
@Meta(snapshot = true)
|
||||
List<User> metaWithSnapshotUsage();
|
||||
|
||||
@Meta(noCursorTimeout = true)
|
||||
List<User> metaWithNoCursorTimeout();
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1266
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user