DATAMONGO-1480 - Polishing.

Opened up Meta attributes to now allowing usage of more than one cursor option via dedicated enum.

new Query().noCursorTimeout();

and

interface PersonRepository extends CrudRepository<Person, String> {

    @Meta(flags = {CursorOptions.NO_TIMEOUT})
    Iterable<Person> findBy();
}

Original Pull Request: #390
This commit is contained in:
Christoph Strobl
2016-10-06 12:56:03 +02:00
parent 98dca5a65e
commit 10208001f8
7 changed files with 132 additions and 25 deletions

View File

@@ -93,6 +93,7 @@ import org.springframework.data.mongodb.core.mapreduce.GroupByResults;
import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions;
import org.springframework.data.mongodb.core.mapreduce.MapReduceResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Meta;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
@@ -2372,8 +2373,24 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
cursorToUse = cursorToUse.addSpecial(entry.getKey(), entry.getValue());
}
if (query.getMeta().isNoCursorTimeout() != null && query.getMeta().isNoCursorTimeout().booleanValue()) {
cursorToUse = cursorToUse.addOption(Bytes.QUERYOPTION_NOTIMEOUT);
for (Meta.CursorOption option : query.getMeta().getFlags()) {
switch (option) {
case EXHAUST:
cursorToUse = cursorToUse.addOption(Bytes.QUERYOPTION_EXHAUST);
break;
case NO_TIMEOUT:
cursorToUse = cursorToUse.addOption(Bytes.QUERYOPTION_NOTIMEOUT);
break;
case PARTIAL:
cursorToUse = cursorToUse.addOption(Bytes.QUERYOPTION_PARTIAL);
break;
case SLAVE_OK:
cursorToUse = cursorToUse.addOption(Bytes.QUERYOPTION_SLAVEOK);
break;
default:
throw new IllegalArgumentException(String.format("%s is no supported flag.", option));
}
}
}

View File

@@ -17,8 +17,10 @@ package org.springframework.data.mongodb.core.query;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.util.Assert;
@@ -46,7 +48,7 @@ public class Meta {
}
private final Map<String, Object> values = new LinkedHashMap<String, Object>(2);
private Boolean noCursorTimeout;
private final Set<CursorOption> flags = new LinkedHashSet<CursorOption>();
/**
* @return {@literal null} if not set.
@@ -123,28 +125,31 @@ public class Meta {
}
/**
* @return {@literal null} if not set.
* Add {@link CursorOption} influencing behavior of the {@link com.mongodb.DBCursor}.
*
* @param option must not be {@literal null}.
* @return
* @since 1.10
*/
public Boolean isNoCursorTimeout() {
return this.noCursorTimeout;
public boolean addFlag(CursorOption option) {
Assert.notNull(option, "CursorOption must not be null!");
return this.flags.add(option);
}
/**
* Instructs the server to avoid closing a cursor automatically after a period of inactivity.
*
* @param noCursorTimeout
* @return never {@literal null}.
* @since 1.10
*/
public void setNoCursorTimeout(boolean noCursorTimeout) {
this.noCursorTimeout = noCursorTimeout;
public Set<CursorOption> getFlags() {
return flags;
}
/**
* @return
*/
public boolean hasValues() {
return !this.values.isEmpty() || this.noCursorTimeout != null;
return !this.values.isEmpty() || !this.flags.isEmpty();
}
/**
@@ -189,7 +194,10 @@ public class Meta {
*/
@Override
public int hashCode() {
return ObjectUtils.nullSafeHashCode(this.values);
int hash = ObjectUtils.nullSafeHashCode(this.values);
hash += ObjectUtils.nullSafeHashCode(this.flags);
return hash;
}
/*
@@ -208,6 +216,35 @@ public class Meta {
}
Meta other = (Meta) obj;
return ObjectUtils.nullSafeEquals(this.values, other.values);
if (!ObjectUtils.nullSafeEquals(this.values, other.values)) {
return false;
}
return ObjectUtils.nullSafeEquals(this.flags, other.flags);
}
/**
* {@link CursorOption} represents {@code OP_QUERY} wire protocol flags to change the behavior of queries.
*
* @author Christoph Strobl
* @since 1.10
*/
public enum CursorOption {
/** Prevents the server from timing out idle cursors. */
NO_TIMEOUT,
/**
* Sets the cursor to return all data returned by the query at once rather than splitting the results into batches.
*/
EXHAUST,
/** Allows querying of a replica slave. */
SLAVE_OK,
/**
* Sets the cursor to return partial data from a query against a sharded cluster in which some shards do not respond
* rather than throwing an error.
*/
PARTIAL
}
}

View File

@@ -339,12 +339,45 @@ public class Query {
/**
* @return
* @see Meta#setNoCursorTimeout(boolean)
* @see org.springframework.data.mongodb.core.query.Meta.CursorOption#NO_TIMEOUT
* @since 1.10
*/
public Query noCursorTimeout() {
meta.setNoCursorTimeout(true);
meta.addFlag(Meta.CursorOption.NO_TIMEOUT);
return this;
}
/**
* @return
* @see org.springframework.data.mongodb.core.query.Meta.CursorOption#EXHAUST
* @since 1.10
*/
public Query exhaust() {
meta.addFlag(Meta.CursorOption.EXHAUST);
return this;
}
/**
* @return
* @see org.springframework.data.mongodb.core.query.Meta.CursorOption#SLAVE_OK
* @since 1.10
*/
public Query slaveOk() {
meta.addFlag(Meta.CursorOption.SLAVE_OK);
return this;
}
/**
* @return
* @see org.springframework.data.mongodb.core.query.Meta.CursorOption#PARTIAL
* @since 1.10
*/
public Query partialResults() {
meta.addFlag(Meta.CursorOption.PARTIAL);
return this;
}

View File

@@ -76,11 +76,11 @@ public @interface Meta {
boolean snapshot() default false;
/**
* Instructs the server to avoid closing a cursor automatically after a period of inactivity.
* Set {@link org.springframework.data.mongodb.core.query.Meta.CursorOption} to be used when executing query.
*
* @return
* @return never {@literal null}.
* @since 1.10
*/
boolean noCursorTimeout() default false;
org.springframework.data.mongodb.core.query.Meta.CursorOption[] flags() default {};
}

View File

@@ -37,6 +37,7 @@ import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
@@ -248,8 +249,11 @@ public class MongoQueryMethod extends QueryMethod {
metaAttributes.setSnapshot(meta.snapshot());
}
if (meta.noCursorTimeout()) {
metaAttributes.setNoCursorTimeout(meta.noCursorTimeout());
if (!ObjectUtils.isEmpty(meta.flags())) {
for (org.springframework.data.mongodb.core.query.Meta.CursorOption option : meta.flags()) {
metaAttributes.addFlag(option);
}
}
return metaAttributes;

View File

@@ -347,7 +347,7 @@ public class AbstractMongoQueryUnitTests {
List<Person> findByFirstname(String firstname);
@Meta(comment = "comment", noCursorTimeout = true)
@Meta(comment = "comment", flags = {org.springframework.data.mongodb.core.query.Meta.CursorOption.NO_TIMEOUT})
Page<Person> findByFirstname(String firstnanme, Pageable pageable);
@Meta(comment = "comment")

View File

@@ -152,7 +152,6 @@ public class MongoQueryMethodUnitTests {
assertThat(method.getQueryMetaAttributes().getMaxTimeMsec(), is(100L));
}
/**
* @see DATAMONGO-1403
*/
@@ -210,7 +209,21 @@ public class MongoQueryMethodUnitTests {
MongoQueryMethod method = queryMethod(PersonRepository.class, "metaWithNoCursorTimeout");
assertThat(method.hasQueryMetaAttributes(), is(true));
assertThat(method.getQueryMetaAttributes().isNoCursorTimeout(), is(true));
assertThat(method.getQueryMetaAttributes().getFlags(),
containsInAnyOrder(org.springframework.data.mongodb.core.query.Meta.CursorOption.NO_TIMEOUT));
}
/**
* @see DATAMONGO-1480
*/
@Test
public void createsMongoQueryMethodWithMultipleFlagsCorrectly() throws Exception {
MongoQueryMethod method = queryMethod(PersonRepository.class, "metaWithMultipleFlags");
assertThat(method.hasQueryMetaAttributes(), is(true));
assertThat(method.getQueryMetaAttributes().getFlags(),
containsInAnyOrder(org.springframework.data.mongodb.core.query.Meta.CursorOption.NO_TIMEOUT, org.springframework.data.mongodb.core.query.Meta.CursorOption.SLAVE_OK));
}
/**
@@ -262,9 +275,12 @@ public class MongoQueryMethodUnitTests {
@Meta(snapshot = true)
List<User> metaWithSnapshotUsage();
@Meta(noCursorTimeout = true)
@Meta(flags = { org.springframework.data.mongodb.core.query.Meta.CursorOption.NO_TIMEOUT })
List<User> metaWithNoCursorTimeout();
@Meta(flags = { org.springframework.data.mongodb.core.query.Meta.CursorOption.NO_TIMEOUT, org.springframework.data.mongodb.core.query.Meta.CursorOption.SLAVE_OK })
List<User> metaWithMultipleFlags();
/**
* @see DATAMONGO-1266
*/