diff --git a/pom.xml b/pom.xml
index 15b2d67f47..795669a69e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-mongodb-parent
- 2.3.0.BUILD-SNAPSHOT
+ 2.3.0.DATAMONGO-2390-SNAPSHOT
pom
Spring Data MongoDB
diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml
index c4766040c1..3e792bdd8e 100644
--- a/spring-data-mongodb-benchmarks/pom.xml
+++ b/spring-data-mongodb-benchmarks/pom.xml
@@ -7,7 +7,7 @@
org.springframework.data
spring-data-mongodb-parent
- 2.3.0.BUILD-SNAPSHOT
+ 2.3.0.DATAMONGO-2390-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml
index ed39c63e76..5e77abc0b6 100644
--- a/spring-data-mongodb-distribution/pom.xml
+++ b/spring-data-mongodb-distribution/pom.xml
@@ -14,7 +14,7 @@
org.springframework.data
spring-data-mongodb-parent
- 2.3.0.BUILD-SNAPSHOT
+ 2.3.0.DATAMONGO-2390-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index 25cf02b5d5..b0f9c5be22 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -11,7 +11,7 @@
org.springframework.data
spring-data-mongodb-parent
- 2.3.0.BUILD-SNAPSHOT
+ 2.3.0.DATAMONGO-2390-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java
index 79e1d603ac..569112cf10 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java
@@ -2190,6 +2190,10 @@ protected AggregationResults doAggregate(Aggregation aggregation, String
options.getComment().ifPresent(aggregateIterable::comment);
+ if(options.hasExecutionTimeLimit()) {
+ aggregateIterable = aggregateIterable.maxTime(options.getMaxTime().toMillis(), TimeUnit.MILLISECONDS);
+ }
+
MongoIterable iterable = aggregateIterable.map(val -> {
rawResult.add(val);
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java
index 0dcab3e87b..b7cbe483d4 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java
@@ -1073,6 +1073,10 @@ private Flux aggregateAndMap(MongoCollection collection, List cursor;
private final Optional collation;
private final Optional comment;
+ private Duration maxTime = Duration.ZERO;
/**
* Creates a new {@link AggregationOptions}.
@@ -129,7 +132,11 @@ public static AggregationOptions fromDocument(Document document) {
: null;
String comment = document.getString(COMMENT);
- return new AggregationOptions(allowDiskUse, explain, cursor, collation, comment);
+ AggregationOptions options = new AggregationOptions(allowDiskUse, explain, cursor, collation, comment);
+ if (document.containsKey(MAX_TIME)) {
+ options.maxTime = Duration.ofMillis(document.getLong(MAX_TIME));
+ }
+ return options;
}
/**
@@ -206,6 +213,14 @@ public Optional getComment() {
return comment;
}
+ /**
+ * @return the time limit for processing. {@link Duration#ZERO} is used for the default unbounded behavior.
+ * @since 2.3
+ */
+ public Duration getMaxTime() {
+ return maxTime;
+ }
+
/**
* Returns a new potentially adjusted copy for the given {@code aggregationCommandObject} with the configuration
* applied.
@@ -233,6 +248,10 @@ Document applyAndReturnPotentiallyChangedCommand(Document command) {
collation.map(Collation::toDocument).ifPresent(val -> result.append(COLLATION, val));
}
+ if (hasExecutionTimeLimit() && !result.containsKey(MAX_TIME)) {
+ result.append(MAX_TIME, maxTime.toMillis());
+ }
+
return result;
}
@@ -251,9 +270,17 @@ public Document toDocument() {
collation.ifPresent(val -> document.append(COLLATION, val.toDocument()));
comment.ifPresent(val -> document.append(COMMENT, val));
+ if (hasExecutionTimeLimit()) {
+ document.append(MAX_TIME, maxTime.toMillis());
+ }
+
return document;
}
+ public boolean hasExecutionTimeLimit() {
+ return !maxTime.isZero() && !maxTime.isNegative();
+ }
+
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@@ -279,6 +306,7 @@ public static class Builder {
private @Nullable Document cursor;
private @Nullable Collation collation;
private @Nullable String comment;
+ private @Nullable Duration maxTime;
/**
* Defines whether to off-load intensive sort-operations to disk.
@@ -355,13 +383,33 @@ public Builder comment(@Nullable String comment) {
return this;
}
+ /**
+ * Set the time limit for processing.
+ *
+ * @param maxTime {@link Duration#ZERO} is used for the default unbounded behavior. {@link Duration#isNegative()
+ * Negative} values will be ignored.
+ * @return this.
+ * @sinve 2.3
+ */
+ public Builder maxTime(@Nullable Duration maxTime) {
+
+ this.maxTime = maxTime;
+ return this;
+ }
+
/**
* Returns a new {@link AggregationOptions} instance with the given configuration.
*
* @return
*/
public AggregationOptions build() {
- return new AggregationOptions(allowDiskUse, explain, cursor, collation, comment);
+
+ AggregationOptions options = new AggregationOptions(allowDiskUse, explain, cursor, collation, comment);
+ if (maxTime != null) {
+ options.maxTime = maxTime;
+ }
+
+ return options;
}
}
}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoOperationsUnitTests.java
index 0a2cba248a..69cc26f8ae 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoOperationsUnitTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoOperationsUnitTests.java
@@ -22,11 +22,11 @@
import org.bson.Document;
import org.bson.conversions.Bson;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.dao.DataAccessException;
import org.springframework.data.geo.Point;
import org.springframework.data.mapping.MappingException;
@@ -49,7 +49,7 @@
* @author Thomas Darimont
* @author Christoph Strobl
*/
-@RunWith(MockitoJUnitRunner.class)
+@ExtendWith(MockitoExtension.class)
public abstract class MongoOperationsUnitTests {
@Mock CollectionCallback