Skip to content

Commit ca29374

Browse files
committed
Forward maxTimeMsec from Query to FindOneAndUpdateOptions.
Closes spring-projects#4776
1 parent 7fbd496 commit ca29374

File tree

2 files changed

+42
-31
lines changed

2 files changed

+42
-31
lines changed

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

+31-31
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@
181181
* @author Bartłomiej Mazur
182182
* @author Michael Krog
183183
* @author Jakub Zurawa
184+
* @author Kinjarapu Sriram
184185
*/
185186
public class MongoTemplate
186187
implements MongoOperations, ApplicationContextAware, IndexOperationsProvider, ReadPreferenceAware {
@@ -1088,7 +1089,7 @@ public <T> T findAndModify(Query query, UpdateDefinition update, FindAndModifyOp
10881089
operations.forType(entityClass).getCollation(query).ifPresent(optionsToUse::collation);
10891090
}
10901091

1091-
return doFindAndModify(createDelegate(query), collectionName, query.getQueryObject(), query.getFieldsObject(),
1092+
return doFindAndModify(createDelegate(query), collectionName, query, query.getFieldsObject(),
10921093
getMappedSortObject(query, entityClass), entityClass, update, optionsToUse);
10931094
}
10941095

@@ -2718,7 +2719,7 @@ protected <T> T doFindAndRemove(CollectionPreparer collectionPreparer, String co
27182719
}
27192720

27202721
@SuppressWarnings("ConstantConditions")
2721-
protected <T> T doFindAndModify(CollectionPreparer collectionPreparer, String collectionName, Document query,
2722+
protected <T> T doFindAndModify(CollectionPreparer collectionPreparer, String collectionName, Query query,
27222723
Document fields, Document sort, Class<T> entityClass, UpdateDefinition update,
27232724
@Nullable FindAndModifyOptions options) {
27242725

@@ -2728,13 +2729,35 @@ protected <T> T doFindAndModify(CollectionPreparer collectionPreparer, String co
27282729

27292730
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
27302731

2731-
UpdateContext updateContext = queryOperations.updateSingleContext(update, query, false);
2732+
UpdateContext updateContext = queryOperations.updateSingleContext(update, query.getQueryObject(), false);
27322733
updateContext.increaseVersionForUpdateIfNecessary(entity);
27332734

27342735
Document mappedQuery = updateContext.getMappedQuery(entity);
27352736
Object mappedUpdate = updateContext.isAggregationUpdate() ? updateContext.getUpdatePipeline(entityClass)
27362737
: updateContext.getMappedUpdate(entity);
27372738

2739+
FindOneAndUpdateOptions opts = new FindOneAndUpdateOptions();
2740+
opts.sort(sort);
2741+
if (options.isUpsert()) {
2742+
opts.upsert(true);
2743+
}
2744+
opts.projection(fields);
2745+
if (options.isReturnNew()) {
2746+
opts.returnDocument(ReturnDocument.AFTER);
2747+
}
2748+
options.getCollation().map(Collation::toMongoCollation).ifPresent(opts::collation);
2749+
List<Document> arrayFilters = update.getArrayFilters().stream().map(ArrayFilter::asDocument).collect(Collectors.toList());
2750+
if (!arrayFilters.isEmpty()) {
2751+
opts.arrayFilters(arrayFilters);
2752+
}
2753+
Meta meta = query.getMeta();
2754+
if (meta.hasValues()) {
2755+
2756+
if (meta.hasMaxTime()) {
2757+
opts.maxTime(meta.getRequiredMaxTimeMsec(), TimeUnit.MILLISECONDS);
2758+
}
2759+
}
2760+
27382761
if (LOGGER.isDebugEnabled()) {
27392762
LOGGER.debug(String.format(
27402763
"findAndModify using query: %s fields: %s sort: %s for class: %s and update: %s in collection: %s",
@@ -2744,8 +2767,7 @@ protected <T> T doFindAndModify(CollectionPreparer collectionPreparer, String co
27442767
}
27452768

27462769
return executeFindOneInternal(
2747-
new FindAndModifyCallback(collectionPreparer, mappedQuery, fields, sort, mappedUpdate,
2748-
update.getArrayFilters().stream().map(ArrayFilter::asDocument).collect(Collectors.toList()), options),
2770+
new FindAndModifyCallback(collectionPreparer, mappedQuery, mappedUpdate, opts),
27492771
new ReadDocumentCallback<>(this.mongoConverter, entityClass, collectionName), collectionName);
27502772
}
27512773

@@ -3157,47 +3179,25 @@ private static class FindAndModifyCallback implements CollectionCallback<Documen
31573179

31583180
private final CollectionPreparer<MongoCollection<Document>> collectionPreparer;
31593181
private final Document query;
3160-
private final Document fields;
3161-
private final Document sort;
31623182
private final Object update;
3163-
private final List<Document> arrayFilters;
3164-
private final FindAndModifyOptions options;
3183+
private final FindOneAndUpdateOptions options;
31653184

31663185
FindAndModifyCallback(CollectionPreparer<MongoCollection<Document>> collectionPreparer, Document query,
3167-
Document fields, Document sort, Object update, List<Document> arrayFilters, FindAndModifyOptions options) {
3186+
Object update, FindOneAndUpdateOptions options) {
31683187

31693188
this.collectionPreparer = collectionPreparer;
31703189
this.query = query;
3171-
this.fields = fields;
3172-
this.sort = sort;
31733190
this.update = update;
3174-
this.arrayFilters = arrayFilters;
31753191
this.options = options;
31763192
}
31773193

31783194
@Override
31793195
public Document doInCollection(MongoCollection<Document> collection) throws MongoException, DataAccessException {
31803196

3181-
FindOneAndUpdateOptions opts = new FindOneAndUpdateOptions();
3182-
opts.sort(sort);
3183-
if (options.isUpsert()) {
3184-
opts.upsert(true);
3185-
}
3186-
opts.projection(fields);
3187-
if (options.isReturnNew()) {
3188-
opts.returnDocument(ReturnDocument.AFTER);
3189-
}
3190-
3191-
options.getCollation().map(Collation::toMongoCollation).ifPresent(opts::collation);
3192-
3193-
if (!arrayFilters.isEmpty()) {
3194-
opts.arrayFilters(arrayFilters);
3195-
}
3196-
31973197
if (update instanceof Document document) {
3198-
return collectionPreparer.prepare(collection).findOneAndUpdate(query, document, opts);
3198+
return collectionPreparer.prepare(collection).findOneAndUpdate(query, document, options);
31993199
} else if (update instanceof List) {
3200-
return collectionPreparer.prepare(collection).findOneAndUpdate(query, (List<Document>) update, opts);
3200+
return collectionPreparer.prepare(collection).findOneAndUpdate(query, (List<Document>) update, options);
32013201
}
32023202

32033203
throw new IllegalArgumentException(String.format("Using %s is not supported in findOneAndUpdate", update));

Diff for: spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java

+11
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@
141141
* @author Roman Puchkovskiy
142142
* @author Yadhukrishna S Pai
143143
* @author Jakub Zurawa
144+
* @author Kinjarapu Sriram
144145
*/
145146
@MockitoSettings(strictness = Strictness.LENIENT)
146147
public class MongoTemplateUnitTests extends MongoOperationsUnitTests {
@@ -2536,6 +2537,16 @@ public WriteConcern resolve(MongoAction action) {
25362537
verify(collection).withWriteConcern(eq(WriteConcern.UNACKNOWLEDGED));
25372538
}
25382539

2540+
@Test // GH-4776
2541+
void findAndModifyConsidersMaxTimeMs() {
2542+
2543+
template.findAndModify(new BasicQuery("{ 'spring' : 'data-mongodb' }").maxTimeMsec(5000), new Update(), Human.class);
2544+
2545+
ArgumentCaptor<FindOneAndUpdateOptions> options = ArgumentCaptor.forClass(FindOneAndUpdateOptions.class);
2546+
verify(collection).findOneAndUpdate(any(Bson.class), any(Bson.class), options.capture());
2547+
assertThat(options.getValue().getMaxTime(TimeUnit.MILLISECONDS)).isEqualTo(5000);
2548+
}
2549+
25392550
class AutogenerateableId {
25402551

25412552
@Id BigInteger id;

0 commit comments

Comments
 (0)