Skip to content

Commit 0c1512e

Browse files
committed
Validate timeoutMode before getting a binding
1 parent 25e1145 commit 0c1512e

File tree

11 files changed

+86
-87
lines changed

11 files changed

+86
-87
lines changed

driver-core/src/main/com/mongodb/internal/operation/AggregateOperationImpl.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
import static com.mongodb.internal.operation.CommandOperationHelper.CommandCreator;
4646
import static com.mongodb.internal.operation.OperationHelper.LOGGER;
4747
import static com.mongodb.internal.operation.OperationHelper.addMaxTimeMSToNonTailableCursor;
48-
import static com.mongodb.internal.operation.OperationHelper.validateTimeoutMode;
4948
import static com.mongodb.internal.operation.OperationReadConcernHelper.appendReadConcernToCommand;
5049
import static com.mongodb.internal.operation.SyncOperationHelper.CommandReadTransformer;
5150
import static com.mongodb.internal.operation.SyncOperationHelper.executeRetryableRead;
@@ -191,7 +190,6 @@ private CommandCreator getCommandCreator() {
191190
}
192191

193192
BsonDocument getCommand(final OperationContext operationContext, final int maxWireVersion) {
194-
validateTimeoutMode(operationContext, timeoutMode);
195193
BsonDocument commandDocument = new BsonDocument("aggregate", aggregateTarget.create());
196194
appendReadConcernToCommand(operationContext.getSessionContext(), maxWireVersion, commandDocument);
197195
commandDocument.put("pipeline", pipelineCreator.create());

driver-core/src/main/com/mongodb/internal/operation/ChangeStreamOperation.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.mongodb.internal.operation;
1818

1919
import com.mongodb.MongoNamespace;
20+
import com.mongodb.client.cursor.TimeoutMode;
2021
import com.mongodb.client.model.Collation;
2122
import com.mongodb.client.model.changestream.FullDocument;
2223
import com.mongodb.client.model.changestream.FullDocumentBeforeChange;
@@ -71,7 +72,7 @@ public ChangeStreamOperation(final MongoNamespace namespace, final FullDocument
7172
final FullDocumentBeforeChange fullDocumentBeforeChange, final List<BsonDocument> pipeline, final Decoder<T> decoder,
7273
final ChangeStreamLevel changeStreamLevel) {
7374
this.wrapped = new AggregateOperationImpl<>(namespace, pipeline, RAW_BSON_DOCUMENT_CODEC, getAggregateTarget(),
74-
getPipelineCreator());
75+
getPipelineCreator()).timeoutMode(TimeoutMode.ITERATION);
7576
this.fullDocument = notNull("fullDocument", fullDocument);
7677
this.fullDocumentBeforeChange = notNull("fullDocumentBeforeChange", fullDocumentBeforeChange);
7778
this.decoder = notNull("decoder", decoder);

driver-core/src/main/com/mongodb/internal/operation/FindOperation.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@
5454
import static com.mongodb.internal.operation.OperationHelper.LOGGER;
5555
import static com.mongodb.internal.operation.OperationHelper.addMaxTimeMSToNonTailableCursor;
5656
import static com.mongodb.internal.operation.OperationHelper.canRetryRead;
57-
import static com.mongodb.internal.operation.OperationHelper.validateTimeoutMode;
5857
import static com.mongodb.internal.operation.OperationReadConcernHelper.appendReadConcernToCommand;
5958
import static com.mongodb.internal.operation.ServerVersionHelper.MIN_WIRE_VERSION;
6059
import static com.mongodb.internal.operation.SyncOperationHelper.CommandReadTransformer;
@@ -370,7 +369,6 @@ <R> CommandReadOperation<R> createExplainableOperation(@Nullable final ExplainVe
370369
}
371370

372371
private BsonDocument getCommand(final OperationContext operationContext, final int maxWireVersion) {
373-
validateTimeoutMode(operationContext, timeoutMode);
374372
BsonDocument commandDocument = new BsonDocument("find", new BsonString(namespace.getCollectionName()));
375373

376374
appendReadConcernToCommand(operationContext.getSessionContext(), maxWireVersion, commandDocument);

driver-core/src/main/com/mongodb/internal/operation/ListCollectionsOperation.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
import static com.mongodb.internal.operation.OperationHelper.LOGGER;
5454
import static com.mongodb.internal.operation.OperationHelper.addMaxTimeMSToNonTailableCursor;
5555
import static com.mongodb.internal.operation.OperationHelper.canRetryRead;
56-
import static com.mongodb.internal.operation.OperationHelper.validateTimeoutMode;
5756
import static com.mongodb.internal.operation.SingleBatchCursor.createEmptySingleBatchCursor;
5857
import static com.mongodb.internal.operation.SyncOperationHelper.CommandReadTransformer;
5958
import static com.mongodb.internal.operation.SyncOperationHelper.createReadCommandAndExecute;
@@ -79,7 +78,7 @@ public class ListCollectionsOperation<T> implements AsyncReadOperation<AsyncBatc
7978
private boolean nameOnly;
8079
private boolean authorizedCollections;
8180
private BsonValue comment;
82-
private TimeoutMode timeoutMode;
81+
private TimeoutMode timeoutMode = TimeoutMode.CURSOR_LIFETIME;
8382

8483
public ListCollectionsOperation(final String databaseName, final Decoder<T> decoder) {
8584
this.databaseName = notNull("databaseName", databaseName);
@@ -216,7 +215,6 @@ private CommandReadTransformerAsync<BsonDocument, AsyncBatchCursor<T>> asyncTran
216215

217216
private CommandCreator getCommandCreator() {
218217
return (operationContext, serverDescription, connectionDescription) -> {
219-
validateTimeoutMode(operationContext, timeoutMode);
220218
BsonDocument commandDocument = new BsonDocument("listCollections", new BsonInt32(1))
221219
.append("cursor", getCursorDocumentFromBatchSize(batchSize == 0 ? null : batchSize));
222220
putIfNotNull(commandDocument, "filter", filter);

driver-core/src/main/com/mongodb/internal/operation/ListIndexesOperation.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
import static com.mongodb.internal.operation.OperationHelper.LOGGER;
5252
import static com.mongodb.internal.operation.OperationHelper.addMaxTimeMSToNonTailableCursor;
5353
import static com.mongodb.internal.operation.OperationHelper.canRetryRead;
54-
import static com.mongodb.internal.operation.OperationHelper.validateTimeoutMode;
5554
import static com.mongodb.internal.operation.SingleBatchCursor.createEmptySingleBatchCursor;
5655
import static com.mongodb.internal.operation.SyncOperationHelper.CommandReadTransformer;
5756
import static com.mongodb.internal.operation.SyncOperationHelper.createReadCommandAndExecute;
@@ -71,7 +70,7 @@ public class ListIndexesOperation<T> implements AsyncReadOperation<AsyncBatchCur
7170
private boolean retryReads;
7271
private int batchSize;
7372
private BsonValue comment;
74-
private TimeoutMode timeoutMode;
73+
private TimeoutMode timeoutMode = TimeoutMode.CURSOR_LIFETIME;
7574

7675
public ListIndexesOperation(final MongoNamespace namespace, final Decoder<T> decoder) {
7776
this.namespace = notNull("namespace", namespace);
@@ -166,7 +165,6 @@ public void executeAsync(final AsyncReadBinding binding, final SingleResultCallb
166165

167166
private CommandCreator getCommandCreator() {
168167
return (operationContext, serverDescription, connectionDescription) -> {
169-
validateTimeoutMode(operationContext, timeoutMode);
170168
BsonDocument commandDocument = new BsonDocument("listIndexes", new BsonString(namespace.getCollectionName()))
171169
.append("cursor", getCursorDocumentFromBatchSize(batchSize == 0 ? null : batchSize));
172170
addMaxTimeMSToNonTailableCursor(commandDocument, timeoutMode, operationContext);

driver-core/src/main/com/mongodb/internal/operation/OperationHelper.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,6 @@
5151
final class OperationHelper {
5252
public static final Logger LOGGER = Loggers.getLogger("operation");
5353

54-
static void validateTimeoutMode(final OperationContext operationContext, @Nullable final TimeoutMode timeoutMode) {
55-
if (timeoutMode != null && !operationContext.getTimeoutContext().hasTimeoutMS()) {
56-
throw new MongoClientException("TimeoutMode requires timeoutMS to be set.");
57-
}
58-
}
59-
6054
static void validateCollationAndWriteConcern(@Nullable final Collation collation, final WriteConcern writeConcern) {
6155
if (collation != null && !writeConcern.isAcknowledged()) {
6256
throw new MongoClientException("Specifying collation with an unacknowledged WriteConcern is not supported");

driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/BatchCursorPublisher.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ public Publisher<T> batchSize(final int batchSize) {
107107
}
108108

109109
public Publisher<T> timeoutMode(final TimeoutMode timeoutMode) {
110+
if (mongoOperationPublisher.getTimeoutSettings().getTimeoutMS() == null) {
111+
throw new IllegalArgumentException("TimeoutMode requires timeoutMS to be set.");
112+
}
110113
this.timeoutMode = timeoutMode;
111114
return this;
112115
}

driver-sync/src/main/com/mongodb/client/internal/ChangeStreamIterableImpl.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import com.mongodb.client.MongoChangeStreamCursor;
2525
import com.mongodb.client.MongoCursor;
2626
import com.mongodb.client.MongoIterable;
27-
import com.mongodb.client.cursor.TimeoutMode;
2827
import com.mongodb.client.model.Collation;
2928
import com.mongodb.client.model.changestream.ChangeStreamDocument;
3029
import com.mongodb.client.model.changestream.FullDocument;
@@ -89,7 +88,6 @@ public ChangeStreamIterableImpl(@Nullable final ClientSession clientSession, fin
8988
this.codec = ChangeStreamDocument.createCodec(notNull("resultClass", resultClass), codecRegistry);
9089
this.changeStreamLevel = notNull("changeStreamLevel", changeStreamLevel);
9190
this.operations = new SyncOperations<>(namespace, resultClass, readPreference, codecRegistry, retryReads, timeoutSettings);
92-
super.timeoutMode(TimeoutMode.ITERATION);
9391
}
9492

9593
@Override

driver-sync/src/main/com/mongodb/client/internal/MongoIterableImpl.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ public TimeoutMode getTimeoutMode() {
102102
}
103103

104104
public MongoIterable<TResult> timeoutMode(final TimeoutMode timeoutMode) {
105+
if (timeoutSettings.getTimeoutMS() == null) {
106+
throw new IllegalArgumentException("TimeoutMode requires timeoutMS to be set.");
107+
}
105108
this.timeoutMode = timeoutMode;
106109
return this;
107110
}

driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java

Lines changed: 75 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -242,29 +242,30 @@ OperationResult executeListCollections(final BsonDocument operation) {
242242
ListCollectionsIterable<BsonDocument> iterable = session == null
243243
? database.listCollections(BsonDocument.class)
244244
: database.listCollections(session, BsonDocument.class);
245-
for (Map.Entry<String, BsonValue> cur : arguments.entrySet()) {
246-
switch (cur.getKey()) {
247-
case "session":
248-
break;
249-
case "filter":
250-
iterable.filter(cur.getValue().asDocument());
251-
break;
252-
case "batchSize":
253-
iterable.batchSize(cur.getValue().asNumber().intValue());
254-
break;
255-
case "timeoutMode":
256-
setTimeoutMode(iterable, cur);
257-
break;
258-
case "maxTimeMS":
259-
iterable.maxTime(cur.getValue().asNumber().longValue(), TimeUnit.MILLISECONDS);
260-
break;
261-
default:
262-
throw new UnsupportedOperationException("Unsupported argument: " + cur.getKey());
245+
return resultOf(() -> {
246+
for (Map.Entry<String, BsonValue> cur : arguments.entrySet()) {
247+
switch (cur.getKey()) {
248+
case "session":
249+
break;
250+
case "filter":
251+
iterable.filter(cur.getValue().asDocument());
252+
break;
253+
case "batchSize":
254+
iterable.batchSize(cur.getValue().asNumber().intValue());
255+
break;
256+
case "timeoutMode":
257+
setTimeoutMode(iterable, cur);
258+
break;
259+
case "maxTimeMS":
260+
iterable.maxTime(cur.getValue().asNumber().longValue(), TimeUnit.MILLISECONDS);
261+
break;
262+
default:
263+
throw new UnsupportedOperationException("Unsupported argument: " + cur.getKey());
264+
}
263265
}
264-
}
265266

266-
return resultOf(() ->
267-
new BsonArray(iterable.into(new ArrayList<>())));
267+
return new BsonArray(iterable.into(new ArrayList<>()));
268+
});
268269
}
269270

270271
OperationResult executeListCollectionNames(final BsonDocument operation) {
@@ -298,17 +299,17 @@ OperationResult executeListCollectionNames(final BsonDocument operation) {
298299
}
299300

300301
OperationResult executeListIndexes(final BsonDocument operation) {
301-
ListIndexesIterable<BsonDocument> iterable = createListIndexesIterable(operation);
302-
303-
return resultOf(() ->
304-
new BsonArray(iterable.into(new ArrayList<>())));
302+
return resultOf(() -> {
303+
ListIndexesIterable<BsonDocument> iterable = createListIndexesIterable(operation);
304+
return new BsonArray(iterable.into(new ArrayList<>()));
305+
});
305306
}
306307

307308
OperationResult executeListIndexNames(final BsonDocument operation) {
308-
ListIndexesIterable<BsonDocument> iterable = createListIndexesIterable(operation);
309-
310-
return resultOf(() ->
311-
new BsonArray(iterable.into(new ArrayList<>()).stream().map(document -> document.getString("name")).collect(toList())));
309+
return resultOf(() -> {
310+
ListIndexesIterable<BsonDocument> iterable = createListIndexesIterable(operation);
311+
return new BsonArray(iterable.into(new ArrayList<>()).stream().map(document -> document.getString("name")).collect(toList()));
312+
});
312313
}
313314

314315
private ListIndexesIterable<BsonDocument> createListIndexesIterable(final BsonDocument operation) {
@@ -339,19 +340,19 @@ private ListIndexesIterable<BsonDocument> createListIndexesIterable(final BsonDo
339340
}
340341

341342
OperationResult executeFind(final BsonDocument operation) {
342-
FindIterable<BsonDocument> iterable = createFindIterable(operation);
343-
return resultOf(() ->
344-
new BsonArray(iterable.into(new ArrayList<>())));
343+
return resultOf(() -> {
344+
FindIterable<BsonDocument> iterable = createFindIterable(operation);
345+
return new BsonArray(iterable.into(new ArrayList<>()));
346+
});
345347
}
346348

347349
OperationResult executeFindOne(final BsonDocument operation) {
348-
FindIterable<BsonDocument> iterable = createFindIterable(operation);
349-
return resultOf(iterable::first);
350+
return resultOf(() -> createFindIterable(operation).first());
350351
}
351352

352353
OperationResult createFindCursor(final BsonDocument operation) {
353-
FindIterable<BsonDocument> iterable = createFindIterable(operation);
354354
return resultOf(() -> {
355+
FindIterable<BsonDocument> iterable = createFindIterable(operation);
355356
entities.addCursor(operation.getString("saveResultAsEntity", new BsonString(createRandomEntityId())).getValue(),
356357
iterable.cursor());
357358
return null;
@@ -647,40 +648,40 @@ OperationResult executeAggregate(final BsonDocument operation) {
647648
} else {
648649
throw new UnsupportedOperationException("Unsupported entity type with name: " + entityName);
649650
}
650-
for (Map.Entry<String, BsonValue> cur : arguments.entrySet()) {
651-
switch (cur.getKey()) {
652-
case "pipeline":
653-
case "session":
654-
break;
655-
case "batchSize":
656-
iterable.batchSize(cur.getValue().asNumber().intValue());
657-
break;
658-
case "allowDiskUse":
659-
iterable.allowDiskUse(cur.getValue().asBoolean().getValue());
660-
break;
661-
case "let":
662-
iterable.let(cur.getValue().asDocument());
663-
break;
664-
case "comment":
665-
iterable.comment(cur.getValue());
666-
break;
667-
case "timeoutMode":
668-
setTimeoutMode(iterable, cur);
669-
break;
670-
case "maxTimeMS":
671-
iterable.maxTime(cur.getValue().asNumber().longValue(), TimeUnit.MILLISECONDS);
672-
break;
673-
case "maxAwaitTimeMS":
674-
iterable.maxAwaitTime(cur.getValue().asNumber().longValue(), TimeUnit.MILLISECONDS);
675-
break;
676-
default:
677-
throw new UnsupportedOperationException("Unsupported argument: " + cur.getKey());
678-
}
679-
}
680-
String lastStageName = pipeline.isEmpty() ? null : pipeline.get(pipeline.size() - 1).getFirstKey();
681-
boolean useToCollection = Objects.equals(lastStageName, "$out") || Objects.equals(lastStageName, "$merge");
682651

683652
return resultOf(() -> {
653+
for (Map.Entry<String, BsonValue> cur : arguments.entrySet()) {
654+
switch (cur.getKey()) {
655+
case "pipeline":
656+
case "session":
657+
break;
658+
case "batchSize":
659+
iterable.batchSize(cur.getValue().asNumber().intValue());
660+
break;
661+
case "allowDiskUse":
662+
iterable.allowDiskUse(cur.getValue().asBoolean().getValue());
663+
break;
664+
case "let":
665+
iterable.let(cur.getValue().asDocument());
666+
break;
667+
case "comment":
668+
iterable.comment(cur.getValue());
669+
break;
670+
case "timeoutMode":
671+
setTimeoutMode(iterable, cur);
672+
break;
673+
case "maxTimeMS":
674+
iterable.maxTime(cur.getValue().asNumber().longValue(), TimeUnit.MILLISECONDS);
675+
break;
676+
case "maxAwaitTimeMS":
677+
iterable.maxAwaitTime(cur.getValue().asNumber().longValue(), TimeUnit.MILLISECONDS);
678+
break;
679+
default:
680+
throw new UnsupportedOperationException("Unsupported argument: " + cur.getKey());
681+
}
682+
}
683+
String lastStageName = pipeline.isEmpty() ? null : pipeline.get(pipeline.size() - 1).getFirstKey();
684+
boolean useToCollection = Objects.equals(lastStageName, "$out") || Objects.equals(lastStageName, "$merge");
684685
if (!pipeline.isEmpty() && useToCollection) {
685686
iterable.toCollection();
686687
return null;
@@ -1834,8 +1835,14 @@ private static void invokeTimeoutMode(final MongoIterable<BsonDocument> iterable
18341835
timeoutModeMethod.invoke(iterable, timeoutMode);
18351836
} catch (NoSuchMethodException e) {
18361837
throw new UnsupportedOperationException("Unsupported timeoutMode method for class: " + iterable.getClass(), e);
1837-
} catch (InvocationTargetException | IllegalAccessException e) {
1838+
} catch (IllegalAccessException e) {
18381839
throw new UnsupportedOperationException("Unable to set timeoutMode method for class: " + iterable.getClass(), e);
1840+
} catch (InvocationTargetException e) {
1841+
Throwable targetException = e.getTargetException();
1842+
if (targetException instanceof IllegalArgumentException) {
1843+
throw (IllegalArgumentException) targetException;
1844+
}
1845+
throw new UnsupportedOperationException("Unable to set timeoutMode method for class: " + iterable.getClass(), targetException);
18391846
}
18401847
}
18411848
}

driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ private void assertOutcome(final UnifiedTestContext context) {
304304
private void assertOperation(final UnifiedTestContext context, final BsonDocument operation, final int operationIndex) {
305305
OperationResult result = executeOperation(context, operation, operationIndex);
306306
context.getAssertionContext().push(ContextElement.ofCompletedOperation(operation, result, operationIndex));
307+
307308
if (!operation.getBoolean("ignoreResultAndError", BsonBoolean.FALSE).getValue()) {
308309
if (operation.containsKey("expectResult")) {
309310
assertNull(context.getAssertionContext().getMessage("The operation expects a result but an exception occurred"),

0 commit comments

Comments
 (0)