From 53698ed4b680c128f9e82fca293a03cc59b5d52e Mon Sep 17 00:00:00 2001 From: Oleksandr Poliakov Date: Wed, 9 Jul 2025 17:34:42 -0700 Subject: [PATCH 1/9] CSHARP-3549: CSOT: Add timeoutMS to settings --- .../Core/Configuration/ConnectionString.cs | 12 +++++++- .../IInheritableMongoClientSettings.cs | 2 +- src/MongoDB.Driver/IMongoClientExtensions.cs | 16 +++++++++-- .../IMongoCollectionExtensions.cs | 12 ++++++++ .../IMongoDatabaseExtensions.cs | 13 +++++++++ src/MongoDB.Driver/MongoClient.cs | 15 ++++++++-- src/MongoDB.Driver/MongoClientSettings.cs | 28 ++++++++++++++++++- src/MongoDB.Driver/MongoCollectionBase.cs | 3 ++ src/MongoDB.Driver/MongoCollectionImpl.cs | 11 ++++++-- src/MongoDB.Driver/MongoCollectionSettings.cs | 27 +++++++++++++++++- src/MongoDB.Driver/MongoDatabase.cs | 14 ++++++++-- src/MongoDB.Driver/MongoDatabaseSettings.cs | 27 +++++++++++++++++- src/MongoDB.Driver/MongoUrl.cs | 8 ++++++ src/MongoDB.Driver/MongoUrlBuilder.cs | 25 +++++++++++++++-- src/MongoDB.Driver/OfTypeMongoCollection.cs | 6 ++++ .../Configuration/ConnectionStringTests.cs | 19 ++++++++++++- .../MongoUrlBuilderTests.cs | 26 +++++++++++++++++ tests/MongoDB.Driver.Tests/MongoUrlTests.cs | 3 ++ 18 files changed, 251 insertions(+), 16 deletions(-) diff --git a/src/MongoDB.Driver/Core/Configuration/ConnectionString.cs b/src/MongoDB.Driver/Core/Configuration/ConnectionString.cs index 79349c035cc..55466c205db 100644 --- a/src/MongoDB.Driver/Core/Configuration/ConnectionString.cs +++ b/src/MongoDB.Driver/Core/Configuration/ConnectionString.cs @@ -98,6 +98,7 @@ public sealed class ConnectionString private TimeSpan? _socketTimeout; private int? _srvMaxHosts; private string _srvServiceName; + private TimeSpan? _timeout; private bool? _tls; private bool? _tlsDisableCertificateRevocationCheck; private bool? _tlsInsecure; @@ -399,7 +400,6 @@ public bool? RetryReads get { return _retryReads; } } - /// /// Gets a value indicating whether or not to retry writes. /// @@ -468,6 +468,12 @@ public bool? Ssl [Obsolete("Use TlsInsecure instead.")] public bool? SslVerifyCertificate => !_tlsInsecure; + /// + /// Gets the per-operation timeout + /// + // TODO: CSOT: Make it public when CSOT will be ready for GA release + internal TimeSpan? Timeout => _timeout; + /// /// Gets whether to use TLS. /// @@ -1089,6 +1095,10 @@ private void ParseOption(string name, string value) var sslVerifyCertificateValue = ParseBoolean(name, value); _tlsInsecure = EnsureTlsInsecureIsValid(!sslVerifyCertificateValue); break; + case "timeout": + case "timeoutms": + _timeout = ParseTimeSpan(name, value); + break; case "tlsdisablecertificaterevocationcheck": var tlsDisableCertificateRevocationCheckValue = ParseBoolean(name, value); _tlsDisableCertificateRevocationCheck = diff --git a/src/MongoDB.Driver/IInheritableMongoClientSettings.cs b/src/MongoDB.Driver/IInheritableMongoClientSettings.cs index 04eb99990f3..7e011f5abd5 100644 --- a/src/MongoDB.Driver/IInheritableMongoClientSettings.cs +++ b/src/MongoDB.Driver/IInheritableMongoClientSettings.cs @@ -15,7 +15,6 @@ using System; using System.Text; -using MongoDB.Bson; namespace MongoDB.Driver { @@ -24,6 +23,7 @@ internal interface IInheritableMongoClientSettings ReadConcern ReadConcern { get; } UTF8Encoding ReadEncoding { get; } ReadPreference ReadPreference { get; } + TimeSpan Timeout { get; } WriteConcern WriteConcern { get; } UTF8Encoding WriteEncoding { get; } } diff --git a/src/MongoDB.Driver/IMongoClientExtensions.cs b/src/MongoDB.Driver/IMongoClientExtensions.cs index d2dd23c498c..9dceb8fd4b1 100644 --- a/src/MongoDB.Driver/IMongoClientExtensions.cs +++ b/src/MongoDB.Driver/IMongoClientExtensions.cs @@ -1,4 +1,4 @@ -/* Copyright 2018-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,12 +13,12 @@ * limitations under the License. */ +using System; using System.Threading; using System.Threading.Tasks; using MongoDB.Bson; using MongoDB.Driver.Core.Clusters; using MongoDB.Driver.Core.Misc; -using MongoDB.Driver.Core.Operations; namespace MongoDB.Driver { @@ -109,6 +109,18 @@ public static Task>> Watc return client.WatchAsync(session, emptyPipeline, options, cancellationToken); } + /// + /// Returns a new IMongoClient instance with a different timeout setting. + /// + /// The client. + /// The timeout. + // TODO: CSOT: Make it public when CSOT will be ready for GA release + internal static IMongoClient WithTimeout(this IMongoClient client, TimeSpan timeout) + { + Ensure.IsNotNull(client, nameof(client)); + return ((MongoClient)client).WithTimeout(timeout); + } + // internal static methods internal static IClusterInternal GetClusterInternal(this IMongoClient client) => (IClusterInternal)client.Cluster; } diff --git a/src/MongoDB.Driver/IMongoCollectionExtensions.cs b/src/MongoDB.Driver/IMongoCollectionExtensions.cs index fe5277a10d3..b5fb79f2e4f 100644 --- a/src/MongoDB.Driver/IMongoCollectionExtensions.cs +++ b/src/MongoDB.Driver/IMongoCollectionExtensions.cs @@ -2653,6 +2653,18 @@ public static Task>> WatchAs return collection.WatchAsync(session, emptyPipeline, options, cancellationToken); } + /// + /// Returns a new IMongoDatabase instance with a different timeout setting. + /// + /// The collection. + /// The timeout. + // TODO: CSOT: Make it public when CSOT will be ready for GA release + internal static IMongoCollection WithTimeout(this IMongoCollection collection, TimeSpan timeout) + { + Ensure.IsNotNull(collection, nameof(collection)); + return ((MongoCollectionBase)collection).WithTimeout(timeout); + } + // private static methods private static IQueryable AsQueryableHelper(IMongoCollection collection, IClientSessionHandle session, AggregateOptions aggregateOptions) { diff --git a/src/MongoDB.Driver/IMongoDatabaseExtensions.cs b/src/MongoDB.Driver/IMongoDatabaseExtensions.cs index 81c1bb67174..b9d9d461af2 100644 --- a/src/MongoDB.Driver/IMongoDatabaseExtensions.cs +++ b/src/MongoDB.Driver/IMongoDatabaseExtensions.cs @@ -13,6 +13,7 @@ * limitations under the License. */ +using System; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -167,6 +168,18 @@ public static Task>> Watc return database.WatchAsync(session, emptyPipeline, options, cancellationToken); } + /// + /// Returns a new IMongoDatabase instance with a different timeout setting. + /// + /// The database. + /// The timeout. + // TODO: CSOT: Make it public when CSOT will be ready for GA release + internal static IMongoDatabase WithTimeout(this IMongoDatabase database, TimeSpan timeout) + { + Ensure.IsNotNull(database, nameof(database)); + return ((MongoDatabase)database).WithTimeout(timeout); + } + // private static methods private static IQueryable AsQueryableHelper(IMongoDatabase database, IClientSessionHandle session, AggregateOptions aggregateOptions) { diff --git a/src/MongoDB.Driver/MongoClient.cs b/src/MongoDB.Driver/MongoClient.cs index 0df21ba32cc..a421b639ea8 100644 --- a/src/MongoDB.Driver/MongoClient.cs +++ b/src/MongoDB.Driver/MongoClient.cs @@ -93,8 +93,8 @@ internal MongoClient(MongoClientSettings settings, Func public IMongoClient WithWriteConcern(WriteConcern writeConcern) { diff --git a/src/MongoDB.Driver/MongoClientSettings.cs b/src/MongoDB.Driver/MongoClientSettings.cs index d7da362ca92..f9014c6546a 100644 --- a/src/MongoDB.Driver/MongoClientSettings.cs +++ b/src/MongoDB.Driver/MongoClientSettings.cs @@ -22,7 +22,6 @@ using MongoDB.Driver.Core.Configuration; using MongoDB.Driver.Core.Misc; using MongoDB.Driver.Core.Servers; -using MongoDB.Driver.Encryption; using MongoDB.Shared; namespace MongoDB.Driver @@ -74,6 +73,7 @@ public class MongoClientSettings : IEquatable, IInheritable private int _srvMaxHosts; private string _srvServiceName; private SslSettings _sslSettings; + private TimeSpan _timeout; private ExpressionTranslationOptions _translationOptions; private bool _useTls; private int _waitQueueSize; @@ -125,6 +125,7 @@ public MongoClientSettings() _srvMaxHosts = 0; _srvServiceName = MongoInternalDefaults.MongoClientSettings.SrvServiceName; _sslSettings = null; + _timeout = System.Threading.Timeout.InfiniteTimeSpan; _translationOptions = null; _useTls = false; #pragma warning disable 618 @@ -666,6 +667,23 @@ public SslSettings SslSettings } } + /// + /// Gets or sets the per-operation timeout + /// + // TODO: CSOT: Make it public when CSOT will be ready for GA release + internal TimeSpan Timeout + { + get { return _timeout; } + set + { + ThrowIfFrozen(); + _timeout = Ensure.IsInfiniteOrGreaterThanZero(value, nameof(Timeout)); + } + } + + // TODO: CSOT: Remove this explicit interface implementaion in favor of public Timeout property + TimeSpan IInheritableMongoClientSettings.Timeout => _timeout; + /// /// Gets or sets the translation options. /// @@ -881,6 +899,7 @@ public static MongoClientSettings FromUrl(MongoUrl url) { clientSettings.SslSettings = new SslSettings { CheckCertificateRevocation = false }; } + clientSettings.Timeout = url.Timeout; clientSettings.UseTls = url.UseTls; #pragma warning disable 618 clientSettings.WaitQueueSize = url.ComputedWaitQueueSize; @@ -935,6 +954,7 @@ public MongoClientSettings Clone() clone._srvMaxHosts = _srvMaxHosts; clone._srvServiceName = _srvServiceName; clone._sslSettings = (_sslSettings == null) ? null : _sslSettings.Clone(); + clone._timeout = _timeout; clone._translationOptions = _translationOptions; clone._useTls = _useTls; clone._waitQueueSize = _waitQueueSize; @@ -1004,6 +1024,7 @@ public override bool Equals(object obj) _srvMaxHosts == rhs._srvMaxHosts && _srvServiceName == rhs._srvServiceName && _sslSettings == rhs._sslSettings && + _timeout == rhs._timeout && object.Equals(_translationOptions, rhs._translationOptions) && _useTls == rhs._useTls && _waitQueueSize == rhs._waitQueueSize && @@ -1091,6 +1112,7 @@ public override int GetHashCode() .Hash(_srvMaxHosts) .Hash(_srvServiceName) .Hash(_sslSettings) + .Hash(_timeout) .Hash(_translationOptions) .Hash(_useTls) .Hash(_waitQueueSize) @@ -1172,6 +1194,10 @@ public override string ToString() { sb.AppendFormat("SslSettings={0};", _sslSettings); } + if(_timeout != System.Threading.Timeout.InfiniteTimeSpan) + { + sb.AppendFormat("Timeout={0};", _timeout); + } sb.AppendFormat("Tls={0};", _useTls); sb.AppendFormat("TlsInsecure={0};", _allowInsecureTls); if (_translationOptions != null) diff --git a/src/MongoDB.Driver/MongoCollectionBase.cs b/src/MongoDB.Driver/MongoCollectionBase.cs index 8a38110a899..cc28684ca30 100644 --- a/src/MongoDB.Driver/MongoCollectionBase.cs +++ b/src/MongoDB.Driver/MongoCollectionBase.cs @@ -882,6 +882,9 @@ public virtual IMongoCollection WithReadConcern(ReadConcern readConce public abstract IMongoCollection WithReadPreference(ReadPreference readPreference); + // TODO: Should move WithTimeout into IMongoCollection interface and made the method public + internal abstract IMongoCollection WithTimeout(TimeSpan timeout); + public abstract IMongoCollection WithWriteConcern(WriteConcern writeConcern); } } diff --git a/src/MongoDB.Driver/MongoCollectionImpl.cs b/src/MongoDB.Driver/MongoCollectionImpl.cs index 8ad05198a18..4963848297e 100644 --- a/src/MongoDB.Driver/MongoCollectionImpl.cs +++ b/src/MongoDB.Driver/MongoCollectionImpl.cs @@ -59,8 +59,8 @@ private MongoCollectionImpl(IMongoDatabase database, CollectionNamespace collect _messageEncoderSettings = GetMessageEncoderSettings(); // TODO: CSOT populate the timeout from settings - _readOperationOptions = new(Timeout: Timeout.InfiniteTimeSpan, DefaultReadPreference: _settings.ReadPreference); - _writeOperationOptions = new(Timeout: Timeout.InfiniteTimeSpan); + _readOperationOptions = new(Timeout: _settings.Timeout, DefaultReadPreference: _settings.ReadPreference); + _writeOperationOptions = new(Timeout: _settings.Timeout); } // properties @@ -659,6 +659,13 @@ public override IMongoCollection WithReadConcern(ReadConcern readConc return new MongoCollectionImpl(_database, _collectionNamespace, newSettings, _cluster, _operationExecutor); } + internal override IMongoCollection WithTimeout(TimeSpan timeout) + { + var newSettings = _settings.Clone(); + newSettings.Timeout = timeout; + return new MongoCollectionImpl(_database, _collectionNamespace, newSettings, _cluster, _operationExecutor); + } + public override IMongoCollection WithReadPreference(ReadPreference readPreference) { var newSettings = _settings.Clone(); diff --git a/src/MongoDB.Driver/MongoCollectionSettings.cs b/src/MongoDB.Driver/MongoCollectionSettings.cs index a8489008921..54101eca5c2 100644 --- a/src/MongoDB.Driver/MongoCollectionSettings.cs +++ b/src/MongoDB.Driver/MongoCollectionSettings.cs @@ -16,7 +16,6 @@ using System; using System.Collections.Generic; using System.Text; -using MongoDB.Bson; using MongoDB.Bson.Serialization; using MongoDB.Driver.Core.Misc; @@ -32,6 +31,7 @@ public class MongoCollectionSettings private Setting _readConcern; private Setting _readEncoding; private Setting _readPreference; + private Setting _timeout; private Setting _writeConcern; private Setting _writeEncoding; @@ -121,6 +121,20 @@ public IBsonSerializerRegistry SerializerRegistry get { return BsonSerializer.SerializerRegistry; } } + /// + /// Gets or sets the per-operation timeout + /// + // TODO: CSOT: Make it public when CSOT will be ready for GA release + internal TimeSpan Timeout + { + get { return _timeout.Value; } + set + { + if (_isFrozen) { throw new InvalidOperationException("MongoCollectionSettings is frozen."); } + _timeout.Value = Ensure.IsInfiniteOrGreaterThanZero(value, nameof(Timeout)); + } + } + /// /// Gets or sets the WriteConcern to use. /// @@ -163,6 +177,7 @@ public virtual MongoCollectionSettings Clone() clone._readConcern = _readConcern.Clone(); clone._readEncoding = _readEncoding.Clone(); clone._readPreference = _readPreference.Clone(); + clone._timeout = _timeout.Clone(); clone._writeConcern = _writeConcern.Clone(); clone._writeEncoding = _writeEncoding.Clone(); return clone; @@ -193,6 +208,7 @@ public override bool Equals(object obj) object.Equals(_readConcern.Value, rhs._readConcern.Value) && object.Equals(_readEncoding, rhs._readEncoding) && _readPreference.Value == rhs._readPreference.Value && + _timeout.Value == rhs._timeout.Value && _writeConcern.Value == rhs._writeConcern.Value && object.Equals(_writeEncoding, rhs._writeEncoding); } @@ -247,6 +263,7 @@ public override int GetHashCode() hash = 37 * hash + ((_readConcern.Value == null) ? 0 : _readConcern.Value.GetHashCode()); hash = 37 * hash + ((_readEncoding.Value == null) ? 0 : _readEncoding.Value.GetHashCode()); hash = 37 * hash + ((_readPreference.Value == null) ? 0 : _readPreference.Value.GetHashCode()); + hash = 37 * hash + _timeout.Value.GetHashCode(); hash = 37 * hash + ((_writeConcern.Value == null) ? 0 : _writeConcern.Value.GetHashCode()); hash = 37 * hash + ((_writeEncoding.Value == null) ? 0 : _writeEncoding.Value.GetHashCode()); return hash; @@ -271,6 +288,10 @@ public override string ToString() parts.Add(string.Format("ReadEncoding={0}", (_readEncoding.Value == null) ? "null" : "UTF8Encoding")); } parts.Add(string.Format("ReadPreference={0}", _readPreference)); + if (_timeout.HasBeenSet) + { + parts.Add(string.Format("Timeout={0}", _timeout)); + } parts.Add(string.Format("WriteConcern={0}", _writeConcern)); if (_writeEncoding.HasBeenSet) { @@ -298,6 +319,10 @@ internal void ApplyDefaultValues(MongoDatabaseSettings databaseSettings) { ReadPreference = databaseSettings.ReadPreference; } + if (!_timeout.HasBeenSet) + { + Timeout = databaseSettings.Timeout; + } if (!_writeConcern.HasBeenSet) { WriteConcern = databaseSettings.WriteConcern; diff --git a/src/MongoDB.Driver/MongoDatabase.cs b/src/MongoDB.Driver/MongoDatabase.cs index ba942b62d70..a46420e6a95 100644 --- a/src/MongoDB.Driver/MongoDatabase.cs +++ b/src/MongoDB.Driver/MongoDatabase.cs @@ -51,8 +51,8 @@ public MongoDatabase(IMongoClient client, DatabaseNamespace databaseNamespace, M _cluster = Ensure.IsNotNull(cluster, nameof(cluster)); _operationExecutor = Ensure.IsNotNull(operationExecutor, nameof(operationExecutor)); // TODO: CSOT populate the timeout from settings - _readOperationOptions = new(Timeout: Timeout.InfiniteTimeSpan, DefaultReadPreference: _settings.ReadPreference); - _writeOperationOptions = new(Timeout: Timeout.InfiniteTimeSpan); + _readOperationOptions = new(Timeout: _settings.Timeout, DefaultReadPreference: _settings.ReadPreference); + _writeOperationOptions = new(Timeout: _settings.Timeout); } // public properties @@ -508,6 +508,16 @@ public IMongoDatabase WithReadPreference(ReadPreference readPreference) return new MongoDatabase(_client, _databaseNamespace, newSettings, _cluster, _operationExecutor); } + // TODO: Should move WithTimeout into IMongoDatabase interface and made the method public + internal IMongoDatabase WithTimeout(TimeSpan timeout) + { + Ensure.IsGreaterThanZero(timeout, nameof(timeout)); + + var newSettings = Settings.Clone(); + newSettings.Timeout = timeout; + return new MongoDatabase(_client, _databaseNamespace, newSettings, _cluster, _operationExecutor); + } + public IMongoDatabase WithWriteConcern(WriteConcern writeConcern) { Ensure.IsNotNull(writeConcern, nameof(writeConcern)); diff --git a/src/MongoDB.Driver/MongoDatabaseSettings.cs b/src/MongoDB.Driver/MongoDatabaseSettings.cs index b82ea52828d..55f18d25077 100644 --- a/src/MongoDB.Driver/MongoDatabaseSettings.cs +++ b/src/MongoDB.Driver/MongoDatabaseSettings.cs @@ -16,7 +16,6 @@ using System; using System.Collections.Generic; using System.Text; -using MongoDB.Bson; using MongoDB.Bson.Serialization; using MongoDB.Driver.Core.Misc; @@ -31,6 +30,7 @@ public class MongoDatabaseSettings private Setting _readConcern; private Setting _readEncoding; private Setting _readPreference; + private Setting _timeout; private Setting _writeConcern; private Setting _writeEncoding; @@ -106,6 +106,20 @@ public IBsonSerializerRegistry SerializerRegistry get { return BsonSerializer.SerializerRegistry; } } + /// + /// Gets or sets the per-operation timeout + /// + // TODO: CSOT: Make it public when CSOT will be ready for GA release + internal TimeSpan Timeout + { + get { return _timeout.Value; } + set + { + if (_isFrozen) { throw new InvalidOperationException("MongoCollectionSettings is frozen."); } + _timeout.Value = Ensure.IsInfiniteOrGreaterThanZero(value, nameof(Timeout)); + } + } + /// /// Gets or sets the WriteConcern to use. /// @@ -147,6 +161,7 @@ public MongoDatabaseSettings Clone() clone._readConcern = _readConcern.Clone(); clone._readEncoding = _readEncoding.Clone(); clone._readPreference = _readPreference.Clone(); + clone._timeout = _timeout.Clone(); clone._writeConcern = _writeConcern.Clone(); clone._writeEncoding = _writeEncoding.Clone(); return clone; @@ -176,6 +191,7 @@ public override bool Equals(object obj) _readConcern.Value == rhs._readConcern.Value && object.Equals(_readEncoding, rhs._readEncoding) && object.Equals(_readPreference.Value, rhs._readPreference.Value) && + _timeout.Value == rhs._timeout.Value && _writeConcern.Value == rhs._writeConcern.Value && object.Equals(_writeEncoding, rhs._writeEncoding); } @@ -229,6 +245,7 @@ public override int GetHashCode() hash = 37 * hash + ((_readConcern.Value == null) ? 0 : _readConcern.GetHashCode()); hash = 37 * hash + ((_readEncoding.Value == null) ? 0 : _readEncoding.GetHashCode()); hash = 37 * hash + ((_readPreference.Value == null) ? 0 : _readPreference.Value.GetHashCode()); + hash = 37 * hash + _timeout.Value.GetHashCode(); hash = 37 * hash + ((_writeConcern.Value == null) ? 0 : _writeConcern.Value.GetHashCode()); hash = 37 * hash + ((_writeEncoding.Value == null) ? 0 : _writeEncoding.GetHashCode()); return hash; @@ -252,6 +269,10 @@ public override string ToString() parts.Add(string.Format("ReadEncoding={0}", (_readEncoding.Value == null) ? "null" : "UTF8Encoding")); } parts.Add(string.Format("ReadPreference={0}", _readPreference.Value)); + if (_timeout.HasBeenSet) + { + parts.Add(string.Format("Timeout={0}", _timeout.Value)); + } parts.Add(string.Format("WriteConcern={0}", _writeConcern.Value)); if (_writeEncoding.HasBeenSet) { @@ -275,6 +296,10 @@ internal void ApplyDefaultValues(IInheritableMongoClientSettings clientSettings) { ReadPreference = clientSettings.ReadPreference; } + if (!_timeout.HasBeenSet) + { + Timeout = clientSettings.Timeout; + } if (!_writeConcern.HasBeenSet) { WriteConcern = clientSettings.WriteConcern; diff --git a/src/MongoDB.Driver/MongoUrl.cs b/src/MongoDB.Driver/MongoUrl.cs index 2c1446fd57c..eb7306aca41 100644 --- a/src/MongoDB.Driver/MongoUrl.cs +++ b/src/MongoDB.Driver/MongoUrl.cs @@ -71,6 +71,7 @@ public class MongoUrl : IEquatable private readonly TimeSpan _socketTimeout; private readonly int? _srvMaxHosts; private readonly string _srvServiceName; + private readonly TimeSpan _timeout; private readonly bool _tlsDisableCertificateRevocationCheck; private readonly string _username; private readonly bool _useTls; @@ -129,6 +130,7 @@ internal MongoUrl(MongoUrlBuilder builder) _socketTimeout = builder.SocketTimeout; _srvMaxHosts = builder.SrvMaxHosts; _srvServiceName = builder.SrvServiceName; + _timeout = builder.Timeout; _tlsDisableCertificateRevocationCheck = builder.TlsDisableCertificateRevocationCheck; _username = builder.Username; _useTls = builder.UseTls; @@ -462,6 +464,12 @@ public string SrvServiceName get { return _srvServiceName; } } + /// + /// Gets the per-operation timeout + /// + // TODO: CSOT: Make it public when CSOT will be ready for GA release + internal TimeSpan Timeout => _timeout; + /// /// Gets whether or not to disable checking certificate revocation status during the TLS handshake. /// diff --git a/src/MongoDB.Driver/MongoUrlBuilder.cs b/src/MongoDB.Driver/MongoUrlBuilder.cs index 3858228cbf6..22f34a2e482 100644 --- a/src/MongoDB.Driver/MongoUrlBuilder.cs +++ b/src/MongoDB.Driver/MongoUrlBuilder.cs @@ -17,7 +17,6 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading; using MongoDB.Bson.IO; using MongoDB.Driver.Core.Compression; using MongoDB.Driver.Core.Configuration; @@ -67,6 +66,7 @@ public class MongoUrlBuilder private TimeSpan _socketTimeout; private int? _srvMaxHosts; private string _srvServiceName; + private TimeSpan _timeout; private bool? _tlsDisableCertificateRevocationCheck; private string _username; private bool _useTls; @@ -116,6 +116,7 @@ public MongoUrlBuilder() _socketTimeout = MongoDefaults.SocketTimeout; _srvMaxHosts = null; _srvServiceName = MongoInternalDefaults.MongoClientSettings.SrvServiceName; + _timeout = System.Threading.Timeout.InfiniteTimeSpan; _username = null; _useTls = false; _w = null; @@ -296,7 +297,7 @@ public TimeSpan HeartbeatTimeout get { return _heartbeatTimeout; } set { - if (value < TimeSpan.Zero && value != Timeout.InfiniteTimeSpan) + if (value < TimeSpan.Zero && value != System.Threading.Timeout.InfiniteTimeSpan) { throw new ArgumentOutOfRangeException("value", "HeartbeatTimeout must be greater than or equal to zero."); } @@ -592,6 +593,19 @@ public string SrvServiceName } } + /// + /// Gets or sets the per-operation timeout + /// + // TODO: CSOT: Make it public when CSOT will be ready for GA release + internal TimeSpan Timeout + { + get { return _timeout; } + set + { + _timeout = Ensure.IsInfiniteOrGreaterThanZero(value, nameof(Timeout)); + } + } + /// /// Gets or sets whether to disable certificate revocation checking during the TLS handshake. /// @@ -956,6 +970,12 @@ public override string ToString() { query.AppendFormat("socketTimeout={0}&", FormatTimeSpan(_socketTimeout)); } + + if (_timeout != System.Threading.Timeout.InfiniteTimeSpan) + { + query.AppendFormat("timeout={0}&", FormatTimeSpan(_timeout)); + } + #pragma warning disable 618 if (_waitQueueMultiple != 0.0 && _waitQueueMultiple != MongoDefaults.WaitQueueMultiple) #pragma warning restore 618 @@ -1045,6 +1065,7 @@ private void InitializeFromConnectionString(ConnectionString connectionString) _socketTimeout = connectionString.SocketTimeout.GetValueOrDefault(MongoDefaults.SocketTimeout); _srvMaxHosts = connectionString.SrvMaxHosts; _srvServiceName = connectionString.SrvServiceName ?? MongoInternalDefaults.MongoClientSettings.SrvServiceName; + _timeout = connectionString.Timeout.GetValueOrDefault(System.Threading.Timeout.InfiniteTimeSpan); _tlsDisableCertificateRevocationCheck = connectionString.TlsDisableCertificateRevocationCheck; _username = connectionString.Username; _useTls = connectionString.Tls.GetValueOrDefault(false); diff --git a/src/MongoDB.Driver/OfTypeMongoCollection.cs b/src/MongoDB.Driver/OfTypeMongoCollection.cs index a1b1dd69220..7c68399a1d1 100644 --- a/src/MongoDB.Driver/OfTypeMongoCollection.cs +++ b/src/MongoDB.Driver/OfTypeMongoCollection.cs @@ -13,6 +13,7 @@ * limitations under the License. */ +using System; using MongoDB.Bson; using MongoDB.Bson.Serialization; @@ -50,6 +51,11 @@ public override IMongoCollection WithReadPreference(ReadPrefer return new OfTypeMongoCollection(_rootDocumentCollection, WrappedCollection.WithReadPreference(readPreference), Filter); } + internal override IMongoCollection WithTimeout(TimeSpan timeout) + { + return new OfTypeMongoCollection(_rootDocumentCollection, WrappedCollection.WithTimeout(timeout), Filter); + } + public override IMongoCollection WithWriteConcern(WriteConcern writeConcern) { return new OfTypeMongoCollection(_rootDocumentCollection, WrappedCollection.WithWriteConcern(writeConcern), Filter); diff --git a/tests/MongoDB.Driver.Tests/Core/Configuration/ConnectionStringTests.cs b/tests/MongoDB.Driver.Tests/Core/Configuration/ConnectionStringTests.cs index ded3872bc19..16d7fbacc76 100644 --- a/tests/MongoDB.Driver.Tests/Core/Configuration/ConnectionStringTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Configuration/ConnectionStringTests.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -385,6 +385,7 @@ public void When_nothing_is_specified(string connectionString) subject.Ssl.Should().Be(null); subject.SslVerifyCertificate.Should().Be(null); #pragma warning restore 618 + subject.Timeout.Should().Be(null); subject.Tls.Should().Be(null); subject.TlsInsecure.Should().Be(null); subject.Username.Should().BeNull(); @@ -432,6 +433,7 @@ public void When_everything_is_specified() "socketTimeout=40ms;" + "ssl=false;" + "sslVerifyCertificate=true;" + + "timeout=42ms;" + "waitQueueMultiple=10;" + "waitQueueSize=30;" + "waitQueueTimeout=60ms;" + @@ -476,6 +478,7 @@ public void When_everything_is_specified() subject.Ssl.Should().BeFalse(); subject.SslVerifyCertificate.Should().Be(true); #pragma warning restore 618 + subject.Timeout.Should().Be(TimeSpan.FromMilliseconds(42)); subject.Tls.Should().BeFalse(); subject.TlsInsecure.Should().Be(false); subject.Username.Should().Be("user"); @@ -1048,6 +1051,20 @@ public void When_sslVerifyCertificate_is_specified(string connectionString, bool #pragma warning restore 618 } + [Theory] + [InlineData("mongodb://localhost?timeout=15ms", 15)] + [InlineData("mongodb://localhost?timeoutMS=15", 15)] + [InlineData("mongodb://localhost?timeout=15", 1000 * 15)] + [InlineData("mongodb://localhost?timeout=15s", 1000 * 15)] + [InlineData("mongodb://localhost?timeout=15m", 1000 * 60 * 15)] + [InlineData("mongodb://localhost?timeout=15h", 1000 * 60 * 60 * 15)] + public void When_timeout_is_specified(string connectionString, int milliseconds) + { + var subject = new ConnectionString(connectionString); + + subject.Timeout.Should().Be(TimeSpan.FromMilliseconds(milliseconds)); + } + [Theory] [InlineData("mongodb://localhost?tls=true", true)] [InlineData("mongodb://localhost?tls=false", false)] diff --git a/tests/MongoDB.Driver.Tests/MongoUrlBuilderTests.cs b/tests/MongoDB.Driver.Tests/MongoUrlBuilderTests.cs index 0ed8719d185..72c42a285f2 100644 --- a/tests/MongoDB.Driver.Tests/MongoUrlBuilderTests.cs +++ b/tests/MongoDB.Driver.Tests/MongoUrlBuilderTests.cs @@ -16,6 +16,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using FluentAssertions; using MongoDB.Bson.IO; using MongoDB.Driver.Core.Compression; @@ -94,6 +95,7 @@ public void TestAll() ServerMonitoringMode = ServerMonitoringMode.Poll, ServerSelectionTimeout = TimeSpan.FromSeconds(10), SocketTimeout = TimeSpan.FromSeconds(7), + Timeout = TimeSpan.FromSeconds(13), Username = "username", #pragma warning disable 618 UseSsl = true, @@ -140,6 +142,7 @@ public void TestAll() "serverMonitoringMode=Poll", "serverSelectionTimeout=10s", "socketTimeout=7s", + "timeout=13s", "waitQueueSize=123", "waitQueueTimeout=8s", "retryReads=false", @@ -185,6 +188,7 @@ public void TestAll() Assert.Equal(ServerMonitoringMode.Poll, builder.ServerMonitoringMode); Assert.Equal(TimeSpan.FromSeconds(10), builder.ServerSelectionTimeout); Assert.Equal(TimeSpan.FromSeconds(7), builder.SocketTimeout); + Assert.Equal(TimeSpan.FromSeconds(13), builder.Timeout); Assert.Equal("username", builder.Username); #pragma warning disable 618 Assert.Equal(true, builder.UseSsl); @@ -443,6 +447,7 @@ public void TestDefaults() Assert.Equal(MongoDefaults.LocalThreshold, builder.LocalThreshold); Assert.Equal(MongoDefaults.ServerSelectionTimeout, builder.ServerSelectionTimeout); Assert.Equal(MongoDefaults.SocketTimeout, builder.SocketTimeout); + Assert.Equal(Timeout.InfiniteTimeSpan, builder.Timeout); Assert.Equal(MongoInternalDefaults.MongoClientSettings.SrvServiceName, builder.SrvServiceName); Assert.Equal(null, builder.Username); #pragma warning disable 618 @@ -1136,6 +1141,27 @@ public void TestSocketTimeout_Range() builder.SocketTimeout = TimeSpan.FromSeconds(1); } + [Theory] + [InlineData(null, "mongodb://localhost", new[] { "" })] + [InlineData(500, "mongodb://localhost/?timeout{0}", new[] { "=500ms", "=0.5", "=0.5s", "=00:00:00.5", "MS=500" })] + [InlineData(30000, "mongodb://localhost/?timeout{0}", new[] { "=30s", "=30000ms", "=30", "=0.5m", "=00:00:30", "MS=30000" })] + [InlineData(1800000, "mongodb://localhost/?timeout{0}", new[] { "=30m", "=1800000ms", "=1800", "=1800s", "=0.5h", "=00:30:00", "MS=1800000" })] + [InlineData(3600000, "mongodb://localhost/?timeout{0}", new[] { "=1h", "=3600000ms", "=3600", "=3600s", "=60m", "=01:00:00", "MS=3600000" })] + [InlineData(3723000, "mongodb://localhost/?timeout{0}", new[] { "=01:02:03", "=3723000ms", "=3723", "=3723s", "MS=3723000" })] + public void TestTimeout(int? ms, string formatString, string[] values) + { + var timeout = (ms == null) ? (TimeSpan?)null : TimeSpan.FromMilliseconds(ms.Value); + var built = new MongoUrlBuilder { Server = _localhost }; + if (timeout != null) { built.Timeout = timeout.Value; } + + var canonicalConnectionString = string.Format(formatString, values[0]); + foreach (var builder in EnumerateBuiltAndParsedBuilders(built, formatString, values)) + { + Assert.Equal(timeout ?? Timeout.InfiniteTimeSpan, builder.Timeout); + Assert.Equal(canonicalConnectionString, builder.ToString()); + } + } + [Fact] public void TestSrvServiceName() { diff --git a/tests/MongoDB.Driver.Tests/MongoUrlTests.cs b/tests/MongoDB.Driver.Tests/MongoUrlTests.cs index d06704219fe..e63873964ce 100644 --- a/tests/MongoDB.Driver.Tests/MongoUrlTests.cs +++ b/tests/MongoDB.Driver.Tests/MongoUrlTests.cs @@ -186,6 +186,7 @@ public void TestAll() ServerMonitoringMode = ServerMonitoringMode.Poll, ServerSelectionTimeout = TimeSpan.FromSeconds(10), SocketTimeout = TimeSpan.FromSeconds(7), + Timeout = TimeSpan.FromSeconds(13), Username = "username", UseTls = true, W = 2, @@ -225,6 +226,7 @@ public void TestAll() "serverMonitoringMode=Poll", "serverSelectionTimeout=10s", "socketTimeout=7s", + "timeout=13s", "waitQueueSize=123", "waitQueueTimeout=8s", "retryReads=false", @@ -268,6 +270,7 @@ public void TestAll() Assert.Equal(ServerMonitoringMode.Poll, url.ServerMonitoringMode); Assert.Equal(TimeSpan.FromSeconds(10), url.ServerSelectionTimeout); Assert.Equal(TimeSpan.FromSeconds(7), url.SocketTimeout); + Assert.Equal(TimeSpan.FromSeconds(13), url.Timeout); Assert.Equal(true, url.TlsDisableCertificateRevocationCheck); Assert.Equal("username", url.Username); #pragma warning disable 618 From 2820bb6cf2af7cbcb11eb6fad7ac15a5b6afb563 Mon Sep 17 00:00:00 2001 From: Oleksandr Poliakov Date: Thu, 17 Jul 2025 11:50:30 -0700 Subject: [PATCH 2/9] tmp --- src/MongoDB.Driver/AggregateOptions.cs | 13 +- src/MongoDB.Driver/BulkWriteOptions.cs | 12 ++ src/MongoDB.Driver/ChangeStreamOptions.cs | 12 +- src/MongoDB.Driver/ClientBulkWriteOptions.cs | 13 ++ ...ionsBase.cs => ClientSessionExtensions.cs} | 19 +- .../Core/Configuration/ConnectionString.cs | 3 +- src/MongoDB.Driver/Core/Misc/Ensure.cs | 17 +- src/MongoDB.Driver/CountOptions.cs | 11 ++ src/MongoDB.Driver/CreateCollectionOptions.cs | 11 ++ .../CreateManyIndexesOptions.cs | 13 +- src/MongoDB.Driver/CreateOneIndexOptions.cs | 13 +- src/MongoDB.Driver/CreateViewOptions.cs | 14 +- src/MongoDB.Driver/DistinctOptions.cs | 11 ++ src/MongoDB.Driver/DropCollectionOptions.cs | 12 ++ src/MongoDB.Driver/DropIndexOptions.cs | 13 +- .../EstimatedDocumentCountOptions.cs | 13 +- src/MongoDB.Driver/FindFluent.cs | 10 +- src/MongoDB.Driver/FindOneAndDeleteOptions.cs | 11 ++ .../FindOneAndReplaceOptions.cs | 11 ++ src/MongoDB.Driver/FindOneAndUpdateOptions.cs | 11 ++ src/MongoDB.Driver/FindOptions.cs | 13 +- .../IInheritableMongoClientSettings.cs | 2 +- src/MongoDB.Driver/IMongoClientExtensions.cs | 13 -- .../IMongoCollectionExtensions.cs | 15 +- .../IMongoDatabaseExtensions.cs | 15 +- src/MongoDB.Driver/IOperationExecutor.cs | 10 +- src/MongoDB.Driver/InsertOneOptions.cs | 18 +- .../ListCollectionNamesOptions.cs | 14 +- src/MongoDB.Driver/ListCollectionsOptions.cs | 12 ++ .../ListDatabaseNamesOptions.cs | 14 +- src/MongoDB.Driver/ListDatabasesOptions.cs | 14 +- src/MongoDB.Driver/ListIndexesOptions.cs | 14 +- src/MongoDB.Driver/MapReduceOptions.cs | 11 ++ src/MongoDB.Driver/MongoClient.cs | 58 +++--- src/MongoDB.Driver/MongoClientSettings.cs | 10 +- src/MongoDB.Driver/MongoCollectionBase.cs | 6 +- src/MongoDB.Driver/MongoCollectionImpl.cs | 187 ++++++++++-------- src/MongoDB.Driver/MongoCollectionSettings.cs | 17 +- src/MongoDB.Driver/MongoDatabase.cs | 118 ++++++----- src/MongoDB.Driver/MongoDatabaseSettings.cs | 13 +- src/MongoDB.Driver/MongoIndexManagerBase.cs | 5 +- src/MongoDB.Driver/MongoUrl.cs | 5 +- src/MongoDB.Driver/MongoUrlBuilder.cs | 11 +- src/MongoDB.Driver/OfTypeMongoCollection.cs | 8 +- src/MongoDB.Driver/OperationContext.cs | 12 +- .../OperationContextExtensions.cs | 4 +- src/MongoDB.Driver/OperationExecutor.cs | 38 ++-- src/MongoDB.Driver/ReadOperationOptions.cs | 45 ----- src/MongoDB.Driver/RenameCollectionOptions.cs | 13 ++ src/MongoDB.Driver/WriteOperationOptions.cs | 23 --- ...sts.cs => ClientSessionExtensionsTests.cs} | 21 +- .../CreateManyIndexOptionsTest.cs | 5 +- .../CreateOneIndexOptionsTest.cs | 5 +- .../DropIndexOptionsTest.cs | 5 +- .../EstimatedDocumentCountOptionsTests.cs | 6 +- tests/MongoDB.Driver.Tests/FindFluentTests.cs | 12 +- .../IMongoCollectionExtensionsTests.cs | 4 + .../JsonDrivenAggregateTest.cs | 4 +- .../MockOperationExecutor.cs | 24 ++- .../MongoCollectionImplTests.cs | 106 +++++++++- .../MongoDatabaseTests.cs | 29 +-- .../OperationExecutorTests.cs | 42 ++-- .../crud/EstimatedDocumentCountTest.cs | 4 +- .../UnifiedAggregateOperation.cs | 4 +- .../UnifiedEstimatedDocumentCountOperation.cs | 4 +- .../UnifiedFindOperation.cs | 4 +- 66 files changed, 795 insertions(+), 465 deletions(-) rename src/MongoDB.Driver/{OperationOptionsBase.cs => ClientSessionExtensions.cs} (51%) delete mode 100644 src/MongoDB.Driver/ReadOperationOptions.cs delete mode 100644 src/MongoDB.Driver/WriteOperationOptions.cs rename tests/MongoDB.Driver.Tests/{ReadOperationOptionsTests.cs => ClientSessionExtensionsTests.cs} (65%) diff --git a/src/MongoDB.Driver/AggregateOptions.cs b/src/MongoDB.Driver/AggregateOptions.cs index cafe47e785b..91070eed189 100644 --- a/src/MongoDB.Driver/AggregateOptions.cs +++ b/src/MongoDB.Driver/AggregateOptions.cs @@ -1,4 +1,4 @@ -/* Copyright 2015-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,6 +34,7 @@ public class AggregateOptions private BsonDocument _let; private TimeSpan? _maxAwaitTime; private TimeSpan? _maxTime; + private TimeSpan? _timeout; private ExpressionTranslationOptions _translationOptions; private bool? _useCursor; @@ -121,12 +122,22 @@ public TimeSpan? MaxAwaitTime /// /// Gets or sets the maximum time. /// + [Obsolete("Use Timeout instead")] public TimeSpan? MaxTime { get { return _maxTime; } set { _maxTime = Ensure.IsNullOrInfiniteOrGreaterThanOrEqualToZero(value, nameof(value)); } } + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } + /// /// Gets or sets the translation options. /// diff --git a/src/MongoDB.Driver/BulkWriteOptions.cs b/src/MongoDB.Driver/BulkWriteOptions.cs index 12b75cbb018..d3c62f52b1b 100644 --- a/src/MongoDB.Driver/BulkWriteOptions.cs +++ b/src/MongoDB.Driver/BulkWriteOptions.cs @@ -13,7 +13,9 @@ * limitations under the License. */ +using System; using MongoDB.Bson; +using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver { @@ -27,6 +29,7 @@ public sealed class BulkWriteOptions private BsonValue _comment; private bool _isOrdered; private BsonDocument _let; + private TimeSpan? _timeout; // constructors /// @@ -73,5 +76,14 @@ public BsonDocument Let get { return _let; } set { _let = value; } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } } diff --git a/src/MongoDB.Driver/ChangeStreamOptions.cs b/src/MongoDB.Driver/ChangeStreamOptions.cs index c4da3830611..c9dc41994e0 100644 --- a/src/MongoDB.Driver/ChangeStreamOptions.cs +++ b/src/MongoDB.Driver/ChangeStreamOptions.cs @@ -1,4 +1,4 @@ -/* Copyright 2017-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,6 +35,7 @@ public class ChangeStreamOptions private bool? _showExpandedEvents; private BsonDocument _startAfter; private BsonTimestamp _startAtOperationTime; + private TimeSpan? _timeout; // public properties /// @@ -166,5 +167,14 @@ public BsonTimestamp StartAtOperationTime get { return _startAtOperationTime; } set { _startAtOperationTime = value; } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } } diff --git a/src/MongoDB.Driver/ClientBulkWriteOptions.cs b/src/MongoDB.Driver/ClientBulkWriteOptions.cs index 9ba9c366c6b..aa81ce2935b 100644 --- a/src/MongoDB.Driver/ClientBulkWriteOptions.cs +++ b/src/MongoDB.Driver/ClientBulkWriteOptions.cs @@ -13,7 +13,9 @@ * limitations under the License. */ +using System; using MongoDB.Bson; +using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver { @@ -22,6 +24,8 @@ namespace MongoDB.Driver /// public sealed class ClientBulkWriteOptions { + private TimeSpan? _timeout; + /// /// Initializes a new instance of the class. /// @@ -75,6 +79,15 @@ public ClientBulkWriteOptions( /// public BsonDocument Let { get; set; } + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } + /// /// Whether detailed results for each successful operation should be included in the returned results. /// diff --git a/src/MongoDB.Driver/OperationOptionsBase.cs b/src/MongoDB.Driver/ClientSessionExtensions.cs similarity index 51% rename from src/MongoDB.Driver/OperationOptionsBase.cs rename to src/MongoDB.Driver/ClientSessionExtensions.cs index 5f564ca1b27..163308fc715 100644 --- a/src/MongoDB.Driver/OperationOptionsBase.cs +++ b/src/MongoDB.Driver/ClientSessionExtensions.cs @@ -13,15 +13,22 @@ * limitations under the License. */ -using System; -using System.Threading; +namespace MongoDB.Driver; -namespace MongoDB.Driver +internal static class ClientSessionExtensions { - internal abstract record OperationOptionsBase(TimeSpan Timeout) + public static ReadPreference GetEffectiveReadPreference(this IClientSession session, ReadPreference defaultReadPreference) { - public OperationContext ToOperationContext(CancellationToken cancellationToken) - => new (Timeout, cancellationToken); + if (session.IsInTransaction) + { + var transactionReadPreference = session.WrappedCoreSession.CurrentTransaction.TransactionOptions.ReadPreference; + if (transactionReadPreference != null) + { + return transactionReadPreference; + } + } + + return defaultReadPreference ?? ReadPreference.Primary; } } diff --git a/src/MongoDB.Driver/Core/Configuration/ConnectionString.cs b/src/MongoDB.Driver/Core/Configuration/ConnectionString.cs index 55466c205db..40c8787d542 100644 --- a/src/MongoDB.Driver/Core/Configuration/ConnectionString.cs +++ b/src/MongoDB.Driver/Core/Configuration/ConnectionString.cs @@ -471,8 +471,7 @@ public bool? Ssl /// /// Gets the per-operation timeout /// - // TODO: CSOT: Make it public when CSOT will be ready for GA release - internal TimeSpan? Timeout => _timeout; + public TimeSpan? Timeout => _timeout; /// /// Gets whether to use TLS. diff --git a/src/MongoDB.Driver/Core/Misc/Ensure.cs b/src/MongoDB.Driver/Core/Misc/Ensure.cs index 7fbab39b9b7..058aff50a31 100644 --- a/src/MongoDB.Driver/Core/Misc/Ensure.cs +++ b/src/MongoDB.Driver/Core/Misc/Ensure.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -444,11 +444,12 @@ public static string IsNullOrNotEmpty(string value, string paramName) /// The value of the parameter. public static TimeSpan? IsNullOrValidTimeout(TimeSpan? value, string paramName) { - if (value != null) + if (value == null) { - IsValidTimeout(value.Value, paramName); + return null; } - return value; + + return IsValidTimeout(value.Value, paramName); } /// @@ -459,12 +460,12 @@ public static string IsNullOrNotEmpty(string value, string paramName) /// The value of the parameter. public static TimeSpan IsValidTimeout(TimeSpan value, string paramName) { - if (value < TimeSpan.Zero && value != Timeout.InfiniteTimeSpan) + if (value > TimeSpan.Zero || value == Timeout.InfiniteTimeSpan) { - var message = string.Format("Invalid timeout: {0}.", value); - throw new ArgumentException(message, paramName); + return value; } - return value; + + throw new ArgumentException($"Invalid timeout: {value}.", paramName); } /// diff --git a/src/MongoDB.Driver/CountOptions.cs b/src/MongoDB.Driver/CountOptions.cs index 2a85963cda7..5c50d56f1c4 100644 --- a/src/MongoDB.Driver/CountOptions.cs +++ b/src/MongoDB.Driver/CountOptions.cs @@ -31,6 +31,7 @@ public sealed class CountOptions private long? _limit; private TimeSpan? _maxTime; private long? _skip; + private TimeSpan? _timeout; // properties /// @@ -72,6 +73,7 @@ public long? Limit /// /// Gets or sets the maximum time. /// + [Obsolete("Use Timeout instead")] public TimeSpan? MaxTime { get { return _maxTime; } @@ -86,5 +88,14 @@ public long? Skip get { return _skip; } set { _skip = value; } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } } diff --git a/src/MongoDB.Driver/CreateCollectionOptions.cs b/src/MongoDB.Driver/CreateCollectionOptions.cs index e5e62381158..86e7396c848 100644 --- a/src/MongoDB.Driver/CreateCollectionOptions.cs +++ b/src/MongoDB.Driver/CreateCollectionOptions.cs @@ -16,6 +16,7 @@ using System; using MongoDB.Bson; using MongoDB.Bson.Serialization; +using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver { @@ -35,6 +36,7 @@ public class CreateCollectionOptions private long? _maxSize; private bool? _noPadding; private BsonDocument _storageEngine; + private TimeSpan? _timeout; private TimeSeriesOptions _timeSeriesOptions; private bool? _usePowerOf2Sizes; private IBsonSerializerRegistry _serializerRegistry; @@ -145,6 +147,15 @@ public BsonDocument StorageEngine set { _storageEngine = value; } } + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } + /// /// Gets or sets the to use when creating a time series collection. /// diff --git a/src/MongoDB.Driver/CreateManyIndexesOptions.cs b/src/MongoDB.Driver/CreateManyIndexesOptions.cs index 7122d65847b..21515e68a95 100644 --- a/src/MongoDB.Driver/CreateManyIndexesOptions.cs +++ b/src/MongoDB.Driver/CreateManyIndexesOptions.cs @@ -1,4 +1,4 @@ -/* Copyright 2018-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,6 +28,7 @@ public class CreateManyIndexesOptions private BsonValue _comment; private CreateIndexCommitQuorum _commitQuorum; private TimeSpan? _maxTime; + private TimeSpan? _timeout; // public properties /// @@ -54,10 +55,20 @@ public CreateIndexCommitQuorum CommitQuorum /// Gets or sets the maximum time. /// /// The maximum time. + [Obsolete("Use Timeout instead")] public TimeSpan? MaxTime { get { return _maxTime; } set { _maxTime = Ensure.IsNullOrInfiniteOrGreaterThanOrEqualToZero(value, nameof(value)); } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } } diff --git a/src/MongoDB.Driver/CreateOneIndexOptions.cs b/src/MongoDB.Driver/CreateOneIndexOptions.cs index 06ab3bf76d7..59379ab9199 100644 --- a/src/MongoDB.Driver/CreateOneIndexOptions.cs +++ b/src/MongoDB.Driver/CreateOneIndexOptions.cs @@ -1,4 +1,4 @@ -/* Copyright 2018-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ public class CreateOneIndexOptions // private fields private CreateIndexCommitQuorum _commitQuorum; private TimeSpan? _maxTime; + private TimeSpan? _timeout; // public properties /// @@ -42,10 +43,20 @@ public CreateIndexCommitQuorum CommitQuorum /// Gets or sets the maximum time. /// /// The maximum time. + [Obsolete("Use Timeout instead")] public TimeSpan? MaxTime { get { return _maxTime; } set { _maxTime = Ensure.IsNullOrInfiniteOrGreaterThanOrEqualToZero(value, nameof(value)); } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } } diff --git a/src/MongoDB.Driver/CreateViewOptions.cs b/src/MongoDB.Driver/CreateViewOptions.cs index 1226e714841..82873304f72 100644 --- a/src/MongoDB.Driver/CreateViewOptions.cs +++ b/src/MongoDB.Driver/CreateViewOptions.cs @@ -1,4 +1,4 @@ -/* Copyright 2016-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,9 @@ * limitations under the License. */ +using System; using MongoDB.Bson.Serialization; +using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver { @@ -27,6 +29,7 @@ public class CreateViewOptions private Collation _collation; private IBsonSerializer _documentSerializer; private IBsonSerializerRegistry _serializerRegistry; + private TimeSpan? _timeout; // properties /// @@ -64,5 +67,14 @@ public IBsonSerializerRegistry SerializerRegistry get { return _serializerRegistry; } set { _serializerRegistry = value; } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } } diff --git a/src/MongoDB.Driver/DistinctOptions.cs b/src/MongoDB.Driver/DistinctOptions.cs index 5aee87e814e..c1516c2d7e1 100644 --- a/src/MongoDB.Driver/DistinctOptions.cs +++ b/src/MongoDB.Driver/DistinctOptions.cs @@ -28,6 +28,7 @@ public sealed class DistinctOptions private Collation _collation; private BsonValue _comment; private TimeSpan? _maxTime; + private TimeSpan? _timeout; // properties /// @@ -51,10 +52,20 @@ public BsonValue Comment /// /// Gets or sets the maximum time. /// + [Obsolete("Use Timeout instead")] public TimeSpan? MaxTime { get { return _maxTime; } set { _maxTime = Ensure.IsNullOrInfiniteOrGreaterThanOrEqualToZero(value, nameof(value)); } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } } diff --git a/src/MongoDB.Driver/DropCollectionOptions.cs b/src/MongoDB.Driver/DropCollectionOptions.cs index 8c3e13bb483..3e72ce31f6f 100644 --- a/src/MongoDB.Driver/DropCollectionOptions.cs +++ b/src/MongoDB.Driver/DropCollectionOptions.cs @@ -13,7 +13,9 @@ * limitations under the License. */ +using System; using MongoDB.Bson; +using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver { @@ -23,6 +25,7 @@ namespace MongoDB.Driver public class DropCollectionOptions { private BsonDocument _encryptedFields; + private TimeSpan? _timeout; /// /// Gets or sets encrypted fields. @@ -32,5 +35,14 @@ public BsonDocument EncryptedFields get { return _encryptedFields; } set { _encryptedFields = value; } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } } diff --git a/src/MongoDB.Driver/DropIndexOptions.cs b/src/MongoDB.Driver/DropIndexOptions.cs index d345fc0cb48..5a3aad472c8 100644 --- a/src/MongoDB.Driver/DropIndexOptions.cs +++ b/src/MongoDB.Driver/DropIndexOptions.cs @@ -1,4 +1,4 @@ -/* Copyright 2018-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ public class DropIndexOptions { private BsonValue _comment; private TimeSpan? _maxTime; + private TimeSpan? _timeout; /// /// Gets or sets the comment. @@ -43,10 +44,20 @@ public BsonValue Comment /// Gets or sets the maximum time. /// /// The maximum time. + [Obsolete("Use Timeout instead")] public TimeSpan? MaxTime { get { return _maxTime; } set { _maxTime = Ensure.IsNullOrInfiniteOrGreaterThanOrEqualToZero(value, nameof(value)); } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } } diff --git a/src/MongoDB.Driver/EstimatedDocumentCountOptions.cs b/src/MongoDB.Driver/EstimatedDocumentCountOptions.cs index 2789601d1da..993464a1a37 100644 --- a/src/MongoDB.Driver/EstimatedDocumentCountOptions.cs +++ b/src/MongoDB.Driver/EstimatedDocumentCountOptions.cs @@ -1,4 +1,4 @@ -/* Copyright 2018-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,7 @@ public sealed class EstimatedDocumentCountOptions // private fields private BsonValue _comment; private TimeSpan? _maxTime; + private TimeSpan? _timeout; // public properties /// @@ -41,10 +42,20 @@ public BsonValue Comment /// /// Gets or sets the maximum time. /// + [Obsolete("Use Timeout instead")] public TimeSpan? MaxTime { get { return _maxTime; } set { _maxTime = Ensure.IsNullOrInfiniteOrGreaterThanOrEqualToZero(value, nameof(value)); } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } } diff --git a/src/MongoDB.Driver/FindFluent.cs b/src/MongoDB.Driver/FindFluent.cs index cc25e841b29..f8ab83f322a 100644 --- a/src/MongoDB.Driver/FindFluent.cs +++ b/src/MongoDB.Driver/FindFluent.cs @@ -133,7 +133,9 @@ public override IFindFluent Project(P Limit = _options.Limit, Max = _options.Max, MaxAwaitTime = _options.MaxAwaitTime, +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = _options.MaxTime, +#pragma warning restore CS0618 // Type or member is obsolete Min = _options.Min, NoCursorTimeout = _options.NoCursorTimeout, #pragma warning disable 618 @@ -144,6 +146,7 @@ public override IFindFluent Project(P ShowRecordId = _options.ShowRecordId, Skip = _options.Skip, Sort = _options.Sort, + Timeout = _options.Timeout, TranslationOptions = _options.TranslationOptions }; return new FindFluent(_session, _collection, _filter, newOptions); @@ -227,10 +230,12 @@ public override string ToString(ExpressionTranslationOptions translationOptions) sb.Append(".limit(" + _options.Limit.Value.ToString() + ")"); } +#pragma warning disable CS0618 // Type or member is obsolete if (_options.MaxTime != null) { sb.Append(".maxTime(" + _options.MaxTime.Value.TotalMilliseconds + ")"); } +#pragma warning restore CS0618 // Type or member is obsolete if (_options.Hint != null) { @@ -273,8 +278,11 @@ private CountOptions CreateCountOptions() Collation = _options.Collation, Hint = _options.Hint, Limit = _options.Limit, +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = _options.MaxTime, - Skip = _options.Skip +#pragma warning restore CS0618 // Type or member is obsolete + Skip = _options.Skip, + Timeout = _options.Timeout }; } diff --git a/src/MongoDB.Driver/FindOneAndDeleteOptions.cs b/src/MongoDB.Driver/FindOneAndDeleteOptions.cs index 7cb6f5317fa..a62cd05468a 100644 --- a/src/MongoDB.Driver/FindOneAndDeleteOptions.cs +++ b/src/MongoDB.Driver/FindOneAndDeleteOptions.cs @@ -34,6 +34,7 @@ public class FindOneAndDeleteOptions private TimeSpan? _maxTime; private ProjectionDefinition _projection; private SortDefinition _sort; + private TimeSpan? _timeout; // properties /// @@ -75,6 +76,7 @@ public BsonDocument Let /// /// Gets or sets the maximum time. /// + [Obsolete("Use Timeout instead")] public TimeSpan? MaxTime { get { return _maxTime; } @@ -98,6 +100,15 @@ public SortDefinition Sort get { return _sort; } set { _sort = value; } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } /// diff --git a/src/MongoDB.Driver/FindOneAndReplaceOptions.cs b/src/MongoDB.Driver/FindOneAndReplaceOptions.cs index bca48a2e621..885086c7320 100644 --- a/src/MongoDB.Driver/FindOneAndReplaceOptions.cs +++ b/src/MongoDB.Driver/FindOneAndReplaceOptions.cs @@ -37,6 +37,7 @@ public class FindOneAndReplaceOptions private ProjectionDefinition _projection; private ReturnDocument _returnDocument; private SortDefinition _sort; + private TimeSpan? _timeout; // constructors /// @@ -105,6 +106,7 @@ public bool IsUpsert /// /// Gets or sets the maximum time. /// + [Obsolete("Use Timeout instead")] public TimeSpan? MaxTime { get { return _maxTime; } @@ -137,6 +139,15 @@ public SortDefinition Sort get { return _sort; } set { _sort = value; } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } /// diff --git a/src/MongoDB.Driver/FindOneAndUpdateOptions.cs b/src/MongoDB.Driver/FindOneAndUpdateOptions.cs index 683156671da..f3e937721ba 100644 --- a/src/MongoDB.Driver/FindOneAndUpdateOptions.cs +++ b/src/MongoDB.Driver/FindOneAndUpdateOptions.cs @@ -39,6 +39,7 @@ public class FindOneAndUpdateOptions private ProjectionDefinition _projection; private ReturnDocument _returnDocument; private SortDefinition _sort; + private TimeSpan? _timeout; // constructors /// @@ -119,6 +120,7 @@ public BsonDocument Let /// /// Gets or sets the maximum time. /// + [Obsolete("Use Timeout instead")] public TimeSpan? MaxTime { get { return _maxTime; } @@ -151,6 +153,15 @@ public SortDefinition Sort get { return _sort; } set { _sort = value; } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } /// diff --git a/src/MongoDB.Driver/FindOptions.cs b/src/MongoDB.Driver/FindOptions.cs index 3ceb5cdfdaa..527f6c8f2b1 100644 --- a/src/MongoDB.Driver/FindOptions.cs +++ b/src/MongoDB.Driver/FindOptions.cs @@ -1,4 +1,4 @@ -/* Copyright 2015-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * 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 @@ public abstract class FindOptionsBase private bool? _oplogReplay; private bool? _returnKey; private bool? _showRecordId; + private TimeSpan? _timeout; private ExpressionTranslationOptions _translationOptions; // constructors @@ -146,6 +147,7 @@ public TimeSpan? MaxAwaitTime /// /// Gets or sets the maximum time. /// + [Obsolete("Use Timeout instead")] public TimeSpan? MaxTime { get { return _maxTime; } @@ -198,6 +200,15 @@ public bool? ShowRecordId set { _showRecordId = value; } } + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } + /// /// Gets or sets the translation options. /// diff --git a/src/MongoDB.Driver/IInheritableMongoClientSettings.cs b/src/MongoDB.Driver/IInheritableMongoClientSettings.cs index 7e011f5abd5..2e54fda9d4c 100644 --- a/src/MongoDB.Driver/IInheritableMongoClientSettings.cs +++ b/src/MongoDB.Driver/IInheritableMongoClientSettings.cs @@ -23,7 +23,7 @@ internal interface IInheritableMongoClientSettings ReadConcern ReadConcern { get; } UTF8Encoding ReadEncoding { get; } ReadPreference ReadPreference { get; } - TimeSpan Timeout { get; } + TimeSpan? Timeout { get; } WriteConcern WriteConcern { get; } UTF8Encoding WriteEncoding { get; } } diff --git a/src/MongoDB.Driver/IMongoClientExtensions.cs b/src/MongoDB.Driver/IMongoClientExtensions.cs index 9dceb8fd4b1..edf59ca8b4e 100644 --- a/src/MongoDB.Driver/IMongoClientExtensions.cs +++ b/src/MongoDB.Driver/IMongoClientExtensions.cs @@ -13,7 +13,6 @@ * limitations under the License. */ -using System; using System.Threading; using System.Threading.Tasks; using MongoDB.Bson; @@ -109,18 +108,6 @@ public static Task>> Watc return client.WatchAsync(session, emptyPipeline, options, cancellationToken); } - /// - /// Returns a new IMongoClient instance with a different timeout setting. - /// - /// The client. - /// The timeout. - // TODO: CSOT: Make it public when CSOT will be ready for GA release - internal static IMongoClient WithTimeout(this IMongoClient client, TimeSpan timeout) - { - Ensure.IsNotNull(client, nameof(client)); - return ((MongoClient)client).WithTimeout(timeout); - } - // internal static methods internal static IClusterInternal GetClusterInternal(this IMongoClient client) => (IClusterInternal)client.Cluster; } diff --git a/src/MongoDB.Driver/IMongoCollectionExtensions.cs b/src/MongoDB.Driver/IMongoCollectionExtensions.cs index b5fb79f2e4f..aa519ea5570 100644 --- a/src/MongoDB.Driver/IMongoCollectionExtensions.cs +++ b/src/MongoDB.Driver/IMongoCollectionExtensions.cs @@ -1192,7 +1192,9 @@ private static IFindFluent FindHelper(IClientSe Let = options.Let, Max = options.Max, MaxAwaitTime = options.MaxAwaitTime, +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = options.MaxTime, +#pragma warning restore CS0618 // Type or member is obsolete Min = options.Min, NoCursorTimeout = options.NoCursorTimeout, #pragma warning disable 618 @@ -1200,6 +1202,7 @@ private static IFindFluent FindHelper(IClientSe #pragma warning restore 618 ReturnKey = options.ReturnKey, ShowRecordId = options.ShowRecordId, + Timeout = options.Timeout, TranslationOptions = options.TranslationOptions }; } @@ -2653,18 +2656,6 @@ public static Task>> WatchAs return collection.WatchAsync(session, emptyPipeline, options, cancellationToken); } - /// - /// Returns a new IMongoDatabase instance with a different timeout setting. - /// - /// The collection. - /// The timeout. - // TODO: CSOT: Make it public when CSOT will be ready for GA release - internal static IMongoCollection WithTimeout(this IMongoCollection collection, TimeSpan timeout) - { - Ensure.IsNotNull(collection, nameof(collection)); - return ((MongoCollectionBase)collection).WithTimeout(timeout); - } - // private static methods private static IQueryable AsQueryableHelper(IMongoCollection collection, IClientSessionHandle session, AggregateOptions aggregateOptions) { diff --git a/src/MongoDB.Driver/IMongoDatabaseExtensions.cs b/src/MongoDB.Driver/IMongoDatabaseExtensions.cs index b9d9d461af2..931736b6c9d 100644 --- a/src/MongoDB.Driver/IMongoDatabaseExtensions.cs +++ b/src/MongoDB.Driver/IMongoDatabaseExtensions.cs @@ -1,4 +1,4 @@ -/* Copyright 2018-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * limitations under the License. */ -using System; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -168,18 +167,6 @@ public static Task>> Watc return database.WatchAsync(session, emptyPipeline, options, cancellationToken); } - /// - /// Returns a new IMongoDatabase instance with a different timeout setting. - /// - /// The database. - /// The timeout. - // TODO: CSOT: Make it public when CSOT will be ready for GA release - internal static IMongoDatabase WithTimeout(this IMongoDatabase database, TimeSpan timeout) - { - Ensure.IsNotNull(database, nameof(database)); - return ((MongoDatabase)database).WithTimeout(timeout); - } - // private static methods private static IQueryable AsQueryableHelper(IMongoDatabase database, IClientSessionHandle session, AggregateOptions aggregateOptions) { diff --git a/src/MongoDB.Driver/IOperationExecutor.cs b/src/MongoDB.Driver/IOperationExecutor.cs index b935561469f..b64c2380776 100644 --- a/src/MongoDB.Driver/IOperationExecutor.cs +++ b/src/MongoDB.Driver/IOperationExecutor.cs @@ -25,29 +25,31 @@ internal interface IOperationExecutor : IDisposable TResult ExecuteReadOperation( IClientSessionHandle session, IReadOperation operation, - ReadOperationOptions options, + ReadPreference readPreference, bool allowChannelPinning, + TimeSpan? timeout, CancellationToken cancellationToken); Task ExecuteReadOperationAsync( IClientSessionHandle session, IReadOperation operation, - ReadOperationOptions options, + ReadPreference readPreference, bool allowChannelPinning, + TimeSpan? timeout, CancellationToken cancellationToken); TResult ExecuteWriteOperation( IClientSessionHandle session, IWriteOperation operation, - WriteOperationOptions options, bool allowChannelPinning, + TimeSpan? timeout, CancellationToken cancellationToken); Task ExecuteWriteOperationAsync( IClientSessionHandle session, IWriteOperation operation, - WriteOperationOptions options, bool allowChannelPinning, + TimeSpan? timeout, CancellationToken cancellationToken); IClientSessionHandle StartImplicitSession(); diff --git a/src/MongoDB.Driver/InsertOneOptions.cs b/src/MongoDB.Driver/InsertOneOptions.cs index 3f2ddf773ba..ffebe926df7 100644 --- a/src/MongoDB.Driver/InsertOneOptions.cs +++ b/src/MongoDB.Driver/InsertOneOptions.cs @@ -11,9 +11,12 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * + * */ + +using System; using MongoDB.Bson; +using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver { @@ -22,10 +25,10 @@ namespace MongoDB.Driver /// public sealed class InsertOneOptions { - private BsonValue _comment; - // private fields private bool? _bypassDocumentValidation; + private BsonValue _comment; + private TimeSpan? _timeout; // public properties /// @@ -45,5 +48,14 @@ public BsonValue Comment get { return _comment; } set { _comment = value; } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } } diff --git a/src/MongoDB.Driver/ListCollectionNamesOptions.cs b/src/MongoDB.Driver/ListCollectionNamesOptions.cs index ae1b89308c7..61385a179b4 100644 --- a/src/MongoDB.Driver/ListCollectionNamesOptions.cs +++ b/src/MongoDB.Driver/ListCollectionNamesOptions.cs @@ -1,4 +1,4 @@ -/* Copyright 2018-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,9 @@ * limitations under the License. */ +using System; using MongoDB.Bson; +using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver { @@ -26,6 +28,7 @@ public sealed class ListCollectionNamesOptions private bool? authorizedCollections; private BsonValue _comment; private FilterDefinition _filter; + private TimeSpan? _timeout; // properties /// @@ -54,5 +57,14 @@ public FilterDefinition Filter get { return _filter; } set { _filter = value; } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } } diff --git a/src/MongoDB.Driver/ListCollectionsOptions.cs b/src/MongoDB.Driver/ListCollectionsOptions.cs index 218fcd03655..3bff8742ea9 100644 --- a/src/MongoDB.Driver/ListCollectionsOptions.cs +++ b/src/MongoDB.Driver/ListCollectionsOptions.cs @@ -13,7 +13,9 @@ * limitations under the License. */ +using System; using MongoDB.Bson; +using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver { @@ -26,6 +28,7 @@ public sealed class ListCollectionsOptions private int? _batchSize; private BsonValue _comment; private FilterDefinition _filter; + private TimeSpan? _timeout; // properties /// @@ -54,5 +57,14 @@ public FilterDefinition Filter get { return _filter; } set { _filter = value; } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } } diff --git a/src/MongoDB.Driver/ListDatabaseNamesOptions.cs b/src/MongoDB.Driver/ListDatabaseNamesOptions.cs index 6e3d696dcf0..44e5bedb57f 100644 --- a/src/MongoDB.Driver/ListDatabaseNamesOptions.cs +++ b/src/MongoDB.Driver/ListDatabaseNamesOptions.cs @@ -1,4 +1,4 @@ -/* Copyright 2020-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,9 @@ * limitations under the License. */ +using System; using MongoDB.Bson; +using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver { @@ -26,6 +28,7 @@ public sealed class ListDatabaseNamesOptions private bool? _authorizedDatabases; private BsonValue _comment; private FilterDefinition _filter; + private TimeSpan? _timeout; // properties /// @@ -54,5 +57,14 @@ public FilterDefinition Filter get { return _filter; } set { _filter = value; } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } } diff --git a/src/MongoDB.Driver/ListDatabasesOptions.cs b/src/MongoDB.Driver/ListDatabasesOptions.cs index 9fc9bb550ba..9194e2da82e 100644 --- a/src/MongoDB.Driver/ListDatabasesOptions.cs +++ b/src/MongoDB.Driver/ListDatabasesOptions.cs @@ -1,4 +1,4 @@ -/* Copyright 2017-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,9 @@ * limitations under the License. */ +using System; using MongoDB.Bson; +using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver { @@ -27,6 +29,7 @@ public sealed class ListDatabasesOptions private BsonValue _comment; private FilterDefinition _filter; private bool? _nameOnly; + private TimeSpan? _timeout; // properties /// @@ -64,5 +67,14 @@ public bool? NameOnly get { return _nameOnly; } set { _nameOnly = value; } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } } diff --git a/src/MongoDB.Driver/ListIndexesOptions.cs b/src/MongoDB.Driver/ListIndexesOptions.cs index 4df3bcc77bf..d5307be8bcc 100644 --- a/src/MongoDB.Driver/ListIndexesOptions.cs +++ b/src/MongoDB.Driver/ListIndexesOptions.cs @@ -1,4 +1,4 @@ -/* Copyright 2021-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,9 @@ * limitations under the License. */ +using System; using MongoDB.Bson; +using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver { @@ -24,6 +26,7 @@ public sealed class ListIndexesOptions { private int? _batchSize; private BsonValue _comment; + private TimeSpan? _timeout; /// /// Gets or sets the batch size. @@ -42,5 +45,14 @@ public BsonValue Comment get { return _comment; } set { _comment = value; } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } } diff --git a/src/MongoDB.Driver/MapReduceOptions.cs b/src/MongoDB.Driver/MapReduceOptions.cs index 53075a94f60..b10762c4477 100644 --- a/src/MongoDB.Driver/MapReduceOptions.cs +++ b/src/MongoDB.Driver/MapReduceOptions.cs @@ -40,6 +40,7 @@ public sealed class MapReduceOptions private IBsonSerializer _resultSerializer; private BsonDocument _scope; private SortDefinition _sort; + private TimeSpan? _timeout; private bool? _verbose; // properties @@ -101,6 +102,7 @@ public long? Limit /// /// Gets or sets the maximum time. /// + [Obsolete("Use Timeout instead")] public TimeSpan? MaxTime { get { return _maxTime; } @@ -143,6 +145,15 @@ public SortDefinition Sort set { _sort = value; } } + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } + /// /// Gets or sets whether to include timing information. /// diff --git a/src/MongoDB.Driver/MongoClient.cs b/src/MongoDB.Driver/MongoClient.cs index a421b639ea8..4fde2d760bd 100644 --- a/src/MongoDB.Driver/MongoClient.cs +++ b/src/MongoDB.Driver/MongoClient.cs @@ -45,8 +45,6 @@ public sealed class MongoClient : IMongoClient private readonly IOperationExecutor _operationExecutor; private readonly MongoClientSettings _settings; private readonly ILogger _logger; - private readonly ReadOperationOptions _readOperationOptions; - private readonly WriteOperationOptions _writeOperationOptions; // constructors /// @@ -92,9 +90,6 @@ internal MongoClient(MongoClientSettings settings, Func(); _cluster = _settings.ClusterSource.Get(_settings.ToClusterKey()); _operationExecutor = _operationExecutorFactory(this); - // TODO: CSOT populate the timeout from settings - _readOperationOptions = new(Timeout: _settings.Timeout, DefaultReadPreference: _settings.ReadPreference); - _writeOperationOptions = new(Timeout: _settings.Timeout); if (settings.AutoEncryptionOptions != null) { @@ -149,7 +144,7 @@ public ClientBulkWriteResult BulkWrite(IClientSessionHandle session, IReadOnlyLi Ensure.IsNotNull(session, nameof(session)); ThrowIfDisposed(); var operation = CreateClientBulkWriteOperation(models, options); - return ExecuteWriteOperation(session, operation, cancellationToken); + return ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken); } /// @@ -166,7 +161,7 @@ public Task BulkWriteAsync(IClientSessionHandle session, Ensure.IsNotNull(session, nameof(session)); ThrowIfDisposed(); var operation = CreateClientBulkWriteOperation(models, options); - return ExecuteWriteOperationAsync(session, operation, cancellationToken); + return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken); } /// @@ -213,7 +208,8 @@ public void DropDatabase(IClientSessionHandle session, string name, Cancellation Ensure.IsNotNull(session, nameof(session)); ThrowIfDisposed(); var operation = CreateDropDatabaseOperation(name); - ExecuteWriteOperation(session, operation, cancellationToken); + // TODO: CSOT: find a way to add timeout parameter to the interface method + ExecuteWriteOperation(session, operation, null, cancellationToken); } /// @@ -230,7 +226,8 @@ public Task DropDatabaseAsync(IClientSessionHandle session, string name, Cancell Ensure.IsNotNull(session, nameof(session)); ThrowIfDisposed(); var opertion = CreateDropDatabaseOperation(name); - return ExecuteWriteOperationAsync(session, opertion, cancellationToken); + // TODO: CSOT: find a way to add timeout parameter to the interface method + return ExecuteWriteOperationAsync(session, opertion, null, cancellationToken); } /// @@ -344,7 +341,7 @@ public IAsyncCursor ListDatabases( ThrowIfDisposed(); Ensure.IsNotNull(session, nameof(session)); var operation = CreateListDatabasesOperation(options); - return ExecuteReadOperation(session, operation, cancellationToken); + return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken); } /// @@ -380,7 +377,7 @@ public Task> ListDatabasesAsync( Ensure.IsNotNull(session, nameof(session)); ThrowIfDisposed(); var operation = CreateListDatabasesOperation(options); - return ExecuteReadOperationAsync(session, operation, cancellationToken); + return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken); } /// @@ -421,7 +418,7 @@ public IChangeStreamCursor Watch( Ensure.IsNotNull(pipeline, nameof(pipeline)); ThrowIfDisposed(); var operation = CreateChangeStreamOperation(pipeline, options); - return ExecuteReadOperation(session, operation, cancellationToken); + return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken); } /// @@ -446,7 +443,7 @@ public Task> WatchAsync( Ensure.IsNotNull(pipeline, nameof(pipeline)); ThrowIfDisposed(); var operation = CreateChangeStreamOperation(pipeline, options); - return ExecuteReadOperationAsync(session, operation, cancellationToken); + return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken); } /// @@ -471,17 +468,6 @@ public IMongoClient WithReadPreference(ReadPreference readPreference) return new MongoClient(newSettings, _operationExecutorFactory); } - // TODO: Should move WithTimeout into IMongoClient interface and made the method public - internal IMongoClient WithTimeout(TimeSpan timeout) - { - Ensure.IsGreaterThanZero(timeout, nameof(timeout)); - ThrowIfDisposed(); - - var newSettings = Settings.Clone(); - newSettings.Timeout = timeout; - return new MongoClient(newSettings, _operationExecutorFactory); - } - /// public IMongoClient WithWriteConcern(WriteConcern writeConcern) { @@ -560,6 +546,7 @@ private ListDatabasesOptions CreateListDatabasesOptionsFromListDatabaseNamesOpti listDatabasesOptions.AuthorizedDatabases = options.AuthorizedDatabases; listDatabasesOptions.Filter = options.Filter; listDatabasesOptions.Comment = options.Comment; + listDatabasesOptions.Timeout = options.Timeout; } return listDatabasesOptions; @@ -576,17 +563,24 @@ private ChangeStreamOperation CreateChangeStreamOperation( _settings.RetryReads, _settings.TranslationOptions); - private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, CancellationToken cancellationToken) - => _operationExecutor.ExecuteReadOperation(session, operation, _readOperationOptions, false, cancellationToken); + private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, TimeSpan? timeout, CancellationToken cancellationToken) + { + var readPreference = session.GetEffectiveReadPreference(_settings.ReadPreference); + return _operationExecutor.ExecuteReadOperation(session, operation, readPreference, false, timeout ?? _settings.Timeout, cancellationToken); + } + + private Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, TimeSpan? timeout, CancellationToken cancellationToken) + { + var readPreference = session.GetEffectiveReadPreference(_settings.ReadPreference); + return _operationExecutor.ExecuteReadOperationAsync(session, operation, readPreference, false, timeout ?? _settings.Timeout, cancellationToken); + } - private Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, CancellationToken cancellationToken) - => _operationExecutor.ExecuteReadOperationAsync(session, operation, _readOperationOptions, false, cancellationToken); + private TResult ExecuteWriteOperation(IClientSessionHandle session, IWriteOperation operation, TimeSpan? timeout, CancellationToken cancellationToken) + => _operationExecutor.ExecuteWriteOperation(session, operation, false, timeout ?? _settings.Timeout, cancellationToken); - private TResult ExecuteWriteOperation(IClientSessionHandle session, IWriteOperation operation, CancellationToken cancellationToken) - => _operationExecutor.ExecuteWriteOperation(session, operation, _writeOperationOptions, false, cancellationToken); + private Task ExecuteWriteOperationAsync(IClientSessionHandle session, IWriteOperation operation, TimeSpan? timeout, CancellationToken cancellationToken) + => _operationExecutor.ExecuteWriteOperationAsync(session, operation, false, timeout ?? _settings.Timeout, cancellationToken); - private Task ExecuteWriteOperationAsync(IClientSessionHandle session, IWriteOperation operation, CancellationToken cancellationToken) - => _operationExecutor.ExecuteWriteOperationAsync(session, operation, _writeOperationOptions, false, cancellationToken); private MessageEncoderSettings GetMessageEncoderSettings() { diff --git a/src/MongoDB.Driver/MongoClientSettings.cs b/src/MongoDB.Driver/MongoClientSettings.cs index f9014c6546a..fd76f48f141 100644 --- a/src/MongoDB.Driver/MongoClientSettings.cs +++ b/src/MongoDB.Driver/MongoClientSettings.cs @@ -73,7 +73,7 @@ public class MongoClientSettings : IEquatable, IInheritable private int _srvMaxHosts; private string _srvServiceName; private SslSettings _sslSettings; - private TimeSpan _timeout; + private TimeSpan? _timeout; private ExpressionTranslationOptions _translationOptions; private bool _useTls; private int _waitQueueSize; @@ -670,20 +670,16 @@ public SslSettings SslSettings /// /// Gets or sets the per-operation timeout /// - // TODO: CSOT: Make it public when CSOT will be ready for GA release - internal TimeSpan Timeout + public TimeSpan? Timeout { get { return _timeout; } set { ThrowIfFrozen(); - _timeout = Ensure.IsInfiniteOrGreaterThanZero(value, nameof(Timeout)); + _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); } } - // TODO: CSOT: Remove this explicit interface implementaion in favor of public Timeout property - TimeSpan IInheritableMongoClientSettings.Timeout => _timeout; - /// /// Gets or sets the translation options. /// diff --git a/src/MongoDB.Driver/MongoCollectionBase.cs b/src/MongoDB.Driver/MongoCollectionBase.cs index cc28684ca30..48f71e0f1ae 100644 --- a/src/MongoDB.Driver/MongoCollectionBase.cs +++ b/src/MongoDB.Driver/MongoCollectionBase.cs @@ -435,7 +435,8 @@ private void InsertOne(TDocument document, InsertOneOptions options, Action WithReadConcern(ReadConcern readConce public abstract IMongoCollection WithReadPreference(ReadPreference readPreference); - // TODO: Should move WithTimeout into IMongoCollection interface and made the method public - internal abstract IMongoCollection WithTimeout(TimeSpan timeout); - public abstract IMongoCollection WithWriteConcern(WriteConcern writeConcern); } } diff --git a/src/MongoDB.Driver/MongoCollectionImpl.cs b/src/MongoDB.Driver/MongoCollectionImpl.cs index 4963848297e..f24827a585b 100644 --- a/src/MongoDB.Driver/MongoCollectionImpl.cs +++ b/src/MongoDB.Driver/MongoCollectionImpl.cs @@ -39,8 +39,6 @@ internal sealed class MongoCollectionImpl : MongoCollectionBase _documentSerializer; private readonly MongoCollectionSettings _settings; - private readonly ReadOperationOptions _readOperationOptions; - private readonly WriteOperationOptions _writeOperationOptions; // constructors public MongoCollectionImpl(IMongoDatabase database, CollectionNamespace collectionNamespace, MongoCollectionSettings settings, IClusterInternal cluster, IOperationExecutor operationExecutor) @@ -58,9 +56,6 @@ private MongoCollectionImpl(IMongoDatabase database, CollectionNamespace collect _documentSerializer = Ensure.IsNotNull(documentSerializer, nameof(documentSerializer)); _messageEncoderSettings = GetMessageEncoderSettings(); - // TODO: CSOT populate the timeout from settings - _readOperationOptions = new(Timeout: _settings.Timeout, DefaultReadPreference: _settings.ReadPreference); - _writeOperationOptions = new(Timeout: _settings.Timeout); } // properties @@ -114,13 +109,13 @@ public override IAsyncCursor Aggregate(IClientSessionHandle se if (isAggregateToCollection) { var aggregateOperation = CreateAggregateToCollectionOperation(renderedPipeline, options); - ExecuteWriteOperation(session, aggregateOperation, cancellationToken); + ExecuteWriteOperation(session, aggregateOperation, options.Timeout, cancellationToken); return CreateAggregateToCollectionResultCursor(session, renderedPipeline, options); } else { var aggregateOperation = CreateAggregateOperation(renderedPipeline, options); - return ExecuteReadOperation(session, aggregateOperation, cancellationToken); + return ExecuteReadOperation(session, aggregateOperation, options.Timeout, cancellationToken); } } @@ -141,13 +136,13 @@ public override async Task> AggregateAsync(IClien if (isAggregateToCollection) { var aggregateOperation = CreateAggregateToCollectionOperation(renderedPipeline, options); - await ExecuteWriteOperationAsync(session, aggregateOperation, cancellationToken).ConfigureAwait(false); + await ExecuteWriteOperationAsync(session, aggregateOperation, options.Timeout, cancellationToken).ConfigureAwait(false); return CreateAggregateToCollectionResultCursor(session, renderedPipeline, options); } else { var aggregateOperation = CreateAggregateOperation(renderedPipeline, options); - return await ExecuteReadOperationAsync(session, aggregateOperation, cancellationToken).ConfigureAwait(false); + return await ExecuteReadOperationAsync(session, aggregateOperation, options.Timeout, cancellationToken).ConfigureAwait(false); } } @@ -171,7 +166,7 @@ public override void AggregateToCollection(IClientSessionHandle session } var aggregateOperation = CreateAggregateToCollectionOperation(renderedPipeline, options); - ExecuteWriteOperation(session, aggregateOperation, cancellationToken); + ExecuteWriteOperation(session, aggregateOperation, options.Timeout, cancellationToken); } public override async Task AggregateToCollectionAsync(PipelineDefinition pipeline, AggregateOptions options, CancellationToken cancellationToken = default) @@ -194,7 +189,7 @@ public override Task AggregateToCollectionAsync(IClientSessionHandle se } var aggregateOperation = CreateAggregateToCollectionOperation(renderedPipeline, options); - return ExecuteWriteOperationAsync(session, aggregateOperation, cancellationToken); + return ExecuteWriteOperationAsync(session, aggregateOperation, options.Timeout, cancellationToken); } public override BulkWriteResult BulkWrite(IEnumerable> requests, BulkWriteOptions options, CancellationToken cancellationToken = default) @@ -216,7 +211,7 @@ public override BulkWriteResult BulkWrite(IClientSessionHandle sessio var operation = CreateBulkWriteOperation(session, requestsArray, options); try { - var result = ExecuteWriteOperation(session, operation, cancellationToken); + var result = ExecuteWriteOperation(session, operation, options.Timeout, cancellationToken); return BulkWriteResult.FromCore(result, requestsArray); } catch (MongoBulkWriteOperationException ex) @@ -244,7 +239,7 @@ public override async Task> BulkWriteAsync(IClientSes var operation = CreateBulkWriteOperation(session, requestsArray, options); try { - var result = await ExecuteWriteOperationAsync(session, operation, cancellationToken).ConfigureAwait(false); + var result = await ExecuteWriteOperationAsync(session, operation, options.Timeout, cancellationToken).ConfigureAwait(false); return BulkWriteResult.FromCore(result, requestsArray); } catch (MongoBulkWriteOperationException ex) @@ -267,7 +262,7 @@ public override long Count(IClientSessionHandle session, FilterDefinition CountAsync(IClientSessionHandle session, FilterDefini Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateCountOperation(filter, options); - return ExecuteReadOperationAsync(session, operation, cancellationToken); + return ExecuteReadOperationAsync(session, operation, options.Timeout, cancellationToken); } public override long CountDocuments(FilterDefinition filter, CountOptions options, CancellationToken cancellationToken = default) @@ -299,7 +294,7 @@ public override long CountDocuments(IClientSessionHandle session, FilterDefiniti Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateCountDocumentsOperation(filter, options); - return ExecuteReadOperation(session, operation, cancellationToken); + return ExecuteReadOperation(session, operation, options.Timeout, cancellationToken); } public override async Task CountDocumentsAsync(FilterDefinition filter, CountOptions options, CancellationToken cancellationToken = default) @@ -314,7 +309,7 @@ public override Task CountDocumentsAsync(IClientSessionHandle session, Fil Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateCountDocumentsOperation(filter, options); - return ExecuteReadOperationAsync(session, operation, cancellationToken); + return ExecuteReadOperationAsync(session, operation, options.Timeout, cancellationToken); } public override IAsyncCursor Distinct(FieldDefinition field, FilterDefinition filter, DistinctOptions options, CancellationToken cancellationToken = default) @@ -330,7 +325,7 @@ public override IAsyncCursor Distinct(IClientSessionHandle sessi Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateDistinctOperation(field, filter, options); - return ExecuteReadOperation(session, operation, cancellationToken); + return ExecuteReadOperation(session, operation, options.Timeout, cancellationToken); } public override async Task> DistinctAsync(FieldDefinition field, FilterDefinition filter, DistinctOptions options, CancellationToken cancellationToken = default) @@ -346,7 +341,7 @@ public override Task> DistinctAsync(IClientSessionH Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateDistinctOperation(field, filter, options); - return ExecuteReadOperationAsync(session, operation, cancellationToken); + return ExecuteReadOperationAsync(session, operation, options.Timeout, cancellationToken); } public override IAsyncCursor DistinctMany(FieldDefinition> field, FilterDefinition filter, DistinctOptions options, CancellationToken cancellationToken = default) @@ -362,7 +357,7 @@ public override IAsyncCursor DistinctMany(IClientSessionHandle ses Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateDistinctManyOperation(field, filter, options); - return ExecuteReadOperation(session, operation, cancellationToken); + return ExecuteReadOperation(session, operation, options.Timeout, cancellationToken); } public override async Task> DistinctManyAsync(FieldDefinition> field, FilterDefinition filter, DistinctOptions options, CancellationToken cancellationToken = default) @@ -378,21 +373,21 @@ public override Task> DistinctManyAsync(IClientSessio Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateDistinctManyOperation(field, filter, options); - return ExecuteReadOperationAsync(session, operation, cancellationToken); + return ExecuteReadOperationAsync(session, operation, options.Timeout, cancellationToken); } public override long EstimatedDocumentCount(EstimatedDocumentCountOptions options, CancellationToken cancellationToken = default) { using var session = _operationExecutor.StartImplicitSession(); var operation = CreateEstimatedDocumentCountOperation(options); - return ExecuteReadOperation(session, operation, cancellationToken); + return ExecuteReadOperation(session, operation, options.Timeout, cancellationToken); } public override async Task EstimatedDocumentCountAsync(EstimatedDocumentCountOptions options, CancellationToken cancellationToken = default) { using var session = _operationExecutor.StartImplicitSession(); var operation = CreateEstimatedDocumentCountOperation(options); - return await ExecuteReadOperationAsync(session, operation, cancellationToken).ConfigureAwait(false); + return await ExecuteReadOperationAsync(session, operation, options.Timeout, cancellationToken).ConfigureAwait(false); } public override IAsyncCursor FindSync(FilterDefinition filter, FindOptions options, CancellationToken cancellationToken = default) @@ -407,7 +402,7 @@ public override IAsyncCursor FindSync(IClientSessionHa Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateFindOperation(filter, options); - return ExecuteReadOperation(session, operation, cancellationToken); + return ExecuteReadOperation(session, operation, options.Timeout, cancellationToken); } public override async Task> FindAsync(FilterDefinition filter, FindOptions options, CancellationToken cancellationToken = default) @@ -422,7 +417,7 @@ public override Task> FindAsync(IClientSe Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateFindOperation(filter, options); - return ExecuteReadOperationAsync(session, operation, cancellationToken); + return ExecuteReadOperationAsync(session, operation, options.Timeout, cancellationToken); } public override TProjection FindOneAndDelete(FilterDefinition filter, FindOneAndDeleteOptions options, CancellationToken cancellationToken = default) @@ -437,7 +432,7 @@ public override TProjection FindOneAndDelete(IClientSessionHandle s Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateFindOneAndDeleteOperation(filter, options); - return ExecuteWriteOperation(session, operation, cancellationToken); + return ExecuteWriteOperation(session, operation, options.Timeout, cancellationToken); } public override async Task FindOneAndDeleteAsync(FilterDefinition filter, FindOneAndDeleteOptions options, CancellationToken cancellationToken = default) @@ -452,7 +447,7 @@ public override Task FindOneAndDeleteAsync(IClientSess Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateFindOneAndDeleteOperation(filter, options); - return ExecuteWriteOperationAsync(session, operation, cancellationToken); + return ExecuteWriteOperationAsync(session, operation, options.Timeout, cancellationToken); } public override TProjection FindOneAndReplace(FilterDefinition filter, TDocument replacement, FindOneAndReplaceOptions options, CancellationToken cancellationToken = default) @@ -468,7 +463,7 @@ public override TProjection FindOneAndReplace(IClientSessionHandle var replacementObject = Ensure.IsNotNull((object)replacement, nameof(replacement)); // only box once if it's a struct var operation = CreateFindOneAndReplaceOperation(filter, replacementObject, options); - return ExecuteWriteOperation(session, operation, cancellationToken); + return ExecuteWriteOperation(session, operation, options.Timeout, cancellationToken); } public override async Task FindOneAndReplaceAsync(FilterDefinition filter, TDocument replacement, FindOneAndReplaceOptions options, CancellationToken cancellationToken = default) @@ -484,7 +479,7 @@ public override Task FindOneAndReplaceAsync(IClientSes var replacementObject = Ensure.IsNotNull((object)replacement, nameof(replacement)); // only box once if it's a struct var operation = CreateFindOneAndReplaceOperation(filter, replacementObject, options); - return ExecuteWriteOperationAsync(session, operation, cancellationToken); + return ExecuteWriteOperationAsync(session, operation, options.Timeout, cancellationToken); } public override TProjection FindOneAndUpdate(FilterDefinition filter, UpdateDefinition update, FindOneAndUpdateOptions options, CancellationToken cancellationToken = default) @@ -506,7 +501,7 @@ public override TProjection FindOneAndUpdate(IClientSessionHandle s } var operation = CreateFindOneAndUpdateOperation(filter, update, options); - return ExecuteWriteOperation(session, operation, cancellationToken); + return ExecuteWriteOperation(session, operation, options.Timeout, cancellationToken); } public override async Task FindOneAndUpdateAsync(FilterDefinition filter, UpdateDefinition update, FindOneAndUpdateOptions options, CancellationToken cancellationToken = default) @@ -527,7 +522,7 @@ public override Task FindOneAndUpdateAsync(IClientSess } var operation = CreateFindOneAndUpdateOperation(filter, update, options); - return ExecuteWriteOperationAsync(session, operation, cancellationToken); + return ExecuteWriteOperationAsync(session, operation, options.Timeout, cancellationToken); } [Obsolete("Use Aggregation pipeline instead.")] @@ -552,12 +547,12 @@ public override IAsyncCursor MapReduce(IClientSessionHandle se if (outputOptions == MapReduceOutputOptions.Inline) { var operation = CreateMapReduceOperation(map, reduce, options, resultSerializer, renderArgs); - return ExecuteReadOperation(session, operation, cancellationToken); + return ExecuteReadOperation(session, operation, options.Timeout, cancellationToken); } else { var mapReduceOperation = CreateMapReduceOutputToCollectionOperation(map, reduce, options, outputOptions, renderArgs); - ExecuteWriteOperation(session, mapReduceOperation, cancellationToken); + ExecuteWriteOperation(session, mapReduceOperation, options.Timeout, cancellationToken); return CreateMapReduceOutputToCollectionResultCursor(session, options, mapReduceOperation.OutputCollectionNamespace, resultSerializer); } } @@ -584,12 +579,12 @@ public override async Task> MapReduceAsync(IClien if (outputOptions == MapReduceOutputOptions.Inline) { var operation = CreateMapReduceOperation(map, reduce, options, resultSerializer, renderArgs); - return await ExecuteReadOperationAsync(session, operation, cancellationToken).ConfigureAwait(false); + return await ExecuteReadOperationAsync(session, operation, options.Timeout, cancellationToken).ConfigureAwait(false); } else { var mapReduceOperation = CreateMapReduceOutputToCollectionOperation(map, reduce, options, outputOptions, renderArgs); - await ExecuteWriteOperationAsync(session, mapReduceOperation, cancellationToken).ConfigureAwait(false); + await ExecuteWriteOperationAsync(session, mapReduceOperation, options.Timeout, cancellationToken).ConfigureAwait(false); return CreateMapReduceOutputToCollectionResultCursor(session, options, mapReduceOperation.OutputCollectionNamespace, resultSerializer); } } @@ -627,7 +622,7 @@ public override IChangeStreamCursor Watch( Ensure.IsNotNull(pipeline, nameof(pipeline)); var operation = CreateChangeStreamOperation(pipeline, options); - return ExecuteReadOperation(session, operation, cancellationToken); + return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken); } public override async Task> WatchAsync( @@ -649,7 +644,7 @@ public override Task> WatchAsync( Ensure.IsNotNull(pipeline, nameof(pipeline)); var operation = CreateChangeStreamOperation(pipeline, options); - return ExecuteReadOperationAsync(session, operation, cancellationToken); + return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken); } public override IMongoCollection WithReadConcern(ReadConcern readConcern) @@ -659,13 +654,6 @@ public override IMongoCollection WithReadConcern(ReadConcern readConc return new MongoCollectionImpl(_database, _collectionNamespace, newSettings, _cluster, _operationExecutor); } - internal override IMongoCollection WithTimeout(TimeSpan timeout) - { - var newSettings = _settings.Clone(); - newSettings.Timeout = timeout; - return new MongoCollectionImpl(_database, _collectionNamespace, newSettings, _cluster, _operationExecutor); - } - public override IMongoCollection WithReadPreference(ReadPreference readPreference) { var newSettings = _settings.Clone(); @@ -776,7 +764,9 @@ private AggregateOperation CreateAggregateOperation(RenderedPi Hint = options.Hint, Let = options.Let, MaxAwaitTime = options.MaxAwaitTime, +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = options.MaxTime, +#pragma warning restore CS0618 // Type or member is obsolete ReadConcern = _settings.ReadConcern, RetryRequested = _database.Client.Settings.RetryReads, #pragma warning disable 618 @@ -793,7 +783,9 @@ private IAsyncCursor CreateAggregateToCollectionResultCursor(I { BatchSize = options.BatchSize, Collation = options.Collation, +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = options.MaxTime, +#pragma warning restore CS0618 // Type or member is obsolete ReadConcern = _settings.ReadConcern, RetryRequested = _database.Client.Settings.RetryReads }; @@ -801,11 +793,10 @@ private IAsyncCursor CreateAggregateToCollectionResultCursor(I // we want to delay execution of the find because the user may // not want to iterate the results at all... var forkedSession = session.Fork(); - var readOperationOptions = _readOperationOptions with { ExplicitReadPreference = ReadPreference.Primary }; var deferredCursor = new DeferredAsyncCursor( () => forkedSession.Dispose(), - ct => ExecuteReadOperation(forkedSession, findOperation, readOperationOptions, ct), - ct => ExecuteReadOperationAsync(forkedSession, findOperation, readOperationOptions, ct)); + ct => ExecuteReadOperation(forkedSession, findOperation, ReadPreference.Primary, options.Timeout, ct), + ct => ExecuteReadOperationAsync(forkedSession, findOperation, ReadPreference.Primary, options.Timeout, ct)); return deferredCursor; } @@ -822,7 +813,9 @@ private AggregateToCollectionOperation CreateAggregateToCollectionOperation CreateDistinctOperation( Collation = options.Collation, Comment = options.Comment, Filter = filter.Render(renderArgs), +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = options.MaxTime, +#pragma warning restore CS0618 // Type or member is obsolete ReadConcern = _settings.ReadConcern, RetryRequested = _database.Client.Settings.RetryReads, }; @@ -960,7 +959,9 @@ private DistinctOperation CreateDistinctManyOperation( Collation = options.Collation, Comment = options.Comment, Filter = filter.Render(renderArgs), +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = options.MaxTime, +#pragma warning restore CS0618 // Type or member is obsolete ReadConcern = _settings.ReadConcern, RetryRequested = _database.Client.Settings.RetryReads, }; @@ -971,7 +972,9 @@ private EstimatedDocumentCountOperation CreateEstimatedDocumentCountOperation(Es return new EstimatedDocumentCountOperation(_collectionNamespace, _messageEncoderSettings) { Comment = options?.Comment, +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = options?.MaxTime, +#pragma warning restore CS0618 // Type or member is obsolete RetryRequested = _database.Client.Settings.RetryReads }; } @@ -995,7 +998,9 @@ private FindOneAndDeleteOperation CreateFindOneAndDeleteOperation CreateFindOneAndReplaceOperation Hint = options.Hint, IsUpsert = options.IsUpsert, Let = options.Let, +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = options.MaxTime, +#pragma warning restore CS0618 // Type or member is obsolete Projection = renderedProjection.Document, ReturnDocument = options.ReturnDocument, Sort = options.Sort?.Render(renderArgs), @@ -1059,7 +1066,9 @@ private FindOneAndUpdateOperation CreateFindOneAndUpdateOperation CreateFindOperation( Limit = options.Limit, Max = options.Max, MaxAwaitTime = options.MaxAwaitTime, +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = options.MaxTime, +#pragma warning restore CS0618 // Type or member is obsolete Min = options.Min, NoCursorTimeout = options.NoCursorTimeout, #pragma warning disable 618 @@ -1134,7 +1145,9 @@ private MapReduceOperation CreateMapReduceOperation( JavaScriptMode = options.JavaScriptMode, #pragma warning restore 618 Limit = options.Limit, +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = options.MaxTime, +#pragma warning restore CS0618 // Type or member is obsolete ReadConcern = _settings.ReadConcern, Scope = options.Scope, Sort = options.Sort?.Render(renderArgs), @@ -1172,7 +1185,9 @@ private MapReduceOutputToCollectionOperation CreateMapReduceOutputToCollectionOp JavaScriptMode = options.JavaScriptMode, #pragma warning restore 618 Limit = options.Limit, +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = options.MaxTime, +#pragma warning restore CS0618 // Type or member is obsolete #pragma warning disable 618 NonAtomicOutput = collectionOutputOptions.NonAtomic, #pragma warning restore 618 @@ -1197,7 +1212,9 @@ private IAsyncCursor CreateMapReduceOutputToCollectionResultCursor CreateMapReduceOutputToCollectionResultCursor( () => forkedSession.Dispose(), - ct => ExecuteReadOperation(forkedSession, findOperation, readOperationOptions, ct), - ct => ExecuteReadOperationAsync(forkedSession, findOperation, readOperationOptions, ct)); + ct => ExecuteReadOperation(forkedSession, findOperation, ReadPreference.Primary, options.Timeout, ct), + ct => ExecuteReadOperationAsync(forkedSession, findOperation, ReadPreference.Primary, options.Timeout, ct)); return deferredCursor; } - private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, CancellationToken cancellationToken) - => ExecuteReadOperation(session, operation, _readOperationOptions, cancellationToken); + private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, TimeSpan? timeout, CancellationToken cancellationToken) + => ExecuteReadOperation(session, operation, null, timeout, cancellationToken); - private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, ReadOperationOptions options, CancellationToken cancellationToken) - => _operationExecutor.ExecuteReadOperation(session, operation, options, true, cancellationToken); - - private Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, CancellationToken cancellationToken) - => ExecuteReadOperationAsync(session, operation, _readOperationOptions, cancellationToken); + private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, ReadPreference explicitReadPreference, TimeSpan? timeout, CancellationToken cancellationToken) + { + var readPreference = explicitReadPreference ?? session.GetEffectiveReadPreference(_settings.ReadPreference); + return _operationExecutor.ExecuteReadOperation(session, operation, readPreference, true, timeout ?? _settings.Timeout, cancellationToken); + } - private Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, ReadOperationOptions options, CancellationToken cancellationToken) - => _operationExecutor.ExecuteReadOperationAsync(session, operation, options, true, cancellationToken); + private Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, TimeSpan? timeout, CancellationToken cancellationToken) + => ExecuteReadOperationAsync(session, operation, null, timeout, cancellationToken); - private TResult ExecuteWriteOperation(IClientSessionHandle session, IWriteOperation operation, CancellationToken cancellationToken) - => _operationExecutor.ExecuteWriteOperation(session, operation, _writeOperationOptions, true, cancellationToken); + private Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, ReadPreference explicitReadPreference, TimeSpan? timeout, CancellationToken cancellationToken) + { + var readPreference = explicitReadPreference ?? session.GetEffectiveReadPreference(_settings.ReadPreference); + return _operationExecutor.ExecuteReadOperationAsync(session, operation, readPreference, true, timeout ?? _settings.Timeout, cancellationToken); + } - private Task ExecuteWriteOperationAsync(IClientSessionHandle session, IWriteOperation operation, CancellationToken cancellationToken) - => _operationExecutor.ExecuteWriteOperationAsync(session, operation, _writeOperationOptions, true, cancellationToken); + private TResult ExecuteWriteOperation(IClientSessionHandle session, IWriteOperation operation, TimeSpan? timeout, CancellationToken cancellationToken) + => _operationExecutor.ExecuteWriteOperation(session, operation, true, timeout ?? _settings.Timeout, cancellationToken); + private Task ExecuteWriteOperationAsync(IClientSessionHandle session, IWriteOperation operation, TimeSpan? timeout, CancellationToken cancellationToken) + => _operationExecutor.ExecuteWriteOperationAsync(session, operation, true, timeout ?? _settings.Timeout, cancellationToken); private MessageEncoderSettings GetMessageEncoderSettings() { @@ -1392,7 +1413,7 @@ public override IEnumerable CreateMany( Ensure.IsNotNull(models, nameof(models)); var operation = CreateCreateIndexesOperation(models, options); - _collection.ExecuteWriteOperation(session, operation, cancellationToken); + _collection.ExecuteWriteOperation(session, operation, options.Timeout, cancellationToken); return operation.Requests.Select(x => x.GetIndexName()); } @@ -1421,7 +1442,7 @@ public override async Task> CreateManyAsync( Ensure.IsNotNull(models, nameof(models)); var operation = CreateCreateIndexesOperation(models, options); - await _collection.ExecuteWriteOperationAsync(session, operation, cancellationToken).ConfigureAwait(false); + await _collection.ExecuteWriteOperationAsync(session, operation, options.Timeout, cancellationToken).ConfigureAwait(false); return operation.Requests.Select(x => x.GetIndexName()); } @@ -1441,7 +1462,7 @@ public override void DropAll(IClientSessionHandle session, DropIndexOptions opti { Ensure.IsNotNull(session, nameof(session)); var operation = CreateDropAllOperation(options); - _collection.ExecuteWriteOperation(session, operation, cancellationToken); + _collection.ExecuteWriteOperation(session, operation, options.Timeout, cancellationToken); } public override Task DropAllAsync(CancellationToken cancellationToken) @@ -1460,7 +1481,7 @@ public override Task DropAllAsync(IClientSessionHandle session, DropIndexOptions { Ensure.IsNotNull(session, nameof(session)); var operation = CreateDropAllOperation(options); - return _collection.ExecuteWriteOperationAsync(session, operation, cancellationToken); + return _collection.ExecuteWriteOperationAsync(session, operation, options.Timeout, cancellationToken); } public override void DropOne(string name, CancellationToken cancellationToken = default) @@ -1485,7 +1506,7 @@ public override void DropOne(IClientSessionHandle session, string name, DropInde } var operation = CreateDropOneOperation(name, options); - _collection.ExecuteWriteOperation(session, operation, cancellationToken); + _collection.ExecuteWriteOperation(session, operation, options.Timeout, cancellationToken); } public override Task DropOneAsync(string name, CancellationToken cancellationToken = default) @@ -1510,7 +1531,7 @@ public override Task DropOneAsync(IClientSessionHandle session, string name, Dro } var operation = CreateDropOneOperation(name, options); - return _collection.ExecuteWriteOperationAsync(session, operation, cancellationToken); + return _collection.ExecuteWriteOperationAsync(session, operation, options.Timeout, cancellationToken); } public override IAsyncCursor List(CancellationToken cancellationToken = default) @@ -1529,7 +1550,7 @@ public override IAsyncCursor List(IClientSessionHandle session, Li { Ensure.IsNotNull(session, nameof(session)); var operation = CreateListIndexesOperation(options); - return _collection.ExecuteReadOperation(session, operation, cancellationToken); + return _collection.ExecuteReadOperation(session, operation, options.Timeout, cancellationToken); } public override Task> ListAsync(CancellationToken cancellationToken = default) @@ -1548,7 +1569,7 @@ public override Task> ListAsync(IClientSessionHandle { Ensure.IsNotNull(session, nameof(session)); var operation = CreateListIndexesOperation(options); - return _collection.ExecuteReadOperationAsync(session, operation, cancellationToken); + return _collection.ExecuteReadOperationAsync(session, operation, options.Timeout, cancellationToken); } // private methods @@ -1560,7 +1581,9 @@ private CreateIndexesOperation CreateCreateIndexesOperation(IEnumerable CreateMany(IEnumerable models { using var session = _collection._operationExecutor.StartImplicitSession(); var operation = CreateCreateIndexesOperation(models); - var result = _collection.ExecuteWriteOperation(session, operation, cancellationToken); + // TODO: CSOT: find a way to add timeout parameter to the interface method + var result = _collection.ExecuteWriteOperation(session, operation, null, cancellationToken); return GetIndexNames(result); } @@ -1657,7 +1685,8 @@ public async Task> CreateManyAsync(IEnumerable List(string indexName, AggregateOptions aggregateOptions = null, CancellationToken cancellationToken = default) @@ -1707,14 +1738,16 @@ public void Update(string indexName, BsonDocument definition, CancellationToken { using var session = _collection._operationExecutor.StartImplicitSession(); var operation = new UpdateSearchIndexOperation(_collection.CollectionNamespace, indexName, definition, _collection._messageEncoderSettings); - _collection.ExecuteWriteOperation(session, operation, cancellationToken); + // TODO: CSOT: find a way to add timeout parameter to the interface method + _collection.ExecuteWriteOperation(session, operation, null, cancellationToken); } public async Task UpdateAsync(string indexName, BsonDocument definition, CancellationToken cancellationToken = default) { using var session = _collection._operationExecutor.StartImplicitSession(); var operation = new UpdateSearchIndexOperation(_collection.CollectionNamespace, indexName, definition, _collection._messageEncoderSettings); - await _collection.ExecuteWriteOperationAsync(session, operation, cancellationToken).ConfigureAwait(false); + // TODO: CSOT: find a way to add timeout parameter to the interface method + await _collection.ExecuteWriteOperationAsync(session, operation, null, cancellationToken).ConfigureAwait(false); } // private methods diff --git a/src/MongoDB.Driver/MongoCollectionSettings.cs b/src/MongoDB.Driver/MongoCollectionSettings.cs index 54101eca5c2..0ee8d0f467a 100644 --- a/src/MongoDB.Driver/MongoCollectionSettings.cs +++ b/src/MongoDB.Driver/MongoCollectionSettings.cs @@ -31,7 +31,7 @@ public class MongoCollectionSettings private Setting _readConcern; private Setting _readEncoding; private Setting _readPreference; - private Setting _timeout; + private TimeSpan? _timeout; private Setting _writeConcern; private Setting _writeEncoding; @@ -124,14 +124,13 @@ public IBsonSerializerRegistry SerializerRegistry /// /// Gets or sets the per-operation timeout /// - // TODO: CSOT: Make it public when CSOT will be ready for GA release - internal TimeSpan Timeout + public TimeSpan? Timeout { get { return _timeout.Value; } set { if (_isFrozen) { throw new InvalidOperationException("MongoCollectionSettings is frozen."); } - _timeout.Value = Ensure.IsInfiniteOrGreaterThanZero(value, nameof(Timeout)); + _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); } } @@ -177,7 +176,7 @@ public virtual MongoCollectionSettings Clone() clone._readConcern = _readConcern.Clone(); clone._readEncoding = _readEncoding.Clone(); clone._readPreference = _readPreference.Clone(); - clone._timeout = _timeout.Clone(); + clone._timeout = _timeout; clone._writeConcern = _writeConcern.Clone(); clone._writeEncoding = _writeEncoding.Clone(); return clone; @@ -208,7 +207,7 @@ public override bool Equals(object obj) object.Equals(_readConcern.Value, rhs._readConcern.Value) && object.Equals(_readEncoding, rhs._readEncoding) && _readPreference.Value == rhs._readPreference.Value && - _timeout.Value == rhs._timeout.Value && + _timeout == rhs._timeout && _writeConcern.Value == rhs._writeConcern.Value && object.Equals(_writeEncoding, rhs._writeEncoding); } @@ -263,7 +262,7 @@ public override int GetHashCode() hash = 37 * hash + ((_readConcern.Value == null) ? 0 : _readConcern.Value.GetHashCode()); hash = 37 * hash + ((_readEncoding.Value == null) ? 0 : _readEncoding.Value.GetHashCode()); hash = 37 * hash + ((_readPreference.Value == null) ? 0 : _readPreference.Value.GetHashCode()); - hash = 37 * hash + _timeout.Value.GetHashCode(); + hash = 37 * hash + _timeout.GetHashCode(); hash = 37 * hash + ((_writeConcern.Value == null) ? 0 : _writeConcern.Value.GetHashCode()); hash = 37 * hash + ((_writeEncoding.Value == null) ? 0 : _writeEncoding.Value.GetHashCode()); return hash; @@ -288,7 +287,7 @@ public override string ToString() parts.Add(string.Format("ReadEncoding={0}", (_readEncoding.Value == null) ? "null" : "UTF8Encoding")); } parts.Add(string.Format("ReadPreference={0}", _readPreference)); - if (_timeout.HasBeenSet) + if (_timeout.HasValue) { parts.Add(string.Format("Timeout={0}", _timeout)); } @@ -319,7 +318,7 @@ internal void ApplyDefaultValues(MongoDatabaseSettings databaseSettings) { ReadPreference = databaseSettings.ReadPreference; } - if (!_timeout.HasBeenSet) + if (!_timeout.HasValue) { Timeout = databaseSettings.Timeout; } diff --git a/src/MongoDB.Driver/MongoDatabase.cs b/src/MongoDB.Driver/MongoDatabase.cs index a46420e6a95..ba9b141ac06 100644 --- a/src/MongoDB.Driver/MongoDatabase.cs +++ b/src/MongoDB.Driver/MongoDatabase.cs @@ -39,8 +39,6 @@ internal sealed class MongoDatabase : IMongoDatabase private readonly DatabaseNamespace _databaseNamespace; private readonly IOperationExecutor _operationExecutor; private readonly MongoDatabaseSettings _settings; - private readonly ReadOperationOptions _readOperationOptions; - private readonly WriteOperationOptions _writeOperationOptions; // constructors public MongoDatabase(IMongoClient client, DatabaseNamespace databaseNamespace, MongoDatabaseSettings settings, IClusterInternal cluster, IOperationExecutor operationExecutor) @@ -50,9 +48,6 @@ public MongoDatabase(IMongoClient client, DatabaseNamespace databaseNamespace, M _settings = Ensure.IsNotNull(settings, nameof(settings)).Freeze(); _cluster = Ensure.IsNotNull(cluster, nameof(cluster)); _operationExecutor = Ensure.IsNotNull(operationExecutor, nameof(operationExecutor)); - // TODO: CSOT populate the timeout from settings - _readOperationOptions = new(Timeout: _settings.Timeout, DefaultReadPreference: _settings.ReadPreference); - _writeOperationOptions = new(Timeout: _settings.Timeout); } // public properties @@ -78,13 +73,13 @@ public IAsyncCursor Aggregate(IClientSessionHandle session, Pi if (isAggregateToCollection) { var aggregateOperation = CreateAggregateToCollectionOperation(renderedPipeline, options); - ExecuteWriteOperation(session, aggregateOperation, cancellationToken); + ExecuteWriteOperation(session, aggregateOperation, options.Timeout, cancellationToken); return CreateAggregateToCollectionResultCursor(session, renderedPipeline, options); } else { var aggregateOperation = CreateAggregateOperation(renderedPipeline, options); - return ExecuteReadOperation(session, aggregateOperation, cancellationToken); + return ExecuteReadOperation(session, aggregateOperation, options.Timeout, cancellationToken); } } @@ -105,13 +100,13 @@ public async Task> AggregateAsync(IClientSessionH if (isAggregateToCollection) { var aggregateOperation = CreateAggregateToCollectionOperation(renderedPipeline, options); - await ExecuteWriteOperationAsync(session, aggregateOperation, cancellationToken).ConfigureAwait(false); + await ExecuteWriteOperationAsync(session, aggregateOperation, options.Timeout, cancellationToken).ConfigureAwait(false); return CreateAggregateToCollectionResultCursor(session, renderedPipeline, options); } else { var aggregateOperation = CreateAggregateOperation(renderedPipeline, options); - return await ExecuteReadOperationAsync(session, aggregateOperation, cancellationToken).ConfigureAwait(false); + return await ExecuteReadOperationAsync(session, aggregateOperation, options.Timeout, cancellationToken).ConfigureAwait(false); } } @@ -135,7 +130,7 @@ public void AggregateToCollection(IClientSessionHandle session, Pipelin } var aggregateOperation = CreateAggregateToCollectionOperation(renderedPipeline, options); - ExecuteWriteOperation(session, aggregateOperation, cancellationToken); + ExecuteWriteOperation(session, aggregateOperation, options.Timeout, cancellationToken); } public async Task AggregateToCollectionAsync(PipelineDefinition pipeline, AggregateOptions options, CancellationToken cancellationToken = default) @@ -158,7 +153,7 @@ public Task AggregateToCollectionAsync(IClientSessionHandle session, Pi } var aggregateOperation = CreateAggregateToCollectionOperation(renderedPipeline, options); - return ExecuteWriteOperationAsync(session, aggregateOperation, cancellationToken); + return ExecuteWriteOperationAsync(session, aggregateOperation, options.Timeout, cancellationToken); } public void CreateCollection(string name, CreateCollectionOptions options, CancellationToken cancellationToken) @@ -249,7 +244,7 @@ public void CreateView(IClientSessionHandle session, string Ensure.IsNotNull(pipeline, nameof(pipeline)); var operation = CreateCreateViewOperation(viewName, viewOn, pipeline, options); - ExecuteWriteOperation(session, operation, cancellationToken); + ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken); } public async Task CreateViewAsync(string viewName, string viewOn, PipelineDefinition pipeline, CreateViewOptions options = null, CancellationToken cancellationToken = default) @@ -266,7 +261,7 @@ public Task CreateViewAsync(IClientSessionHandle session, st Ensure.IsNotNull(pipeline, nameof(pipeline)); var operation = CreateCreateViewOperation(viewName, viewOn, pipeline, options); - return ExecuteWriteOperationAsync(session, operation, cancellationToken); + return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken); } public void DropCollection(string name, CancellationToken cancellationToken) @@ -293,7 +288,7 @@ public void DropCollection(IClientSessionHandle session, string name, DropCollec var collectionNamespace = new CollectionNamespace(_databaseNamespace, name); var encryptedFields = GetEffectiveEncryptedFields(session, collectionNamespace, options, cancellationToken); var operation = CreateDropCollectionOperation(collectionNamespace, encryptedFields); - ExecuteWriteOperation(session, operation, cancellationToken); + ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken); } public Task DropCollectionAsync(string name, CancellationToken cancellationToken) @@ -316,7 +311,7 @@ public async Task DropCollectionAsync(IClientSessionHandle session, string name, var collectionNamespace = new CollectionNamespace(_databaseNamespace, name); var encryptedFields = await GetEffectiveEncryptedFieldsAsync(session, collectionNamespace, options, cancellationToken).ConfigureAwait(false); var operation = CreateDropCollectionOperation(collectionNamespace, encryptedFields); - await ExecuteWriteOperationAsync(session, operation, cancellationToken).ConfigureAwait(false); + await ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken).ConfigureAwait(false); } public IMongoCollection GetCollection(string name, MongoCollectionSettings settings) @@ -342,7 +337,8 @@ public IAsyncCursor ListCollectionNames(IClientSessionHandle session, Li { Ensure.IsNotNull(session, nameof(session)); var operation = CreateListCollectionNamesOperation(options); - var cursor = ExecuteReadOperation(session, operation, _readOperationOptions with { DefaultReadPreference = ReadPreference.Primary }, cancellationToken); + var readPreference = session.GetEffectiveReadPreference(ReadPreference.Primary); + var cursor = ExecuteReadOperation(session, operation, readPreference, options?.Timeout, cancellationToken); return new BatchTransformingAsyncCursor(cursor, ExtractCollectionNames); } @@ -356,7 +352,8 @@ public async Task> ListCollectionNamesAsync(IClientSessionH { Ensure.IsNotNull(session, nameof(session)); var operation = CreateListCollectionNamesOperation(options); - var cursor = await ExecuteReadOperationAsync(session, operation, _readOperationOptions with { DefaultReadPreference = ReadPreference.Primary }, cancellationToken).ConfigureAwait(false); + var readPreference = session.GetEffectiveReadPreference(ReadPreference.Primary); + var cursor = await ExecuteReadOperationAsync(session, operation, readPreference, options?.Timeout, cancellationToken).ConfigureAwait(false); return new BatchTransformingAsyncCursor(cursor, ExtractCollectionNames); } @@ -370,7 +367,8 @@ public IAsyncCursor ListCollections(IClientSessionHandle session, { Ensure.IsNotNull(session, nameof(session)); var operation = CreateListCollectionsOperation(options); - return ExecuteReadOperation(session, operation, _readOperationOptions with { DefaultReadPreference = ReadPreference.Primary }, cancellationToken); + var readPreference = session.GetEffectiveReadPreference(ReadPreference.Primary); + return ExecuteReadOperation(session, operation, readPreference, options?.Timeout, cancellationToken); } public async Task> ListCollectionsAsync(ListCollectionsOptions options, CancellationToken cancellationToken) @@ -383,7 +381,8 @@ public Task> ListCollectionsAsync(IClientSessionHandl { Ensure.IsNotNull(session, nameof(session)); var operation = CreateListCollectionsOperation(options); - return ExecuteReadOperationAsync(session, operation, _readOperationOptions with { DefaultReadPreference = ReadPreference.Primary }, cancellationToken); + var readPreference = session.GetEffectiveReadPreference(ReadPreference.Primary); + return ExecuteReadOperationAsync(session, operation, readPreference, options?.Timeout, cancellationToken); } public void RenameCollection(string oldName, string newName, RenameCollectionOptions options, CancellationToken cancellationToken) @@ -399,7 +398,7 @@ public void RenameCollection(IClientSessionHandle session, string oldName, strin Ensure.IsNotNullOrEmpty(newName, nameof(newName)); var operation = CreateRenameCollectionOperation(oldName, newName, options); - ExecuteWriteOperation(session, operation, cancellationToken); + ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken); } public async Task RenameCollectionAsync(string oldName, string newName, RenameCollectionOptions options, CancellationToken cancellationToken) @@ -415,7 +414,7 @@ public Task RenameCollectionAsync(IClientSessionHandle session, string oldName, Ensure.IsNotNullOrEmpty(newName, nameof(newName)); var operation = CreateRenameCollectionOperation(oldName, newName, options); - return ExecuteWriteOperationAsync(session, operation, cancellationToken); + return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken); } public TResult RunCommand(Command command, ReadPreference readPreference = null, CancellationToken cancellationToken = default) @@ -430,7 +429,14 @@ public TResult RunCommand(IClientSessionHandle session, Command RunCommandAsync(Command command, ReadPreference readPreference = null, CancellationToken cancellationToken = default) @@ -445,7 +451,14 @@ public Task RunCommandAsync(IClientSessionHandle session, Comm Ensure.IsNotNull(command, nameof(command)); var operation = CreateRunCommandOperation(command); - return ExecuteReadOperationAsync(session, operation, _readOperationOptions with { ExplicitReadPreference = readPreference, DefaultReadPreference = ReadPreference.Primary }, cancellationToken); + var effectiveReadPreference = readPreference; + if (readPreference == null) + { + effectiveReadPreference = session.GetEffectiveReadPreference(ReadPreference.Primary); + } + + // TODO: CSOT: See what run command should do with timeout + return ExecuteReadOperationAsync(session, operation, effectiveReadPreference, null, cancellationToken); } public IChangeStreamCursor Watch( @@ -467,7 +480,7 @@ public IChangeStreamCursor Watch( Ensure.IsNotNull(pipeline, nameof(pipeline)); var operation = CreateChangeStreamOperation(pipeline, options); - return ExecuteReadOperation(session, operation, cancellationToken); + return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken); } public async Task> WatchAsync( @@ -489,7 +502,7 @@ public Task> WatchAsync( Ensure.IsNotNull(pipeline, nameof(pipeline)); var operation = CreateChangeStreamOperation(pipeline, options); - return ExecuteReadOperationAsync(session, operation, cancellationToken); + return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken); } public IMongoDatabase WithReadConcern(ReadConcern readConcern) @@ -508,16 +521,6 @@ public IMongoDatabase WithReadPreference(ReadPreference readPreference) return new MongoDatabase(_client, _databaseNamespace, newSettings, _cluster, _operationExecutor); } - // TODO: Should move WithTimeout into IMongoDatabase interface and made the method public - internal IMongoDatabase WithTimeout(TimeSpan timeout) - { - Ensure.IsGreaterThanZero(timeout, nameof(timeout)); - - var newSettings = Settings.Clone(); - newSettings.Timeout = timeout; - return new MongoDatabase(_client, _databaseNamespace, newSettings, _cluster, _operationExecutor); - } - public IMongoDatabase WithWriteConcern(WriteConcern writeConcern) { Ensure.IsNotNull(writeConcern, nameof(writeConcern)); @@ -544,7 +547,9 @@ private AggregateOperation CreateAggregateOperation(RenderedPi Hint = options.Hint, Let = options.Let, MaxAwaitTime = options.MaxAwaitTime, +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = options.MaxTime, +#pragma warning restore CS0618 // Type or member is obsolete ReadConcern = _settings.ReadConcern, RetryRequested = _client.Settings.RetryReads, #pragma warning disable 618 @@ -566,7 +571,9 @@ private IAsyncCursor CreateAggregateToCollectionResultCursor(I { BatchSize = options.BatchSize, Collation = options.Collation, +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = options.MaxTime, +#pragma warning restore CS0618 // Type or member is obsolete ReadConcern = _settings.ReadConcern, RetryRequested = _client.Settings.RetryReads }; @@ -574,11 +581,10 @@ private IAsyncCursor CreateAggregateToCollectionResultCursor(I // we want to delay execution of the find because the user may // not want to iterate the results at all... var forkedSession = session.Fork(); - var readOperationOptions = _readOperationOptions with { ExplicitReadPreference = ReadPreference.Primary }; var deferredCursor = new DeferredAsyncCursor( () => forkedSession.Dispose(), - ct => ExecuteReadOperation(forkedSession, findOperation, readOperationOptions, ct), - ct => ExecuteReadOperationAsync(forkedSession, findOperation, readOperationOptions, ct)); + ct => ExecuteReadOperation(forkedSession, findOperation, ReadPreference.Primary, options.Timeout, ct), + ct => ExecuteReadOperationAsync(forkedSession, findOperation, ReadPreference.Primary, options.Timeout, ct)); return deferredCursor; } @@ -596,7 +602,9 @@ private AggregateToCollectionOperation CreateAggregateToCollectionOperation(IClientSessionHandle session, string name, CreateCollectionOptions options, CancellationToken cancellationToken) { var operation = CreateCreateCollectionOperation(name, options); - ExecuteWriteOperation(session, operation, cancellationToken); + ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken); } private Task CreateCollectionHelperAsync(IClientSessionHandle session, string name, CreateCollectionOptions options, CancellationToken cancellationToken) { var operation = CreateCreateCollectionOperation(name, options); - return ExecuteWriteOperationAsync(session, operation, cancellationToken); + return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken); } private IWriteOperation CreateCreateCollectionOperation(string name, CreateCollectionOptions options) @@ -753,23 +761,29 @@ private ChangeStreamOperation CreateChangeStreamOperation( translationOptions); } - private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, CancellationToken cancellationToken) - => ExecuteReadOperation(session, operation, _readOperationOptions, cancellationToken); + private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, TimeSpan? timeout, CancellationToken cancellationToken) + => ExecuteReadOperation(session, operation, null, timeout, cancellationToken); - private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, ReadOperationOptions options, CancellationToken cancellationToken) - => _operationExecutor.ExecuteReadOperation(session, operation, options, true, cancellationToken); + private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, ReadPreference explicitReadPreference, TimeSpan? timeout, CancellationToken cancellationToken) + { + var readPreference = explicitReadPreference ?? session.GetEffectiveReadPreference(_settings.ReadPreference); + return _operationExecutor.ExecuteReadOperation(session, operation, readPreference, true, timeout ?? _settings.Timeout, cancellationToken); + } - private Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, CancellationToken cancellationToken) - => ExecuteReadOperationAsync(session, operation, _readOperationOptions, cancellationToken); + private Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, TimeSpan? timeout, CancellationToken cancellationToken) + => ExecuteReadOperationAsync(session, operation, null, timeout, cancellationToken); - private Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, ReadOperationOptions options, CancellationToken cancellationToken) - => _operationExecutor.ExecuteReadOperationAsync(session, operation, options, true, cancellationToken); + private Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, ReadPreference explicitReadPreference, TimeSpan? timeout, CancellationToken cancellationToken) + { + var readPreference = explicitReadPreference ?? session.GetEffectiveReadPreference(_settings.ReadPreference); + return _operationExecutor.ExecuteReadOperationAsync(session, operation, readPreference, true, timeout ?? _settings.Timeout, cancellationToken); + } - private TResult ExecuteWriteOperation(IClientSessionHandle session, IWriteOperation operation, CancellationToken cancellationToken) - => _operationExecutor.ExecuteWriteOperation(session, operation, _writeOperationOptions, true, cancellationToken); + private TResult ExecuteWriteOperation(IClientSessionHandle session, IWriteOperation operation, TimeSpan? timeout, CancellationToken cancellationToken) + => _operationExecutor.ExecuteWriteOperation(session, operation, true, timeout ?? _settings.Timeout, cancellationToken); - private Task ExecuteWriteOperationAsync(IClientSessionHandle session, IWriteOperation operation, CancellationToken cancellationToken) - => _operationExecutor.ExecuteWriteOperationAsync(session, operation, _writeOperationOptions, true, cancellationToken); + private Task ExecuteWriteOperationAsync(IClientSessionHandle session, IWriteOperation operation, TimeSpan? timeout, CancellationToken cancellationToken) + => _operationExecutor.ExecuteWriteOperationAsync(session, operation, true, timeout ?? _settings.Timeout, cancellationToken); private IEnumerable ExtractCollectionNames(IEnumerable collections) { diff --git a/src/MongoDB.Driver/MongoDatabaseSettings.cs b/src/MongoDB.Driver/MongoDatabaseSettings.cs index 55f18d25077..c1c82935600 100644 --- a/src/MongoDB.Driver/MongoDatabaseSettings.cs +++ b/src/MongoDB.Driver/MongoDatabaseSettings.cs @@ -30,7 +30,7 @@ public class MongoDatabaseSettings private Setting _readConcern; private Setting _readEncoding; private Setting _readPreference; - private Setting _timeout; + private TimeSpan? _timeout; private Setting _writeConcern; private Setting _writeEncoding; @@ -109,14 +109,13 @@ public IBsonSerializerRegistry SerializerRegistry /// /// Gets or sets the per-operation timeout /// - // TODO: CSOT: Make it public when CSOT will be ready for GA release - internal TimeSpan Timeout + public TimeSpan? Timeout { get { return _timeout.Value; } set { if (_isFrozen) { throw new InvalidOperationException("MongoCollectionSettings is frozen."); } - _timeout.Value = Ensure.IsInfiniteOrGreaterThanZero(value, nameof(Timeout)); + _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); } } @@ -161,7 +160,7 @@ public MongoDatabaseSettings Clone() clone._readConcern = _readConcern.Clone(); clone._readEncoding = _readEncoding.Clone(); clone._readPreference = _readPreference.Clone(); - clone._timeout = _timeout.Clone(); + clone._timeout = _timeout; clone._writeConcern = _writeConcern.Clone(); clone._writeEncoding = _writeEncoding.Clone(); return clone; @@ -269,7 +268,7 @@ public override string ToString() parts.Add(string.Format("ReadEncoding={0}", (_readEncoding.Value == null) ? "null" : "UTF8Encoding")); } parts.Add(string.Format("ReadPreference={0}", _readPreference.Value)); - if (_timeout.HasBeenSet) + if (_timeout.HasValue) { parts.Add(string.Format("Timeout={0}", _timeout.Value)); } @@ -296,7 +295,7 @@ internal void ApplyDefaultValues(IInheritableMongoClientSettings clientSettings) { ReadPreference = clientSettings.ReadPreference; } - if (!_timeout.HasBeenSet) + if (!_timeout.HasValue) { Timeout = clientSettings.Timeout; } diff --git a/src/MongoDB.Driver/MongoIndexManagerBase.cs b/src/MongoDB.Driver/MongoIndexManagerBase.cs index 0ac93ee98ff..f8576b0f220 100644 --- a/src/MongoDB.Driver/MongoIndexManagerBase.cs +++ b/src/MongoDB.Driver/MongoIndexManagerBase.cs @@ -319,7 +319,10 @@ private CreateManyIndexesOptions ToCreateManyIndexesOptions(CreateOneIndexOption return new CreateManyIndexesOptions { CommitQuorum = options?.CommitQuorum, - MaxTime = options?.MaxTime +#pragma warning disable CS0618 // Type or member is obsolete + MaxTime = options?.MaxTime, +#pragma warning restore CS0618 // Type or member is obsolete + Timeout = options?.Timeout, }; } } diff --git a/src/MongoDB.Driver/MongoUrl.cs b/src/MongoDB.Driver/MongoUrl.cs index eb7306aca41..c2e51c855dc 100644 --- a/src/MongoDB.Driver/MongoUrl.cs +++ b/src/MongoDB.Driver/MongoUrl.cs @@ -71,7 +71,7 @@ public class MongoUrl : IEquatable private readonly TimeSpan _socketTimeout; private readonly int? _srvMaxHosts; private readonly string _srvServiceName; - private readonly TimeSpan _timeout; + private readonly TimeSpan? _timeout; private readonly bool _tlsDisableCertificateRevocationCheck; private readonly string _username; private readonly bool _useTls; @@ -467,8 +467,7 @@ public string SrvServiceName /// /// Gets the per-operation timeout /// - // TODO: CSOT: Make it public when CSOT will be ready for GA release - internal TimeSpan Timeout => _timeout; + public TimeSpan? Timeout => _timeout; /// /// Gets whether or not to disable checking certificate revocation status during the TLS handshake. diff --git a/src/MongoDB.Driver/MongoUrlBuilder.cs b/src/MongoDB.Driver/MongoUrlBuilder.cs index 22f34a2e482..a9baecaa78b 100644 --- a/src/MongoDB.Driver/MongoUrlBuilder.cs +++ b/src/MongoDB.Driver/MongoUrlBuilder.cs @@ -66,7 +66,7 @@ public class MongoUrlBuilder private TimeSpan _socketTimeout; private int? _srvMaxHosts; private string _srvServiceName; - private TimeSpan _timeout; + private TimeSpan? _timeout; private bool? _tlsDisableCertificateRevocationCheck; private string _username; private bool _useTls; @@ -596,13 +596,12 @@ public string SrvServiceName /// /// Gets or sets the per-operation timeout /// - // TODO: CSOT: Make it public when CSOT will be ready for GA release - internal TimeSpan Timeout + public TimeSpan? Timeout { get { return _timeout; } set { - _timeout = Ensure.IsInfiniteOrGreaterThanZero(value, nameof(Timeout)); + _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); } } @@ -971,9 +970,9 @@ public override string ToString() query.AppendFormat("socketTimeout={0}&", FormatTimeSpan(_socketTimeout)); } - if (_timeout != System.Threading.Timeout.InfiniteTimeSpan) + if (_timeout.HasValue) { - query.AppendFormat("timeout={0}&", FormatTimeSpan(_timeout)); + query.AppendFormat("timeout={0}&", FormatTimeSpan(_timeout.Value)); } #pragma warning disable 618 diff --git a/src/MongoDB.Driver/OfTypeMongoCollection.cs b/src/MongoDB.Driver/OfTypeMongoCollection.cs index 7c68399a1d1..152096e56dd 100644 --- a/src/MongoDB.Driver/OfTypeMongoCollection.cs +++ b/src/MongoDB.Driver/OfTypeMongoCollection.cs @@ -1,4 +1,4 @@ -/* Copyright 2015-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * limitations under the License. */ -using System; using MongoDB.Bson; using MongoDB.Bson.Serialization; @@ -51,11 +50,6 @@ public override IMongoCollection WithReadPreference(ReadPrefer return new OfTypeMongoCollection(_rootDocumentCollection, WrappedCollection.WithReadPreference(readPreference), Filter); } - internal override IMongoCollection WithTimeout(TimeSpan timeout) - { - return new OfTypeMongoCollection(_rootDocumentCollection, WrappedCollection.WithTimeout(timeout), Filter); - } - public override IMongoCollection WithWriteConcern(WriteConcern writeConcern) { return new OfTypeMongoCollection(_rootDocumentCollection, WrappedCollection.WithWriteConcern(writeConcern), Filter); diff --git a/src/MongoDB.Driver/OperationContext.cs b/src/MongoDB.Driver/OperationContext.cs index a2ea007b93e..ac6e7737dd9 100644 --- a/src/MongoDB.Driver/OperationContext.cs +++ b/src/MongoDB.Driver/OperationContext.cs @@ -29,15 +29,15 @@ internal sealed class OperationContext : IDisposable private CancellationTokenSource _remainingTimeoutCancellationTokenSource; private CancellationTokenSource _combinedCancellationTokenSource; - public OperationContext(TimeSpan timeout, CancellationToken cancellationToken) + public OperationContext(TimeSpan? timeout, CancellationToken cancellationToken) : this(Stopwatch.StartNew(), timeout, cancellationToken) { } - internal OperationContext(Stopwatch stopwatch, TimeSpan timeout, CancellationToken cancellationToken) + internal OperationContext(Stopwatch stopwatch, TimeSpan? timeout, CancellationToken cancellationToken) { Stopwatch = stopwatch; - Timeout = Ensure.IsInfiniteOrGreaterThanOrEqualToZero(timeout, nameof(timeout)); + Timeout = Ensure.IsNullOrValidTimeout(timeout, nameof(timeout)); CancellationToken = cancellationToken; RootContext = this; } @@ -50,12 +50,12 @@ public TimeSpan RemainingTimeout { get { - if (Timeout == System.Threading.Timeout.InfiniteTimeSpan) + if (Timeout == null || Timeout == System.Threading.Timeout.InfiniteTimeSpan) { return System.Threading.Timeout.InfiniteTimeSpan; } - var result = Timeout - Stopwatch.Elapsed; + var result = Timeout.Value - Stopwatch.Elapsed; if (result < TimeSpan.Zero) { result = TimeSpan.Zero; @@ -87,7 +87,7 @@ public CancellationToken CombinedCancellationToken } private Stopwatch Stopwatch { get; } - public TimeSpan Timeout { get; } + public TimeSpan? Timeout { get; } public void Dispose() { diff --git a/src/MongoDB.Driver/OperationContextExtensions.cs b/src/MongoDB.Driver/OperationContextExtensions.cs index dace4a05bdf..7350214e227 100644 --- a/src/MongoDB.Driver/OperationContextExtensions.cs +++ b/src/MongoDB.Driver/OperationContextExtensions.cs @@ -13,13 +13,11 @@ * limitations under the License. */ -using System.Threading; - namespace MongoDB.Driver { internal static class OperationContextExtensions { public static bool IsRootContextTimeoutConfigured(this OperationContext operationContext) - => operationContext.RootContext.Timeout != Timeout.InfiniteTimeSpan; + => operationContext.RootContext.Timeout.HasValue; } } diff --git a/src/MongoDB.Driver/OperationExecutor.cs b/src/MongoDB.Driver/OperationExecutor.cs index 84ddcf287bd..06c8534b70c 100644 --- a/src/MongoDB.Driver/OperationExecutor.cs +++ b/src/MongoDB.Driver/OperationExecutor.cs @@ -41,17 +41,18 @@ public void Dispose() public TResult ExecuteReadOperation( IClientSessionHandle session, IReadOperation operation, - ReadOperationOptions options, + ReadPreference readPreference, bool allowChannelPinning, + TimeSpan? timeout, CancellationToken cancellationToken) { - Ensure.IsNotNull(operation, nameof(operation)); - Ensure.IsNotNull(options, nameof(options)); Ensure.IsNotNull(session, nameof(session)); + Ensure.IsNotNull(operation, nameof(operation)); + Ensure.IsNotNull(readPreference, nameof(readPreference)); + Ensure.IsNullOrValidTimeout(timeout, nameof(timeout)); ThrowIfDisposed(); - using var operationContext = options.ToOperationContext(cancellationToken); - var readPreference = options.GetEffectiveReadPreference(session); + using var operationContext = new OperationContext(timeout, cancellationToken); using var binding = CreateReadBinding(session, readPreference, allowChannelPinning); return operation.Execute(operationContext, binding); } @@ -59,17 +60,18 @@ public TResult ExecuteReadOperation( public async Task ExecuteReadOperationAsync( IClientSessionHandle session, IReadOperation operation, - ReadOperationOptions options, + ReadPreference readPreference, bool allowChannelPinning, + TimeSpan? timeout, CancellationToken cancellationToken) { - Ensure.IsNotNull(operation, nameof(operation)); - Ensure.IsNotNull(options, nameof(options)); Ensure.IsNotNull(session, nameof(session)); + Ensure.IsNotNull(operation, nameof(operation)); + Ensure.IsNotNull(readPreference, nameof(readPreference)); + Ensure.IsNullOrValidTimeout(timeout, nameof(timeout)); ThrowIfDisposed(); - using var operationContext = options.ToOperationContext(cancellationToken); - var readPreference = options.GetEffectiveReadPreference(session); + using var operationContext = new OperationContext(timeout, cancellationToken); using var binding = CreateReadBinding(session, readPreference, allowChannelPinning); return await operation.ExecuteAsync(operationContext, binding).ConfigureAwait(false); } @@ -77,16 +79,16 @@ public async Task ExecuteReadOperationAsync( public TResult ExecuteWriteOperation( IClientSessionHandle session, IWriteOperation operation, - WriteOperationOptions options, bool allowChannelPinning, + TimeSpan? timeout, CancellationToken cancellationToken) { - Ensure.IsNotNull(operation, nameof(operation)); - Ensure.IsNotNull(options, nameof(options)); Ensure.IsNotNull(session, nameof(session)); + Ensure.IsNotNull(operation, nameof(operation)); + Ensure.IsNullOrValidTimeout(timeout, nameof(timeout)); ThrowIfDisposed(); - using var operationContext = options.ToOperationContext(cancellationToken); + using var operationContext = new OperationContext(timeout, cancellationToken); using var binding = CreateReadWriteBinding(session, allowChannelPinning); return operation.Execute(operationContext, binding); } @@ -94,16 +96,16 @@ public TResult ExecuteWriteOperation( public async Task ExecuteWriteOperationAsync( IClientSessionHandle session, IWriteOperation operation, - WriteOperationOptions options, bool allowChannelPinning, + TimeSpan? timeout, CancellationToken cancellationToken) { - Ensure.IsNotNull(operation, nameof(operation)); - Ensure.IsNotNull(options, nameof(options)); Ensure.IsNotNull(session, nameof(session)); + Ensure.IsNotNull(operation, nameof(operation)); + Ensure.IsNullOrValidTimeout(timeout, nameof(timeout)); ThrowIfDisposed(); - using var operationContext = options.ToOperationContext(cancellationToken); + using var operationContext = new OperationContext(timeout, cancellationToken); using var binding = CreateReadWriteBinding(session, allowChannelPinning); return await operation.ExecuteAsync(operationContext, binding).ConfigureAwait(false); } diff --git a/src/MongoDB.Driver/ReadOperationOptions.cs b/src/MongoDB.Driver/ReadOperationOptions.cs deleted file mode 100644 index baba0248e8f..00000000000 --- a/src/MongoDB.Driver/ReadOperationOptions.cs +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright 2010-present MongoDB Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -namespace MongoDB.Driver -{ - internal record ReadOperationOptions(TimeSpan Timeout, ReadPreference ExplicitReadPreference = null, ReadPreference DefaultReadPreference = null) - : OperationOptionsBase(Timeout); - - internal static class ReadOperationOptionsExtensions - { - public static ReadPreference GetEffectiveReadPreference(this ReadOperationOptions options, IClientSessionHandle session) - { - if (options.ExplicitReadPreference != null) - { - return options.ExplicitReadPreference; - } - - if (session.IsInTransaction) - { - var transactionReadPreference = session.WrappedCoreSession.CurrentTransaction.TransactionOptions.ReadPreference; - if (transactionReadPreference != null) - { - return transactionReadPreference; - } - } - - return options.DefaultReadPreference ?? ReadPreference.Primary; - } - } -} - diff --git a/src/MongoDB.Driver/RenameCollectionOptions.cs b/src/MongoDB.Driver/RenameCollectionOptions.cs index e319db23f4a..7f551757803 100644 --- a/src/MongoDB.Driver/RenameCollectionOptions.cs +++ b/src/MongoDB.Driver/RenameCollectionOptions.cs @@ -13,6 +13,9 @@ * limitations under the License. */ +using System; +using MongoDB.Driver.Core.Misc; + namespace MongoDB.Driver { /// @@ -22,6 +25,7 @@ public class RenameCollectionOptions { // fields private bool? _dropTarget; + private TimeSpan? _timeout; // properties /// @@ -32,5 +36,14 @@ public bool? DropTarget get { return _dropTarget; } set { _dropTarget = value; } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } } diff --git a/src/MongoDB.Driver/WriteOperationOptions.cs b/src/MongoDB.Driver/WriteOperationOptions.cs deleted file mode 100644 index f141c2ebc39..00000000000 --- a/src/MongoDB.Driver/WriteOperationOptions.cs +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright 2010-present MongoDB Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -namespace MongoDB.Driver -{ - internal record WriteOperationOptions(TimeSpan Timeout) - : OperationOptionsBase(Timeout); -} - diff --git a/tests/MongoDB.Driver.Tests/ReadOperationOptionsTests.cs b/tests/MongoDB.Driver.Tests/ClientSessionExtensionsTests.cs similarity index 65% rename from tests/MongoDB.Driver.Tests/ReadOperationOptionsTests.cs rename to tests/MongoDB.Driver.Tests/ClientSessionExtensionsTests.cs index eab234fa94b..6758dff71a7 100644 --- a/tests/MongoDB.Driver.Tests/ReadOperationOptionsTests.cs +++ b/tests/MongoDB.Driver.Tests/ClientSessionExtensionsTests.cs @@ -14,7 +14,6 @@ */ using System.Collections.Generic; -using System.Threading; using FluentAssertions; using MongoDB.Driver.Core.Bindings; using Moq; @@ -22,18 +21,16 @@ namespace MongoDB.Driver.Tests { - public class ReadOperationOptionsTests + public class ClientSessionExtensionsTests { [Theory] [MemberData(nameof(GetEffectiveReadPreferenceTestCases))] public void GetEffectiveReadPreferenceTests( ReadPreference expectedReadPreference, - ReadPreference explicitReadPreference, ReadPreference defaultReadPreference, IClientSessionHandle session) { - var readOperationOptions = new ReadOperationOptions(Timeout.InfiniteTimeSpan, explicitReadPreference, defaultReadPreference); - var result = readOperationOptions.GetEffectiveReadPreference(session); + var result = session.GetEffectiveReadPreference(defaultReadPreference); result.Should().Be(expectedReadPreference); } @@ -44,13 +41,13 @@ public static IEnumerable GetEffectiveReadPreferenceTestCases() var inTransactionSession = CreateSessionMock(new TransactionOptions(readPreference: ReadPreference.Nearest)); var inTransactionNoPreferenceSession = CreateSessionMock(new TransactionOptions()); - yield return [ReadPreference.Primary, null, null, noTransactionSession]; - yield return [ReadPreference.Secondary, ReadPreference.Secondary, ReadPreference.SecondaryPreferred, noTransactionSession]; - yield return [ReadPreference.Secondary, ReadPreference.Secondary, ReadPreference.SecondaryPreferred, inTransactionSession]; - yield return [ReadPreference.SecondaryPreferred, null, ReadPreference.SecondaryPreferred, noTransactionSession]; - yield return [ReadPreference.Nearest, null, ReadPreference.SecondaryPreferred, inTransactionSession]; - yield return [ReadPreference.Primary, null, null, inTransactionNoPreferenceSession]; - yield return [ReadPreference.SecondaryPreferred, null, ReadPreference.SecondaryPreferred, inTransactionNoPreferenceSession]; + yield return [ReadPreference.Primary, null, noTransactionSession]; + yield return [ReadPreference.SecondaryPreferred, ReadPreference.SecondaryPreferred, noTransactionSession]; + + yield return [ReadPreference.Nearest, ReadPreference.SecondaryPreferred, inTransactionSession]; + + yield return [ReadPreference.Primary, null, inTransactionNoPreferenceSession]; + yield return [ReadPreference.SecondaryPreferred, ReadPreference.SecondaryPreferred, inTransactionNoPreferenceSession]; } private static IClientSessionHandle CreateSessionMock(TransactionOptions transactionOptions) diff --git a/tests/MongoDB.Driver.Tests/CreateManyIndexOptionsTest.cs b/tests/MongoDB.Driver.Tests/CreateManyIndexOptionsTest.cs index 5ed06f04ce7..c58c0aac891 100644 --- a/tests/MongoDB.Driver.Tests/CreateManyIndexOptionsTest.cs +++ b/tests/MongoDB.Driver.Tests/CreateManyIndexOptionsTest.cs @@ -1,4 +1,4 @@ -/* Copyright 2018-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,6 +48,7 @@ public void CommitQuorum_set_should_have_expected_result( subject.CommitQuorum.Should().Be(commitQuorum); } +#pragma warning disable CS0618 // Type or member is obsolete [Fact] public void MaxTime_get_should_return_expected_result() { @@ -84,7 +85,7 @@ public void MaxTime_set_should_throw_when_value_is_invalid( var e = exception.Should().BeOfType().Subject; e.ParamName.Should().Be("value"); } - +#pragma warning restore CS0618 // Type or member is obsolete } } diff --git a/tests/MongoDB.Driver.Tests/CreateOneIndexOptionsTest.cs b/tests/MongoDB.Driver.Tests/CreateOneIndexOptionsTest.cs index e0b8d0dd4f2..73871f3fced 100644 --- a/tests/MongoDB.Driver.Tests/CreateOneIndexOptionsTest.cs +++ b/tests/MongoDB.Driver.Tests/CreateOneIndexOptionsTest.cs @@ -1,4 +1,4 @@ -/* Copyright 2018-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,6 +48,7 @@ public void CommitQuorum_set_should_have_expected_result( subject.CommitQuorum.Should().Be(commitQuorum); } +#pragma warning disable CS0618 // Type or member is obsolete [Fact] public void MaxTime_get_should_return_expected_result() { @@ -84,7 +85,7 @@ public void MaxTime_set_should_throw_when_value_is_invalid( var e = exception.Should().BeOfType().Subject; e.ParamName.Should().Be("value"); } - +#pragma warning restore CS0618 // Type or member is obsolete } } diff --git a/tests/MongoDB.Driver.Tests/DropIndexOptionsTest.cs b/tests/MongoDB.Driver.Tests/DropIndexOptionsTest.cs index 39933afe653..a37258c8a96 100644 --- a/tests/MongoDB.Driver.Tests/DropIndexOptionsTest.cs +++ b/tests/MongoDB.Driver.Tests/DropIndexOptionsTest.cs @@ -1,4 +1,4 @@ -/* Copyright 2016-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ namespace MongoDB.Driver.Tests { public class DropIndexOptionsTest { +#pragma warning disable CS0618 // Type or member is obsolete [Fact] public void MaxTime_get_should_return_expected_result() { @@ -57,6 +58,8 @@ public void MaxTime_set_should_throw_when_value_is_invalid( var e = exception.Should().BeOfType().Subject; e.ParamName.Should().Be("value"); } + +#pragma warning restore CS0618 // Type or member is obsolete } } diff --git a/tests/MongoDB.Driver.Tests/EstimatedDocumentCountOptionsTests.cs b/tests/MongoDB.Driver.Tests/EstimatedDocumentCountOptionsTests.cs index dae0b51ff0b..e981d171b3c 100644 --- a/tests/MongoDB.Driver.Tests/EstimatedDocumentCountOptionsTests.cs +++ b/tests/MongoDB.Driver.Tests/EstimatedDocumentCountOptionsTests.cs @@ -1,4 +1,4 @@ -/* Copyright 2018-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,9 +28,12 @@ public void constructor_should_initialize_instance() var result = new EstimatedDocumentCountOptions(); result.Comment.Should().BeNull(); +#pragma warning disable CS0618 // Type or member is obsolete result.MaxTime.Should().NotHaveValue(); +#pragma warning restore CS0618 // Type or member is obsolete } +#pragma warning disable CS0618 // Type or member is obsolete [Theory] [ParameterAttributeData] public void MaxTime_get_should_return_expected_result( @@ -56,5 +59,6 @@ public void MaxTime_set_should_have_expected_result( subject.MaxTime.Should().Be(value); } +#pragma warning restore CS0618 // Type or member is obsolete } } diff --git a/tests/MongoDB.Driver.Tests/FindFluentTests.cs b/tests/MongoDB.Driver.Tests/FindFluentTests.cs index 78faff1ec9b..3e3a4c27aa6 100644 --- a/tests/MongoDB.Driver.Tests/FindFluentTests.cs +++ b/tests/MongoDB.Driver.Tests/FindFluentTests.cs @@ -20,8 +20,6 @@ using MongoDB.Bson; using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Serializers; -using MongoDB.Driver.Core.Misc; -using MongoDB.Driver.Core.TestHelpers.XunitExtensions; using MongoDB.TestHelpers.XunitExtensions; using Moq; using Xunit; @@ -87,7 +85,9 @@ public void Count_should_call_collection_Count( Collation = new Collation("en-us"), Hint = hint, Limit = 1, +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = TimeSpan.FromSeconds(2), +#pragma warning restore CS0618 // Type or member is obsolete Skip = 3 }; var subject = CreateSubject(session: session, filter: filter, options: findOptions); @@ -98,7 +98,9 @@ public void Count_should_call_collection_Count( countOptions.Collation.Equals(findOptions.Collation) && countOptions.Hint.Equals(hint) && countOptions.Limit.Equals((long?)findOptions.Limit) && +#pragma warning disable CS0618 // Type or member is obsolete countOptions.MaxTime.Equals(findOptions.MaxTime) && +#pragma warning restore CS0618 // Type or member is obsolete countOptions.Skip.Equals((long?)findOptions.Skip); if (async) @@ -173,7 +175,9 @@ public void CountDocuments_should_call_collection_CountDocuments( Collation = new Collation("en-us"), Hint = hint, Limit = 1, +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = TimeSpan.FromSeconds(2), +#pragma warning restore CS0618 // Type or member is obsolete Skip = 3 }; var subject = CreateSubject(session: session, filter: filter, options: findOptions); @@ -184,7 +188,9 @@ public void CountDocuments_should_call_collection_CountDocuments( countOptions.Collation.Equals(findOptions.Collation) && countOptions.Hint.Equals(hint) && countOptions.Limit.Equals((long?)findOptions.Limit) && +#pragma warning disable CS0618 // Type or member is obsolete countOptions.MaxTime.Equals(findOptions.MaxTime) && +#pragma warning restore CS0618 // Type or member is obsolete countOptions.Skip.Equals((long?)findOptions.Skip); if (async) @@ -309,7 +315,9 @@ public void ToString_should_return_the_correct_string() subject.Options.Comment = "awesome"; subject.Options.Hint = "x_3"; subject.Options.Max = new BsonDocument("max", 5); +#pragma warning disable CS0618 // Type or member is obsolete subject.Options.MaxTime = TimeSpan.FromSeconds(2); +#pragma warning restore CS0618 // Type or member is obsolete subject.Options.Min = new BsonDocument("min", 2); subject.Options.ReturnKey = true; subject.Options.ShowRecordId = true; diff --git a/tests/MongoDB.Driver.Tests/IMongoCollectionExtensionsTests.cs b/tests/MongoDB.Driver.Tests/IMongoCollectionExtensionsTests.cs index a65cf915b5c..6eb59135e2b 100644 --- a/tests/MongoDB.Driver.Tests/IMongoCollectionExtensionsTests.cs +++ b/tests/MongoDB.Driver.Tests/IMongoCollectionExtensionsTests.cs @@ -609,7 +609,9 @@ public void Find_should_return_expected_result( Comment = "comment", CursorType = CursorType.Tailable, MaxAwaitTime = TimeSpan.FromSeconds(1), +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = TimeSpan.FromSeconds(2), +#pragma warning restore CS0618 // Type or member is obsolete NoCursorTimeout = true, #pragma warning disable 618 OplogReplay = true @@ -659,7 +661,9 @@ public void Find_should_return_expected_result( actualOptions.Comment.Should().Be(options.Comment); actualOptions.CursorType.Should().Be(options.CursorType); actualOptions.MaxAwaitTime.Should().Be(options.MaxAwaitTime); +#pragma warning disable CS0618 // Type or member is obsolete actualOptions.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete actualOptions.NoCursorTimeout.Should().Be(options.NoCursorTimeout); #pragma warning disable 618 actualOptions.OplogReplay.Should().Be(options.OplogReplay); diff --git a/tests/MongoDB.Driver.Tests/JsonDrivenTests/JsonDrivenAggregateTest.cs b/tests/MongoDB.Driver.Tests/JsonDrivenTests/JsonDrivenAggregateTest.cs index 19bbd216e9c..fc6db6ff3d6 100644 --- a/tests/MongoDB.Driver.Tests/JsonDrivenTests/JsonDrivenAggregateTest.cs +++ b/tests/MongoDB.Driver.Tests/JsonDrivenTests/JsonDrivenAggregateTest.cs @@ -1,4 +1,4 @@ -/* Copyright 2018-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -96,7 +96,9 @@ protected override void SetArgument(string name, BsonValue value) return; case "maxTimeMS": +#pragma warning disable CS0618 // Type or member is obsolete _options.MaxTime = TimeSpan.FromMilliseconds(value.ToInt32()); +#pragma warning restore CS0618 // Type or member is obsolete return; } diff --git a/tests/MongoDB.Driver.Tests/MockOperationExecutor.cs b/tests/MongoDB.Driver.Tests/MockOperationExecutor.cs index 6abf665a10e..b4702eaae5b 100644 --- a/tests/MongoDB.Driver.Tests/MockOperationExecutor.cs +++ b/tests/MongoDB.Driver.Tests/MockOperationExecutor.cs @@ -65,16 +65,18 @@ public void EnqueueException(Exception exception) public TResult ExecuteReadOperation( IClientSessionHandle session, IReadOperation operation, - ReadOperationOptions readOperationOptions, + ReadPreference readPreference, bool allowChannelPinning, + TimeSpan? timeout, CancellationToken cancellationToken) { _calls.Enqueue(new ReadCall { Operation = operation, CancellationToken = cancellationToken, - Options = readOperationOptions, + ReadPreference = readPreference, SessionId = session?.WrappedCoreSession.Id, + Timeout = timeout, UsedImplicitSession = session == null || session.IsImplicit }); @@ -97,13 +99,14 @@ public TResult ExecuteReadOperation( public Task ExecuteReadOperationAsync( IClientSessionHandle session, IReadOperation operation, - ReadOperationOptions readOperationOptions, + ReadPreference readPreference, bool allowChannelPinning, + TimeSpan? timeout, CancellationToken cancellationToken) { try { - var result = ExecuteReadOperation(session, operation, readOperationOptions, allowChannelPinning, cancellationToken); + var result = ExecuteReadOperation(session, operation, readPreference, allowChannelPinning, timeout, cancellationToken); return Task.FromResult(result); } catch (Exception ex) @@ -117,16 +120,16 @@ public Task ExecuteReadOperationAsync( public TResult ExecuteWriteOperation( IClientSessionHandle session, IWriteOperation operation, - WriteOperationOptions writeOperationOptions, bool allowChannelPinning, + TimeSpan? timeout, CancellationToken cancellationToken) { _calls.Enqueue(new WriteCall { Operation = operation, CancellationToken = cancellationToken, - Options = writeOperationOptions, SessionId = session?.WrappedCoreSession.Id, + Timeout = timeout, UsedImplicitSession = session == null || session.IsImplicit }); @@ -149,13 +152,13 @@ public TResult ExecuteWriteOperation( public Task ExecuteWriteOperationAsync( IClientSessionHandle session, IWriteOperation operation, - WriteOperationOptions writeOperationOptions, bool allowChannelPinning, + TimeSpan? timeout, CancellationToken cancellationToken) { try { - var result = ExecuteWriteOperation(session, operation, writeOperationOptions, allowChannelPinning, cancellationToken); + var result = ExecuteWriteOperation(session, operation, allowChannelPinning, timeout, cancellationToken); return Task.FromResult(result); } catch (Exception ex) @@ -214,8 +217,9 @@ public class ReadCall { public IReadOperation Operation { get; set; } public CancellationToken CancellationToken { get; set; } - public ReadOperationOptions Options { get; set; } + public ReadPreference ReadPreference { get; set; } public BsonDocument SessionId { get; set; } + public TimeSpan? Timeout { get; set; } public bool UsedImplicitSession { get; set; } } @@ -223,8 +227,8 @@ public class WriteCall { public IWriteOperation Operation { get; set; } public CancellationToken CancellationToken { get; set; } - public WriteOperationOptions Options { get; set; } public BsonDocument SessionId { get; set; } + public TimeSpan? Timeout { get; set; } public bool UsedImplicitSession { get; set; } } } diff --git a/tests/MongoDB.Driver.Tests/MongoCollectionImplTests.cs b/tests/MongoDB.Driver.Tests/MongoCollectionImplTests.cs index d89660af55e..c5f3e397ec8 100644 --- a/tests/MongoDB.Driver.Tests/MongoCollectionImplTests.cs +++ b/tests/MongoDB.Driver.Tests/MongoCollectionImplTests.cs @@ -91,8 +91,8 @@ public void Aggregate_should_execute_an_AggregateOperation_when_out_is_not_speci Hint = new BsonDocument("x", 1), Let = new BsonDocument("y", "z"), MaxAwaitTime = TimeSpan.FromSeconds(4), - MaxTime = TimeSpan.FromSeconds(3), #pragma warning disable 618 + MaxTime = TimeSpan.FromSeconds(3), UseCursor = false #pragma warning restore 618 }; @@ -135,7 +135,9 @@ public void Aggregate_should_execute_an_AggregateOperation_when_out_is_not_speci operation.Hint.Should().Be(options.Hint); operation.Let.Should().Be(options.Let); operation.MaxAwaitTime.Should().Be(options.MaxAwaitTime); +#pragma warning disable CS0618 // Type or member is obsolete operation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete operation.Pipeline.Should().Equal(renderedPipeline.Documents); operation.ReadConcern.Should().Be(_readConcern); operation.RetryRequested.Should().BeTrue(); @@ -171,8 +173,8 @@ public void Aggregate_should_execute_an_AggregateToCollectionOperation_and_a_Fin Comment = "test", Hint = new BsonDocument("x", 1), Let = new BsonDocument("y", "z"), - MaxTime = TimeSpan.FromSeconds(3), #pragma warning disable 618 + MaxTime = TimeSpan.FromSeconds(3), UseCursor = false #pragma warning restore 618 }; @@ -223,7 +225,9 @@ public void Aggregate_should_execute_an_AggregateToCollectionOperation_and_a_Fin aggregateOperation.Comment.Should().Be(options.Comment); aggregateOperation.Hint.Should().Be(options.Hint); aggregateOperation.Let.Should().Be(options.Let); +#pragma warning disable CS0618 // Type or member is obsolete aggregateOperation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete aggregateOperation.Pipeline.Should().Equal(expectedPipeline); aggregateOperation.ReadConcern.Should().Be(readConcern); aggregateOperation.WriteConcern.Should().BeSameAs(writeConcern); @@ -253,7 +257,9 @@ public void Aggregate_should_execute_an_AggregateToCollectionOperation_and_a_Fin findOperation.CursorType.Should().Be(CursorType.NonTailable); findOperation.Filter.Should().BeNull(); findOperation.Limit.Should().Be(null); +#pragma warning disable CS0618 // Type or member is obsolete findOperation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete findOperation.NoCursorTimeout.Should().NotHaveValue(); #pragma warning disable 618 findOperation.OplogReplay.Should().NotHaveValue(); @@ -346,8 +352,8 @@ public void AggregateToCollection_should_execute_an_AggregateToCollectionOperati Comment = "test", Hint = new BsonDocument("x", 1), Let = new BsonDocument("y", "z"), - MaxTime = TimeSpan.FromSeconds(3), #pragma warning disable 618 + MaxTime = TimeSpan.FromSeconds(3), UseCursor = false #pragma warning restore 618 }; @@ -393,7 +399,9 @@ public void AggregateToCollection_should_execute_an_AggregateToCollectionOperati aggregateOperation.Comment.Should().Be(options.Comment); aggregateOperation.Hint.Should().Be(options.Hint); aggregateOperation.Let.Should().Be(options.Let); +#pragma warning disable CS0618 // Type or member is obsolete aggregateOperation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete aggregateOperation.Pipeline.Should().Equal(expectedPipeline); aggregateOperation.ReadConcern.Should().Be(readConcern); aggregateOperation.WriteConcern.Should().BeSameAs(writeConcern); @@ -769,7 +777,9 @@ public void Count_should_execute_a_CountOperation( Collation = new Collation("en_US"), Hint = "funny", Limit = 10, +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = TimeSpan.FromSeconds(20), +#pragma warning restore CS0618 // Type or member is obsolete Skip = 30 }; using var cancellationTokenSource = new CancellationTokenSource(); @@ -815,7 +825,9 @@ public void Count_should_execute_a_CountOperation( operation.Filter.Should().Be(filter); operation.Hint.Should().Be(options.Hint); operation.Limit.Should().Be(options.Limit); +#pragma warning disable CS0618 // Type or member is obsolete operation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete operation.ReadConcern.Should().Be(_readConcern); operation.RetryRequested.Should().BeTrue(); operation.Skip.Should().Be(options.Skip); @@ -835,7 +847,9 @@ public void CountDocuments_should_execute_a_CountDocumentsOperation( Collation = new Collation("en_US"), Hint = "funny", Limit = 10, +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = TimeSpan.FromSeconds(20), +#pragma warning restore CS0618 // Type or member is obsolete Skip = 30 }; using var cancellationTokenSource = new CancellationTokenSource(); @@ -873,7 +887,9 @@ public void CountDocuments_should_execute_a_CountDocumentsOperation( operation.Filter.Should().Be(filter); operation.Hint.Should().Be(options.Hint); operation.Limit.Should().Be(options.Limit); +#pragma warning disable CS0618 // Type or member is obsolete operation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete operation.ReadConcern.Should().Be(_readConcern); operation.RetryRequested.Should().BeTrue(); operation.Skip.Should().Be(options.Skip); @@ -1118,7 +1134,9 @@ public void Distinct_should_execute_a_DistinctOperation( var options = new DistinctOptions { Collation = new Collation("en_US"), +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = TimeSpan.FromSeconds(20) +#pragma warning restore CS0618 // Type or member is obsolete }; using var cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; @@ -1154,7 +1172,9 @@ public void Distinct_should_execute_a_DistinctOperation( operation.CollectionNamespace.Should().Be(subject.CollectionNamespace); operation.FieldName.Should().Be(fieldName); operation.Filter.Should().Be(filterDocument); +#pragma warning disable CS0618 // Type or member is obsolete operation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete operation.ReadConcern.Should().Be(_readConcern); operation.RetryRequested.Should().BeTrue(); operation.ValueSerializer.ValueType.Should().Be(typeof(int)); @@ -1184,7 +1204,9 @@ public void Distinct_should_execute_a_DistinctOperation_when_type_parameter_is_a var options = new DistinctOptions { Collation = new Collation("en_US"), +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = TimeSpan.FromSeconds(20) +#pragma warning restore CS0618 // Type or member is obsolete }; using var cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; @@ -1220,7 +1242,9 @@ public void Distinct_should_execute_a_DistinctOperation_when_type_parameter_is_a operation.CollectionNamespace.Should().Be(subject.CollectionNamespace); operation.FieldName.Should().Be(fieldName); operation.Filter.Should().Be(filterDocument); +#pragma warning disable CS0618 // Type or member is obsolete operation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete operation.ReadConcern.Should().Be(_readConcern); operation.RetryRequested.Should().BeTrue(); @@ -1246,7 +1270,9 @@ public void Distinct_should_execute_a_DistinctOperation_when_type_parameter_is_s var options = new DistinctOptions { Collation = new Collation("en_US"), +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = TimeSpan.FromSeconds(20) +#pragma warning restore CS0618 // Type or member is obsolete }; using var cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; @@ -1282,7 +1308,9 @@ public void Distinct_should_execute_a_DistinctOperation_when_type_parameter_is_s operation.CollectionNamespace.Should().Be(subject.CollectionNamespace); operation.FieldName.Should().Be(fieldName); operation.Filter.Should().Be(filterDocument); +#pragma warning disable CS0618 // Type or member is obsolete operation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete operation.ReadConcern.Should().Be(_readConcern); operation.RetryRequested.Should().BeTrue(); @@ -1310,7 +1338,9 @@ public void DistinctMany_should_execute_a_DistinctOperation_when_type_parameter_ var options = new DistinctOptions { Collation = new Collation("en_US"), +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = TimeSpan.FromSeconds(20) +#pragma warning restore CS0618 // Type or member is obsolete }; using var cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; @@ -1346,7 +1376,9 @@ public void DistinctMany_should_execute_a_DistinctOperation_when_type_parameter_ operation.CollectionNamespace.Should().Be(subject.CollectionNamespace); operation.FieldName.Should().Be(fieldName); operation.Filter.Should().Be(filterDocument); +#pragma warning disable CS0618 // Type or member is obsolete operation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete operation.ReadConcern.Should().Be(_readConcern); operation.RetryRequested.Should().BeTrue(); @@ -1364,7 +1396,9 @@ public void EstimatedDocumentCount_should_execute_an_EstimatedDocumentCount_oper var subject = CreateSubject(); var options = new EstimatedDocumentCountOptions { +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = TimeSpan.FromSeconds(20) +#pragma warning restore CS0618 // Type or member is obsolete }; using var cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; @@ -1383,7 +1417,9 @@ public void EstimatedDocumentCount_should_execute_an_EstimatedDocumentCount_oper var operation = call.Operation.Should().BeOfType().Subject; operation.CollectionNamespace.Should().Be(subject.CollectionNamespace); +#pragma warning disable CS0618 // Type or member is obsolete operation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete operation.ReadConcern.Should().Be(ReadConcern.Default); operation.RetryRequested.Should().BeTrue(); } @@ -1415,7 +1451,9 @@ public void Find_should_execute_a_FindOperation( Let = letDocument, Limit = 30, MaxAwaitTime = TimeSpan.FromSeconds(4), +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = TimeSpan.FromSeconds(3), +#pragma warning restore CS0618 // Type or member is obsolete NoCursorTimeout = true, #pragma warning disable 618 OplogReplay = true, @@ -1466,7 +1504,9 @@ public void Find_should_execute_a_FindOperation( operation.Let.Should().Be(options.Let); operation.Limit.Should().Be(options.Limit); operation.MaxAwaitTime.Should().Be(options.MaxAwaitTime); +#pragma warning disable CS0618 // Type or member is obsolete operation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete operation.NoCursorTimeout.Should().Be(options.NoCursorTimeout); #pragma warning disable 618 operation.OplogReplay.Should().Be(options.OplogReplay); @@ -1504,7 +1544,9 @@ public void Find_with_an_expression_execute_a_FindOperation( Let = letDocument, Limit = 30, MaxAwaitTime = TimeSpan.FromSeconds(4), +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = TimeSpan.FromSeconds(3), +#pragma warning restore CS0618 // Type or member is obsolete NoCursorTimeout = true, #pragma warning disable 618 OplogReplay = true, @@ -1554,7 +1596,9 @@ public void Find_with_an_expression_execute_a_FindOperation( operation.Let.Should().Be(options.Let); operation.Limit.Should().Be(options.Limit); operation.MaxAwaitTime.Should().Be(options.MaxAwaitTime); +#pragma warning disable CS0618 // Type or member is obsolete operation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete operation.NoCursorTimeout.Should().Be(options.NoCursorTimeout); #pragma warning disable 618 operation.OplogReplay.Should().Be(options.OplogReplay); @@ -1640,7 +1684,9 @@ public void FindOneAndDelete_should_execute_a_FindOneAndDeleteOperation( Let = letDocument, Projection = projectionDefinition, Sort = sortDefinition, +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = TimeSpan.FromSeconds(2) +#pragma warning restore CS0618 // Type or member is obsolete }; using var cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; @@ -1676,7 +1722,9 @@ public void FindOneAndDelete_should_execute_a_FindOneAndDeleteOperation( operation.CollectionNamespace.Should().Be(subject.CollectionNamespace); operation.Filter.Should().Be(filterDocument); operation.Let.Should().Be(letDocument); +#pragma warning disable CS0618 // Type or member is obsolete operation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete operation.Projection.Should().Be(projectionDocument); operation.ResultSerializer.Should().BeOfType>(); operation.Sort.Should().Be(sortDocument); @@ -1764,7 +1812,9 @@ public void FindOneAndReplace_should_execute_a_FindOneAndReplaceOperation( Hint = new BsonDocument("_id", 1), IsUpsert = isUpsert, Let = letDocument, +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = TimeSpan.FromSeconds(2), +#pragma warning restore CS0618 // Type or member is obsolete Projection = projectionDefinition, ReturnDocument = returnDocument, Sort = sortDefinition @@ -1806,7 +1856,9 @@ public void FindOneAndReplace_should_execute_a_FindOneAndReplaceOperation( operation.Filter.Should().Be(filterDocument); operation.IsUpsert.Should().Be(isUpsert); operation.Let.Should().Be(options.Let); +#pragma warning disable CS0618 // Type or member is obsolete operation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete operation.Projection.Should().Be(projectionDocument); operation.Replacement.Should().Be(replacement); operation.ResultSerializer.Should().BeOfType>(); @@ -1899,7 +1951,9 @@ public void FindOneAndUpdate_should_execute_a_FindOneAndUpdateOperation( Hint = new BsonDocument("_id", 1), IsUpsert = isUpsert, Let = letDocument, +#pragma warning disable CS0618 // Type or member is obsolete MaxTime = TimeSpan.FromSeconds(2), +#pragma warning restore CS0618 // Type or member is obsolete Projection = projectionDefinition, ReturnDocument = returnDocument, Sort = sortDefinition, @@ -1942,7 +1996,9 @@ public void FindOneAndUpdate_should_execute_a_FindOneAndUpdateOperation( operation.Filter.Should().Be(filterDocument); operation.IsUpsert.Should().Be(isUpsert); operation.Let.Should().Be(options.Let); +#pragma warning disable CS0618 // Type or member is obsolete operation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete operation.Projection.Should().Be(projectionDocument); operation.ResultSerializer.Should().BeOfType>(); operation.ReturnDocument.Should().Be(returnDocument); @@ -2061,7 +2117,13 @@ public void Indexes_CreateOne_should_execute_a_CreateIndexesOperation( var storageEngine = new BsonDocument("awesome", true); var commitQuorum = commitQuorumW.HasValue ? CreateIndexCommitQuorum.Create(commitQuorumW.Value) : null; var maxTime = milliseconds != null ? TimeSpan.FromMilliseconds(milliseconds.Value) : (TimeSpan?)null; - var createOneIndexOptions = usingCreateOneIndexOptions ? new CreateOneIndexOptions { CommitQuorum = commitQuorum, MaxTime = maxTime } : null; + var createOneIndexOptions = usingCreateOneIndexOptions ? new CreateOneIndexOptions + { + CommitQuorum = commitQuorum, +#pragma warning disable CS0618 // Type or member is obsolete + MaxTime = maxTime +#pragma warning restore CS0618 // Type or member is obsolete + } : null; var wildcardProjectionDefinition = Builders.Projection.Include("w"); var options = new CreateIndexOptions { @@ -2125,7 +2187,9 @@ public void Indexes_CreateOne_should_execute_a_CreateIndexesOperation( var operation = call.Operation.Should().BeOfType().Subject; operation.CollectionNamespace.FullName.Should().Be("foo.bar"); operation.CommitQuorum.Should().BeSameAs(createOneIndexOptions?.CommitQuorum); +#pragma warning disable CS0618 // Type or member is obsolete operation.MaxTime.Should().Be(createOneIndexOptions?.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete operation.Requests.Count().Should().Be(1); operation.WriteConcern.Should().BeSameAs(writeConcern); @@ -2197,7 +2261,13 @@ public void Indexes_CreateMany_should_execute_a_CreateIndexesOperation( var storageEngine = new BsonDocument("awesome", true); var commitQuorum = commitQuorumW.HasValue ? CreateIndexCommitQuorum.Create(commitQuorumW.Value) : null; var maxTime = milliseconds != null ? TimeSpan.FromMilliseconds(milliseconds.Value) : (TimeSpan?)null; - var createManyIndexesOptions = usingCreateManyIndexesOptions ? new CreateManyIndexesOptions { CommitQuorum = commitQuorum, MaxTime = maxTime } : null; + var createManyIndexesOptions = usingCreateManyIndexesOptions ? new CreateManyIndexesOptions + { + CommitQuorum = commitQuorum, +#pragma warning disable CS0618 // Type or member is obsolete + MaxTime = maxTime +#pragma warning restore CS0618 // Type or member is obsolete + } : null; var options = new CreateIndexOptions { @@ -2262,7 +2332,9 @@ public void Indexes_CreateMany_should_execute_a_CreateIndexesOperation( var operation = call.Operation.Should().BeOfType().Subject; operation.CollectionNamespace.Should().Be(subject.CollectionNamespace); operation.CommitQuorum.Should().BeSameAs(createManyIndexesOptions?.CommitQuorum); +#pragma warning disable CS0618 // Type or member is obsolete operation.MaxTime.Should().Be(createManyIndexesOptions?.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete operation.Requests.Count().Should().Be(2); operation.WriteConcern.Should().BeSameAs(writeConcern); @@ -2346,7 +2418,12 @@ public void Indexes_DropAll_should_execute_a_DropIndexOperation( using var cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; var maxTime = TimeSpan.FromMilliseconds(42); - var options = new DropIndexOptions { MaxTime = maxTime }; + var options = new DropIndexOptions + { +#pragma warning disable CS0618 // Type or member is obsolete + MaxTime = maxTime +#pragma warning restore CS0618 // Type or member is obsolete + }; if (usingSession) { @@ -2377,7 +2454,9 @@ public void Indexes_DropAll_should_execute_a_DropIndexOperation( var operation = call.Operation.Should().BeOfType().Subject; operation.CollectionNamespace.Should().Be(subject.CollectionNamespace); operation.IndexName.Should().Be("*"); +#pragma warning disable CS0618 // Type or member is obsolete operation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete operation.WriteConcern.Should().BeSameAs(writeConcern); } @@ -2393,7 +2472,12 @@ public void Indexes_DropOne_should_execute_a_DropIndexOperation( using var cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; var maxTime = TimeSpan.FromMilliseconds(42); - var options = new DropIndexOptions { MaxTime = maxTime }; + var options = new DropIndexOptions + { +#pragma warning disable CS0618 // Type or member is obsolete + MaxTime = maxTime +#pragma warning restore CS0618 // Type or member is obsolete + }; if (usingSession) { @@ -2821,8 +2905,8 @@ public void MapReduce_with_inline_output_mode_should_execute_a_MapReduceOperatio JavaScriptMode = true, #pragma warning restore 618 Limit = 10, - MaxTime = TimeSpan.FromMinutes(2), #pragma warning disable CS0618 // Type or member is obsolete + MaxTime = TimeSpan.FromMinutes(2), OutputOptions = MapReduceOutputOptions.Inline, #pragma warning restore CS0618 // Type or member is obsolete Scope = new BsonDocument("test", 3), @@ -2878,7 +2962,9 @@ public void MapReduce_with_inline_output_mode_should_execute_a_MapReduceOperatio #pragma warning restore 618 operation.Limit.Should().Be(options.Limit); operation.MapFunction.Should().Be(map); +#pragma warning disable CS0618 // Type or member is obsolete operation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete operation.ReadConcern.Should().Be(subject.Settings.ReadConcern); operation.ReduceFunction.Should().Be(reduce); operation.ResultSerializer.Should().Be(BsonDocumentSerializer.Instance); @@ -2914,8 +3000,8 @@ public void MapReduce_with_collection_output_mode_should_execute_a_MapReduceOutp JavaScriptMode = true, #pragma warning restore 618 Limit = 10, - MaxTime = TimeSpan.FromMinutes(2), #pragma warning disable 618 + MaxTime = TimeSpan.FromMinutes(2), OutputOptions = MapReduceOutputOptions.Replace("awesome", "otherDB", true), #pragma warning restore 618 Scope = new BsonDocument("test", 3), @@ -2972,8 +3058,8 @@ public void MapReduce_with_collection_output_mode_should_execute_a_MapReduceOutp #pragma warning restore 618 operation.Limit.Should().Be(options.Limit); operation.MapFunction.Should().Be(map); - operation.MaxTime.Should().Be(options.MaxTime); #pragma warning disable 618 + operation.MaxTime.Should().Be(options.MaxTime); operation.NonAtomicOutput.Should().NotHaveValue(); #pragma warning restore 618 operation.OutputCollectionNamespace.Should().Be(CollectionNamespace.FromFullName("otherDB.awesome")); diff --git a/tests/MongoDB.Driver.Tests/MongoDatabaseTests.cs b/tests/MongoDB.Driver.Tests/MongoDatabaseTests.cs index 9ca955ef522..0d1c5dbacac 100644 --- a/tests/MongoDB.Driver.Tests/MongoDatabaseTests.cs +++ b/tests/MongoDB.Driver.Tests/MongoDatabaseTests.cs @@ -86,8 +86,8 @@ public void Aggregate_should_execute_an_AggregateOperation_when_out_is_not_speci Hint = new BsonDocument("x", 1), Let = new BsonDocument("y", "z"), MaxAwaitTime = TimeSpan.FromSeconds(4), - MaxTime = TimeSpan.FromSeconds(3), #pragma warning disable 618 + MaxTime = TimeSpan.FromSeconds(3), UseCursor = false #pragma warning restore 618 }; @@ -131,7 +131,9 @@ public void Aggregate_should_execute_an_AggregateOperation_when_out_is_not_speci operation.Hint.Should().Be(options.Hint); operation.Let.Should().Be(options.Let); operation.MaxAwaitTime.Should().Be(options.MaxAwaitTime); +#pragma warning disable CS0618 // Type or member is obsolete operation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete operation.Pipeline.Should().Equal(renderedPipeline.Documents); operation.ReadConcern.Should().Be(subject.Settings.ReadConcern); operation.RetryRequested.Should().BeTrue(); @@ -165,8 +167,8 @@ public void Aggregate_should_execute_an_AggregateToCollectionOperation_and_a_Fin Comment = "test", Hint = new BsonDocument("x", 1), Let = new BsonDocument("y", "z"), - MaxTime = TimeSpan.FromSeconds(3), #pragma warning disable 618 + MaxTime = TimeSpan.FromSeconds(3), UseCursor = false #pragma warning restore 618 }; @@ -214,7 +216,9 @@ public void Aggregate_should_execute_an_AggregateToCollectionOperation_and_a_Fin aggregateOperation.DatabaseNamespace.Should().BeSameAs(subject.DatabaseNamespace); aggregateOperation.Hint.Should().Be(options.Hint); aggregateOperation.Let.Should().Be(options.Let); +#pragma warning disable CS0618 // Type or member is obsolete aggregateOperation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete aggregateOperation.Pipeline.Should().Equal(expectedPipeline); aggregateOperation.WriteConcern.Should().BeSameAs(writeConcern); @@ -243,7 +247,9 @@ public void Aggregate_should_execute_an_AggregateToCollectionOperation_and_a_Fin findOperation.CursorType.Should().Be(CursorType.NonTailable); findOperation.Filter.Should().BeNull(); findOperation.Limit.Should().Be(null); +#pragma warning disable CS0618 // Type or member is obsolete findOperation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete findOperation.NoCursorTimeout.Should().NotHaveValue(); #pragma warning disable 618 findOperation.OplogReplay.Should().NotHaveValue(); @@ -284,8 +290,8 @@ public void AggregateToCollection_should_execute_an_AggregateToCollectionOperati Comment = "test", Hint = new BsonDocument("x", 1), Let = new BsonDocument("y", "z"), - MaxTime = TimeSpan.FromSeconds(3), #pragma warning disable 618 + MaxTime = TimeSpan.FromSeconds(3), UseCursor = false #pragma warning restore 618 }; @@ -332,7 +338,9 @@ public void AggregateToCollection_should_execute_an_AggregateToCollectionOperati aggregateOperation.DatabaseNamespace.Should().BeSameAs(subject.DatabaseNamespace); aggregateOperation.Hint.Should().Be(options.Hint); aggregateOperation.Let.Should().Be(options.Let); +#pragma warning disable CS0618 // Type or member is obsolete aggregateOperation.MaxTime.Should().Be(options.MaxTime); +#pragma warning restore CS0618 // Type or member is obsolete aggregateOperation.Pipeline.Should().Equal(expectedPipeline); aggregateOperation.WriteConcern.Should().BeSameAs(writeConcern); } @@ -1087,8 +1095,7 @@ public void RunCommand_should_default_to_ReadPreference_primary( var call = _operationExecutor.GetReadCall(); VerifySessionAndCancellationToken(call, session, cancellationToken); - call.Options.ExplicitReadPreference.Should().BeNull(); - call.Options.DefaultReadPreference.Should().Be(ReadPreference.Primary); + call.ReadPreference.Should().Be(ReadPreference.Primary); var op = call.Operation.Should().BeOfType>().Subject; op.DatabaseNamespace.Should().Be(_subject.DatabaseNamespace); @@ -1134,8 +1141,7 @@ public void RunCommand_should_use_the_provided_ReadPreference( var call = _operationExecutor.GetReadCall(); VerifySessionAndCancellationToken(call, session, cancellationToken); - call.Options.ExplicitReadPreference.Should().Be(readPreference); - call.Options.DefaultReadPreference.Should().Be(ReadPreference.Primary); + call.ReadPreference.Should().Be(readPreference); var op = call.Operation.Should().BeOfType>().Subject; op.DatabaseNamespace.Should().Be(_subject.DatabaseNamespace); @@ -1180,8 +1186,7 @@ public void RunCommand_should_run_a_non_read_command( var call = _operationExecutor.GetReadCall(); VerifySessionAndCancellationToken(call, session, cancellationToken); - call.Options.ExplicitReadPreference.Should().BeNull(); - call.Options.DefaultReadPreference.Should().Be(ReadPreference.Primary); + call.ReadPreference.Should().Be(ReadPreference.Primary); var op = call.Operation.Should().BeOfType>().Subject; op.DatabaseNamespace.Should().Be(_subject.DatabaseNamespace); @@ -1226,8 +1231,7 @@ public void RunCommand_should_run_a_json_command( var call = _operationExecutor.GetReadCall(); VerifySessionAndCancellationToken(call, session, cancellationToken); - call.Options.ExplicitReadPreference.Should().BeNull(); - call.Options.DefaultReadPreference.Should().Be(ReadPreference.Primary); + call.ReadPreference.Should().Be(ReadPreference.Primary); var op = call.Operation.Should().BeOfType>().Subject; op.DatabaseNamespace.Should().Be(_subject.DatabaseNamespace); @@ -1272,8 +1276,7 @@ public void RunCommand_should_run_a_serialized_command( var call = _operationExecutor.GetReadCall(); VerifySessionAndCancellationToken(call, session, cancellationToken); - call.Options.ExplicitReadPreference.Should().BeNull(); - call.Options.DefaultReadPreference.Should().Be(ReadPreference.Primary); + call.ReadPreference.Should().Be(ReadPreference.Primary); var op = call.Operation.Should().BeOfType>().Subject; op.DatabaseNamespace.Should().Be(_subject.DatabaseNamespace); diff --git a/tests/MongoDB.Driver.Tests/OperationExecutorTests.cs b/tests/MongoDB.Driver.Tests/OperationExecutorTests.cs index 267d3db0620..3d683a7ac39 100644 --- a/tests/MongoDB.Driver.Tests/OperationExecutorTests.cs +++ b/tests/MongoDB.Driver.Tests/OperationExecutorTests.cs @@ -43,12 +43,11 @@ public void StartImplicitSession_should_call_cluster_StartSession() public async Task ExecuteReadOperation_throws_on_null_operation([Values(true, false)] bool async) { var subject = CreateSubject(out _); - var options = new ReadOperationOptions(Timeout.InfiniteTimeSpan); var session = Mock.Of(); var exception = async ? - await Record.ExceptionAsync(() => subject.ExecuteReadOperationAsync(session, null, options, true, CancellationToken.None)) : - Record.Exception(() => subject.ExecuteReadOperation(session, null, options, true, CancellationToken.None)); + await Record.ExceptionAsync(() => subject.ExecuteReadOperationAsync(session, null, ReadPreference.Primary, true, Timeout.InfiniteTimeSpan, CancellationToken.None)) : + Record.Exception(() => subject.ExecuteReadOperation(session, null, ReadPreference.Primary, true, Timeout.InfiniteTimeSpan, CancellationToken.None)); exception.Should().BeOfType() .Subject.ParamName.Should().Be("operation"); @@ -56,15 +55,15 @@ await Record.ExceptionAsync(() => subject.ExecuteReadOperationAsync(sess [Theory] [ParameterAttributeData] - public async Task ExecuteReadOperation_throws_on_null_options([Values(true, false)] bool async) + public async Task ExecuteReadOperation_throws_on_null_readPreference([Values(true, false)] bool async) { var subject = CreateSubject(out _); var operation = Mock.Of>(); var session = Mock.Of(); var exception = async ? - await Record.ExceptionAsync(() => subject.ExecuteReadOperationAsync(session, operation, null, true, CancellationToken.None)) : - Record.Exception(() => subject.ExecuteReadOperation(session, operation, null, true, CancellationToken.None)); + await Record.ExceptionAsync(() => subject.ExecuteReadOperationAsync(session, operation, null, true, Timeout.InfiniteTimeSpan, CancellationToken.None)) : + Record.Exception(() => subject.ExecuteReadOperation(session, operation, null, true, Timeout.InfiniteTimeSpan, CancellationToken.None)); exception.Should().BeOfType() .Subject.ParamName.Should().Be("options"); @@ -76,11 +75,10 @@ public async Task ExecuteReadOperation_throws_on_null_session([Values(true, fals { var subject = CreateSubject(out _); var operation = Mock.Of>(); - var options = new ReadOperationOptions(Timeout.InfiniteTimeSpan); var exception = async ? - await Record.ExceptionAsync(() => subject.ExecuteReadOperationAsync(null, operation, options, true, CancellationToken.None)) : - Record.Exception(() => subject.ExecuteReadOperation(null, operation, options, true, CancellationToken.None)); + await Record.ExceptionAsync(() => subject.ExecuteReadOperationAsync(null, operation, ReadPreference.Primary, true, Timeout.InfiniteTimeSpan, CancellationToken.None)) : + Record.Exception(() => subject.ExecuteReadOperation(null, operation, ReadPreference.Primary, true, Timeout.InfiniteTimeSpan, CancellationToken.None)); exception.Should().BeOfType() .Subject.ParamName.Should().Be("session"); @@ -91,44 +89,26 @@ await Record.ExceptionAsync(() => subject.ExecuteReadOperationAsync(null, operat public async Task ExecuteWriteOperation_throws_on_null_operation([Values(true, false)] bool async) { var subject = CreateSubject(out _); - var options = new WriteOperationOptions(Timeout.InfiniteTimeSpan); var session = Mock.Of(); var exception = async ? - await Record.ExceptionAsync(() => subject.ExecuteWriteOperationAsync(session, null, options, true, CancellationToken.None)) : - Record.Exception(() => subject.ExecuteWriteOperation(session, null, options, true, CancellationToken.None)); + await Record.ExceptionAsync(() => subject.ExecuteWriteOperationAsync(session, null, true, Timeout.InfiniteTimeSpan, CancellationToken.None)) : + Record.Exception(() => subject.ExecuteWriteOperation(session, null, true, Timeout.InfiniteTimeSpan, CancellationToken.None)); exception.Should().BeOfType() .Subject.ParamName.Should().Be("operation"); } - [Theory] - [ParameterAttributeData] - public async Task ExecuteWriteOperation_throws_on_null_options([Values(true, false)] bool async) - { - var subject = CreateSubject(out _); - var operation = Mock.Of>(); - var session = Mock.Of(); - - var exception = async ? - await Record.ExceptionAsync(() => subject.ExecuteWriteOperationAsync(session, operation, null, true, CancellationToken.None)) : - Record.Exception(() => subject.ExecuteWriteOperation(session, operation, null, true, CancellationToken.None)); - - exception.Should().BeOfType() - .Subject.ParamName.Should().Be("options"); - } - [Theory] [ParameterAttributeData] public async Task ExecuteWriteOperation_throws_on_null_session([Values(true, false)] bool async) { var subject = CreateSubject(out _); var operation = Mock.Of>(); - var options = new WriteOperationOptions(Timeout.InfiniteTimeSpan); var exception = async ? - await Record.ExceptionAsync(() => subject.ExecuteWriteOperationAsync(null, operation, options, true, CancellationToken.None)) : - Record.Exception(() => subject.ExecuteWriteOperation(null, operation, options, true, CancellationToken.None)); + await Record.ExceptionAsync(() => subject.ExecuteWriteOperationAsync(null, operation, true, Timeout.InfiniteTimeSpan, CancellationToken.None)) : + Record.Exception(() => subject.ExecuteWriteOperation(null, operation, true, Timeout.InfiniteTimeSpan, CancellationToken.None)); exception.Should().BeOfType() .Subject.ParamName.Should().Be("session"); diff --git a/tests/MongoDB.Driver.Tests/Specifications/crud/EstimatedDocumentCountTest.cs b/tests/MongoDB.Driver.Tests/Specifications/crud/EstimatedDocumentCountTest.cs index abb74cb4ed4..c7992726eab 100644 --- a/tests/MongoDB.Driver.Tests/Specifications/crud/EstimatedDocumentCountTest.cs +++ b/tests/MongoDB.Driver.Tests/Specifications/crud/EstimatedDocumentCountTest.cs @@ -1,4 +1,4 @@ -/* Copyright 2019-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -49,7 +49,9 @@ protected override bool TrySetArgument(string name, BsonValue value) switch (name) { case "limit": +#pragma warning disable CS0618 // Type or member is obsolete _options.MaxTime = new TimeSpan(value.ToInt64()); +#pragma warning restore CS0618 // Type or member is obsolete return true; } diff --git a/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedAggregateOperation.cs b/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedAggregateOperation.cs index 51f386691ef..c8a6aba3d2e 100644 --- a/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedAggregateOperation.cs +++ b/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedAggregateOperation.cs @@ -1,4 +1,4 @@ -/* Copyright 2020-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -202,7 +202,9 @@ private IUnifiedEntityTestOperation Build(IMongoDatabase database, IMongoCollect break; case "maxTimeMS": options ??= new AggregateOptions(); +#pragma warning disable CS0618 // Type or member is obsolete options.MaxTime = TimeSpan.FromMilliseconds(argument.Value.AsInt32); +#pragma warning restore CS0618 // Type or member is obsolete break; case "pipeline": pipeline = argument.Value.AsBsonArray.Cast().ToList(); diff --git a/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedEstimatedDocumentCountOperation.cs b/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedEstimatedDocumentCountOperation.cs index b144a6715bb..916a8591e7f 100644 --- a/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedEstimatedDocumentCountOperation.cs +++ b/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedEstimatedDocumentCountOperation.cs @@ -1,4 +1,4 @@ -/* Copyright 2021-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -85,7 +85,9 @@ public UnifiedEstimatedDocumentCountOperation Build(string targetCollectionId, B options.Comment = argument.Value.AsBsonValue; break; case "maxTimeMS": +#pragma warning disable CS0618 // Type or member is obsolete options.MaxTime = TimeSpan.FromMilliseconds(argument.Value.AsInt32); +#pragma warning restore CS0618 // Type or member is obsolete break; default: throw new FormatException($"Invalid {nameof(UnifiedEstimatedDocumentCountOperation)} argument name: '{argument.Name}'."); diff --git a/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedFindOperation.cs b/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedFindOperation.cs index d4777a1c7b6..cb7037db408 100644 --- a/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedFindOperation.cs +++ b/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedFindOperation.cs @@ -1,4 +1,4 @@ -/* Copyright 2020-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -130,7 +130,9 @@ public UnifiedFindOperation Build(string targetCollectionId, BsonDocument argume break; case "maxTimeMS": options ??= new FindOptions(); +#pragma warning disable CS0618 // Type or member is obsolete options.MaxTime = TimeSpan.FromMilliseconds(argument.Value.AsInt32); +#pragma warning restore CS0618 // Type or member is obsolete break; case "min": options ??= new FindOptions(); From af44109ca3b53eae828c7788769bdc3c1f4efa42 Mon Sep 17 00:00:00 2001 From: Oleksandr Poliakov Date: Fri, 18 Jul 2025 18:32:18 -0700 Subject: [PATCH 3/9] pr --- src/MongoDB.Driver/Core/Misc/Ensure.cs | 2 +- .../Core/Operations/AggregateOperation.cs | 12 +-- .../AggregateToCollectionOperation.cs | 14 ++-- .../Core/Operations/CountOperation.cs | 14 ++-- .../Core/Operations/CreateIndexesOperation.cs | 14 ++-- .../Core/Operations/DistinctOperation.cs | 14 ++-- .../Core/Operations/DropIndexOperation.cs | 14 ++-- .../Operations/FindAndModifyOperationBase.cs | 12 +-- .../Operations/FindOneAndDeleteOperation.cs | 6 +- .../Operations/FindOneAndReplaceOperation.cs | 6 +- .../Operations/FindOneAndUpdateOperation.cs | 6 +- .../Core/Operations/FindOperation.cs | 15 ++-- .../Core/Operations/MapReduceOperation.cs | 14 ++-- .../Core/Operations/MapReduceOperationBase.cs | 14 +--- .../MapReduceOutputToCollectionOperation.cs | 14 ++-- .../CommandUsingCommandMessageWireProtocol.cs | 9 ++- src/MongoDB.Driver/MongoCollectionImpl.cs | 64 ++++++++-------- src/MongoDB.Driver/MongoDatabaseSettings.cs | 4 +- src/MongoDB.Driver/MongoUrl.cs | 6 -- src/MongoDB.Driver/MongoUrlBuilder.cs | 11 +-- src/MongoDB.Driver/OperationContext.cs | 4 +- .../Operations/AggregateOperationTests.cs | 40 +++++++--- .../AggregateToCollectionOperationTests.cs | 41 +++++++--- .../Core/Operations/CountOperationTests.cs | 41 +++++++--- .../CreateCollectionOperationTests.cs | 5 +- .../Operations/CreateIndexesOperationTests.cs | 42 ++++++++--- .../Core/Operations/DistinctOperationTests.cs | 33 ++++++-- .../Operations/DropIndexOperationTests.cs | 75 ++++++++++++------- .../EstimatedDocumentCountOperationTests.cs | 4 +- .../FindOneAndDeleteOperationTests.cs | 35 +++++++-- .../FindOneAndReplaceOperationTests.cs | 41 +++++++--- .../FindOneAndUpdateOperationTests.cs | 42 ++++++++--- .../Core/Operations/FindOperationTests.cs | 63 ++++++++++------ .../Operations/MapReduceOperationBaseTests.cs | 42 ++++++++--- .../Operations/MapReduceOperationTests.cs | 6 +- ...pReduceOutputToCollectionOperationTests.cs | 9 +-- .../RetryableReadOperationExecutorTests.cs | 2 +- .../MongoUrlBuilderTests.cs | 4 +- .../OperationExecutorTests.cs | 2 +- 39 files changed, 493 insertions(+), 303 deletions(-) diff --git a/src/MongoDB.Driver/Core/Misc/Ensure.cs b/src/MongoDB.Driver/Core/Misc/Ensure.cs index 058aff50a31..8cd1163f7f1 100644 --- a/src/MongoDB.Driver/Core/Misc/Ensure.cs +++ b/src/MongoDB.Driver/Core/Misc/Ensure.cs @@ -465,7 +465,7 @@ public static TimeSpan IsValidTimeout(TimeSpan value, string paramName) return value; } - throw new ArgumentException($"Invalid timeout: {value}.", paramName); + throw new ArgumentOutOfRangeException($"Invalid timeout: {value}.", paramName); } /// diff --git a/src/MongoDB.Driver/Core/Operations/AggregateOperation.cs b/src/MongoDB.Driver/Core/Operations/AggregateOperation.cs index 86eae237593..8f1947cc546 100644 --- a/src/MongoDB.Driver/Core/Operations/AggregateOperation.cs +++ b/src/MongoDB.Driver/Core/Operations/AggregateOperation.cs @@ -288,7 +288,7 @@ public IAsyncCursor Execute(OperationContext operationContext, Retryabl using (EventContext.BeginOperation()) { - var operation = CreateOperation(context); + var operation = CreateOperation(operationContext, context); var result = operation.Execute(operationContext, context); context.ChannelSource.Session.SetSnapshotTimeIfNeeded(result.AtClusterTime); @@ -317,7 +317,7 @@ public async Task> ExecuteAsync(OperationContext operation using (EventContext.BeginOperation()) { - var operation = CreateOperation(context); + var operation = CreateOperation(operationContext, context); var result = await operation.ExecuteAsync(operationContext, context).ConfigureAwait(false); context.ChannelSource.Session.SetSnapshotTimeIfNeeded(result.AtClusterTime); @@ -326,7 +326,7 @@ public async Task> ExecuteAsync(OperationContext operation } } - internal BsonDocument CreateCommand(ConnectionDescription connectionDescription, ICoreSession session) + internal BsonDocument CreateCommand(OperationContext operationContext, ICoreSession session, ConnectionDescription connectionDescription) { var readConcern = ReadConcernHelper.GetReadConcernForCommand(session, connectionDescription, _readConcern); var command = new BsonDocument @@ -334,7 +334,7 @@ internal BsonDocument CreateCommand(ConnectionDescription connectionDescription, { "aggregate", _collectionNamespace == null ? (BsonValue)1 : _collectionNamespace.CollectionName }, { "pipeline", new BsonArray(_pipeline) }, { "allowDiskUse", () => _allowDiskUse.Value, _allowDiskUse.HasValue }, - { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue }, + { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue && !operationContext.IsRootContextTimeoutConfigured() }, { "collation", () => _collation.ToBsonDocument(), _collation != null }, { "hint", _hint, _hint != null }, { "let", _let, _let != null }, @@ -354,10 +354,10 @@ internal BsonDocument CreateCommand(ConnectionDescription connectionDescription, private IDisposable BeginOperation() => EventContext.BeginOperation(null, "aggregate"); - private ReadCommandOperation CreateOperation(RetryableReadContext context) + private ReadCommandOperation CreateOperation(OperationContext operationContext, RetryableReadContext context) { var databaseNamespace = _collectionNamespace == null ? _databaseNamespace : _collectionNamespace.DatabaseNamespace; - var command = CreateCommand(context.Channel.ConnectionDescription, context.Binding.Session); + var command = CreateCommand(operationContext, context.Binding.Session, context.Channel.ConnectionDescription); var serializer = new AggregateResultDeserializer(_resultSerializer); return new ReadCommandOperation(databaseNamespace, command, serializer, MessageEncoderSettings) { diff --git a/src/MongoDB.Driver/Core/Operations/AggregateToCollectionOperation.cs b/src/MongoDB.Driver/Core/Operations/AggregateToCollectionOperation.cs index 79c684d9752..f8ed350f732 100644 --- a/src/MongoDB.Driver/Core/Operations/AggregateToCollectionOperation.cs +++ b/src/MongoDB.Driver/Core/Operations/AggregateToCollectionOperation.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -157,7 +157,7 @@ public BsonDocument Execute(OperationContext operationContext, IWriteBinding bin using (var channel = channelSource.GetChannel(operationContext)) using (var channelBinding = new ChannelReadWriteBinding(channelSource.Server, channel, binding.Session.Fork())) { - var operation = CreateOperation(channelBinding.Session, channel.ConnectionDescription, mayUseSecondary.EffectiveReadPreference); + var operation = CreateOperation(operationContext, channelBinding.Session, channel.ConnectionDescription, mayUseSecondary.EffectiveReadPreference); return operation.Execute(operationContext, channelBinding); } } @@ -172,12 +172,12 @@ public async Task ExecuteAsync(OperationContext operationContext, using (var channel = await channelSource.GetChannelAsync(operationContext).ConfigureAwait(false)) using (var channelBinding = new ChannelReadWriteBinding(channelSource.Server, channel, binding.Session.Fork())) { - var operation = CreateOperation(channelBinding.Session, channel.ConnectionDescription, mayUseSecondary.EffectiveReadPreference); + var operation = CreateOperation(operationContext, channelBinding.Session, channel.ConnectionDescription, mayUseSecondary.EffectiveReadPreference); return await operation.ExecuteAsync(operationContext, channelBinding).ConfigureAwait(false); } } - public BsonDocument CreateCommand(ICoreSessionHandle session, ConnectionDescription connectionDescription) + public BsonDocument CreateCommand(OperationContext operationContext, ICoreSessionHandle session, ConnectionDescription connectionDescription) { var readConcern = _readConcern != null ? ReadConcernHelper.GetReadConcernForCommand(session, connectionDescription, _readConcern) @@ -189,7 +189,7 @@ public BsonDocument CreateCommand(ICoreSessionHandle session, ConnectionDescript { "pipeline", new BsonArray(_pipeline) }, { "allowDiskUse", () => _allowDiskUse.Value, _allowDiskUse.HasValue }, { "bypassDocumentValidation", () => _bypassDocumentValidation.Value, _bypassDocumentValidation.HasValue }, - { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue }, + { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue && !operationContext.IsRootContextTimeoutConfigured() }, { "collation", () => _collation.ToBsonDocument(), _collation != null }, { "readConcern", readConcern, readConcern != null }, { "writeConcern", writeConcern, writeConcern != null }, @@ -202,9 +202,9 @@ public BsonDocument CreateCommand(ICoreSessionHandle session, ConnectionDescript private IDisposable BeginOperation() => EventContext.BeginOperation("aggregate"); - private WriteCommandOperation CreateOperation(ICoreSessionHandle session, ConnectionDescription connectionDescription, ReadPreference effectiveReadPreference) + private WriteCommandOperation CreateOperation(OperationContext operationContext, ICoreSessionHandle session, ConnectionDescription connectionDescription, ReadPreference effectiveReadPreference) { - var command = CreateCommand(session, connectionDescription); + var command = CreateCommand(operationContext, session, connectionDescription); var operation = new WriteCommandOperation(_databaseNamespace, command, BsonDocumentSerializer.Instance, MessageEncoderSettings); if (effectiveReadPreference != null) { diff --git a/src/MongoDB.Driver/Core/Operations/CountOperation.cs b/src/MongoDB.Driver/Core/Operations/CountOperation.cs index cd83e1d374d..1f19a2063ac 100644 --- a/src/MongoDB.Driver/Core/Operations/CountOperation.cs +++ b/src/MongoDB.Driver/Core/Operations/CountOperation.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -109,7 +109,7 @@ public long? Skip set { _skip = value; } } - public BsonDocument CreateCommand(ConnectionDescription connectionDescription, ICoreSession session) + public BsonDocument CreateCommand(OperationContext operationContext, ICoreSession session, ConnectionDescription connectionDescription) { var readConcern = ReadConcernHelper.GetReadConcernForCommand(session, connectionDescription, _readConcern); return new BsonDocument @@ -119,7 +119,7 @@ public BsonDocument CreateCommand(ConnectionDescription connectionDescription, I { "limit", () => _limit.Value, _limit.HasValue }, { "skip", () => _skip.Value, _skip.HasValue }, { "hint", _hint, _hint != null }, - { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue }, + { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue && !operationContext.IsRootContextTimeoutConfigured() }, { "collation", () => _collation.ToBsonDocument(), _collation != null }, { "comment", _comment, _comment != null }, { "readConcern", readConcern, readConcern != null } @@ -139,7 +139,7 @@ public long Execute(OperationContext operationContext, IReadBinding binding) public long Execute(OperationContext operationContext, RetryableReadContext context) { - var operation = CreateOperation(context); + var operation = CreateOperation(operationContext, context); var document = operation.Execute(operationContext, context); return document["n"].ToInt64(); } @@ -157,16 +157,16 @@ public async Task ExecuteAsync(OperationContext operationContext, IReadBin public async Task ExecuteAsync(OperationContext operationContext, RetryableReadContext context) { - var operation = CreateOperation(context); + var operation = CreateOperation(operationContext, context); var document = await operation.ExecuteAsync(operationContext, context).ConfigureAwait(false); return document["n"].ToInt64(); } private IDisposable BeginOperation() => EventContext.BeginOperation("count"); - private ReadCommandOperation CreateOperation(RetryableReadContext context) + private ReadCommandOperation CreateOperation(OperationContext operationContext, RetryableReadContext context) { - var command = CreateCommand(context.Channel.ConnectionDescription, context.Binding.Session); + var command = CreateCommand(operationContext, context.Binding.Session, context.Channel.ConnectionDescription); return new ReadCommandOperation(_collectionNamespace.DatabaseNamespace, command, BsonDocumentSerializer.Instance, _messageEncoderSettings) { RetryRequested = _retryRequested // might be overridden by retryable read context diff --git a/src/MongoDB.Driver/Core/Operations/CreateIndexesOperation.cs b/src/MongoDB.Driver/Core/Operations/CreateIndexesOperation.cs index f4e071950ad..ea57950eea7 100644 --- a/src/MongoDB.Driver/Core/Operations/CreateIndexesOperation.cs +++ b/src/MongoDB.Driver/Core/Operations/CreateIndexesOperation.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -93,7 +93,7 @@ public BsonDocument Execute(OperationContext operationContext, IWriteBinding bin using (var channel = channelSource.GetChannel(operationContext)) using (var channelBinding = new ChannelReadWriteBinding(channelSource.Server, channel, binding.Session.Fork())) { - var operation = CreateOperation(channelBinding.Session, channel.ConnectionDescription); + var operation = CreateOperation(operationContext, channelBinding.Session, channel.ConnectionDescription); return operation.Execute(operationContext, channelBinding); } } @@ -105,12 +105,12 @@ public async Task ExecuteAsync(OperationContext operationContext, using (var channel = await channelSource.GetChannelAsync(operationContext).ConfigureAwait(false)) using (var channelBinding = new ChannelReadWriteBinding(channelSource.Server, channel, binding.Session.Fork())) { - var operation = CreateOperation(channelBinding.Session, channel.ConnectionDescription); + var operation = CreateOperation(operationContext, channelBinding.Session, channel.ConnectionDescription); return await operation.ExecuteAsync(operationContext, channelBinding).ConfigureAwait(false); } } - internal BsonDocument CreateCommand(ICoreSessionHandle session, ConnectionDescription connectionDescription) + internal BsonDocument CreateCommand(OperationContext operationContext, ICoreSessionHandle session, ConnectionDescription connectionDescription) { var maxWireVersion = connectionDescription.MaxWireVersion; var writeConcern = WriteConcernHelper.GetEffectiveWriteConcern(session, _writeConcern); @@ -123,7 +123,7 @@ internal BsonDocument CreateCommand(ICoreSessionHandle session, ConnectionDescri { { "createIndexes", _collectionNamespace.CollectionName }, { "indexes", new BsonArray(_requests.Select(request => request.CreateIndexDocument())) }, - { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue }, + { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue && !operationContext.IsRootContextTimeoutConfigured() }, { "writeConcern", writeConcern, writeConcern != null }, { "comment", _comment, _comment != null }, { "commitQuorum", () => _commitQuorum.ToBsonValue(), _commitQuorum != null } @@ -132,10 +132,10 @@ internal BsonDocument CreateCommand(ICoreSessionHandle session, ConnectionDescri private IDisposable BeginOperation() => EventContext.BeginOperation(null, "createIndexes"); - private WriteCommandOperation CreateOperation(ICoreSessionHandle session, ConnectionDescription connectionDescription) + private WriteCommandOperation CreateOperation(OperationContext operationContext, ICoreSessionHandle session, ConnectionDescription connectionDescription) { var databaseNamespace = _collectionNamespace.DatabaseNamespace; - var command = CreateCommand(session, connectionDescription); + var command = CreateCommand(operationContext, session, connectionDescription); var resultSerializer = BsonDocumentSerializer.Instance; return new WriteCommandOperation(databaseNamespace, command, resultSerializer, _messageEncoderSettings); } diff --git a/src/MongoDB.Driver/Core/Operations/DistinctOperation.cs b/src/MongoDB.Driver/Core/Operations/DistinctOperation.cs index 0e25eb3d097..a64cee8a13c 100644 --- a/src/MongoDB.Driver/Core/Operations/DistinctOperation.cs +++ b/src/MongoDB.Driver/Core/Operations/DistinctOperation.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -111,7 +111,7 @@ public IAsyncCursor Execute(OperationContext operationContext, IReadBind using (BeginOperation()) using (var context = RetryableReadContext.Create(operationContext, binding, _retryRequested)) { - var operation = CreateOperation(context); + var operation = CreateOperation(operationContext, context); var result = operation.Execute(operationContext, context); binding.Session.SetSnapshotTimeIfNeeded(result.AtClusterTime); @@ -127,7 +127,7 @@ public async Task> ExecuteAsync(OperationContext operationC using (BeginOperation()) using (var context = await RetryableReadContext.CreateAsync(operationContext, binding, _retryRequested).ConfigureAwait(false)) { - var operation = CreateOperation(context); + var operation = CreateOperation(operationContext, context); var result = await operation.ExecuteAsync(operationContext, context).ConfigureAwait(false); binding.Session.SetSnapshotTimeIfNeeded(result.AtClusterTime); @@ -136,7 +136,7 @@ public async Task> ExecuteAsync(OperationContext operationC } } - public BsonDocument CreateCommand(ConnectionDescription connectionDescription, ICoreSession session) + public BsonDocument CreateCommand(OperationContext operationContext, ICoreSession session, ConnectionDescription connectionDescription) { var readConcern = ReadConcernHelper.GetReadConcernForCommand(session, connectionDescription, _readConcern); return new BsonDocument @@ -144,7 +144,7 @@ public BsonDocument CreateCommand(ConnectionDescription connectionDescription, I { "distinct", _collectionNamespace.CollectionName }, { "key", _fieldName }, { "query", _filter, _filter != null }, - { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue }, + { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue && !operationContext.IsRootContextTimeoutConfigured() }, { "collation", () => _collation.ToBsonDocument(), _collation != null }, { "comment", _comment, _comment != null }, { "readConcern", readConcern, readConcern != null } @@ -153,9 +153,9 @@ public BsonDocument CreateCommand(ConnectionDescription connectionDescription, I private IDisposable BeginOperation() => EventContext.BeginOperation("distinct"); - private ReadCommandOperation CreateOperation(RetryableReadContext context) + private ReadCommandOperation CreateOperation(OperationContext operationContext, RetryableReadContext context) { - var command = CreateCommand(context.Channel.ConnectionDescription, context.Binding.Session); + var command = CreateCommand(operationContext, context.Binding.Session, context.Channel.ConnectionDescription); var serializer = new DistinctResultDeserializer(_valueSerializer); return new ReadCommandOperation(_collectionNamespace.DatabaseNamespace, command, serializer, _messageEncoderSettings) diff --git a/src/MongoDB.Driver/Core/Operations/DropIndexOperation.cs b/src/MongoDB.Driver/Core/Operations/DropIndexOperation.cs index ef68ad071c5..72e8b1bc53b 100644 --- a/src/MongoDB.Driver/Core/Operations/DropIndexOperation.cs +++ b/src/MongoDB.Driver/Core/Operations/DropIndexOperation.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -84,14 +84,14 @@ public TimeSpan? MaxTime set { _maxTime = Ensure.IsNullOrInfiniteOrGreaterThanOrEqualToZero(value, nameof(value)); } } - public BsonDocument CreateCommand(ICoreSessionHandle session) + public BsonDocument CreateCommand(OperationContext operationContext, ICoreSessionHandle session) { var writeConcern = WriteConcernHelper.GetEffectiveWriteConcern(session, _writeConcern); return new BsonDocument { { "dropIndexes", _collectionNamespace.CollectionName }, { "index", _indexName }, - { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue }, + { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue && !operationContext.IsRootContextTimeoutConfigured() }, { "writeConcern", writeConcern, writeConcern != null }, { "comment", _comment, _comment != null } }; @@ -106,7 +106,7 @@ public BsonDocument Execute(OperationContext operationContext, IWriteBinding bin using (var channel = channelSource.GetChannel(operationContext)) using (var channelBinding = new ChannelReadWriteBinding(channelSource.Server, channel, binding.Session.Fork())) { - var operation = CreateOperation(channelBinding.Session); + var operation = CreateOperation(operationContext, channelBinding.Session); BsonDocument result; try { @@ -133,7 +133,7 @@ public async Task ExecuteAsync(OperationContext operationContext, using (var channel = await channelSource.GetChannelAsync(operationContext).ConfigureAwait(false)) using (var channelBinding = new ChannelReadWriteBinding(channelSource.Server, channel, binding.Session.Fork())) { - var operation = CreateOperation(channelBinding.Session); + var operation = CreateOperation(operationContext, channelBinding.Session); BsonDocument result; try { @@ -153,9 +153,9 @@ public async Task ExecuteAsync(OperationContext operationContext, private IDisposable BeginOperation() => EventContext.BeginOperation("dropIndexes"); - private WriteCommandOperation CreateOperation(ICoreSessionHandle session) + private WriteCommandOperation CreateOperation(OperationContext operationContext, ICoreSessionHandle session) { - var command = CreateCommand(session); + var command = CreateCommand(operationContext, session); return new WriteCommandOperation(_collectionNamespace.DatabaseNamespace, command, BsonDocumentSerializer.Instance, _messageEncoderSettings); } diff --git a/src/MongoDB.Driver/Core/Operations/FindAndModifyOperationBase.cs b/src/MongoDB.Driver/Core/Operations/FindAndModifyOperationBase.cs index d32198f81af..1b346fe013f 100644 --- a/src/MongoDB.Driver/Core/Operations/FindAndModifyOperationBase.cs +++ b/src/MongoDB.Driver/Core/Operations/FindAndModifyOperationBase.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -124,7 +124,7 @@ public TResult ExecuteAttempt(OperationContext operationContext, RetryableWriteC using (var channelBinding = new ChannelReadWriteBinding(channelSource.Server, channel, binding.Session.Fork())) { - var operation = CreateOperation(channelBinding.Session, channel.ConnectionDescription, transactionNumber); + var operation = CreateOperation(operationContext, channelBinding.Session, channel.ConnectionDescription, transactionNumber); using (var rawBsonDocument = operation.Execute(operationContext, channelBinding)) { return ProcessCommandResult(channel.ConnectionDescription.ConnectionId, rawBsonDocument); @@ -140,7 +140,7 @@ public async Task ExecuteAttemptAsync(OperationContext operationContext using (var channelBinding = new ChannelReadWriteBinding(channelSource.Server, channel, binding.Session.Fork())) { - var operation = CreateOperation(channelBinding.Session, channel.ConnectionDescription, transactionNumber); + var operation = CreateOperation(operationContext, channelBinding.Session, channel.ConnectionDescription, transactionNumber); using (var rawBsonDocument = await operation.ExecuteAsync(operationContext, channelBinding).ConfigureAwait(false)) { return ProcessCommandResult(channel.ConnectionDescription.ConnectionId, rawBsonDocument); @@ -148,15 +148,15 @@ public async Task ExecuteAttemptAsync(OperationContext operationContext } } - public abstract BsonDocument CreateCommand(ICoreSessionHandle session, ConnectionDescription connectionDescription, long? transactionNumber); + public abstract BsonDocument CreateCommand(OperationContext operationContext, ICoreSessionHandle session, ConnectionDescription connectionDescription, long? transactionNumber); protected abstract IElementNameValidator GetCommandValidator(); private IDisposable BeginOperation() => EventContext.BeginOperation("findAndModify"); - private WriteCommandOperation CreateOperation(ICoreSessionHandle session, ConnectionDescription connectionDescription, long? transactionNumber) + private WriteCommandOperation CreateOperation(OperationContext operationContext, ICoreSessionHandle session, ConnectionDescription connectionDescription, long? transactionNumber) { - var command = CreateCommand(session, connectionDescription, transactionNumber); + var command = CreateCommand(operationContext, session, connectionDescription, transactionNumber); return new WriteCommandOperation(_collectionNamespace.DatabaseNamespace, command, RawBsonDocumentSerializer.Instance, _messageEncoderSettings) { CommandValidator = GetCommandValidator() diff --git a/src/MongoDB.Driver/Core/Operations/FindOneAndDeleteOperation.cs b/src/MongoDB.Driver/Core/Operations/FindOneAndDeleteOperation.cs index a06756a1a6f..dcc41a6876b 100644 --- a/src/MongoDB.Driver/Core/Operations/FindOneAndDeleteOperation.cs +++ b/src/MongoDB.Driver/Core/Operations/FindOneAndDeleteOperation.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -74,7 +74,7 @@ public BsonDocument Sort set { _sort = value; } } - public override BsonDocument CreateCommand(ICoreSessionHandle session, ConnectionDescription connectionDescription, long? transactionNumber) + public override BsonDocument CreateCommand(OperationContext operationContext, ICoreSessionHandle session, ConnectionDescription connectionDescription, long? transactionNumber) { var wireVersion = connectionDescription.MaxWireVersion; FindProjectionChecker.ThrowIfAggregationExpressionIsUsedWhenNotSupported(_projection, wireVersion); @@ -95,7 +95,7 @@ public override BsonDocument CreateCommand(ICoreSessionHandle session, Connectio { "remove", true }, { "sort", _sort, _sort != null }, { "fields", _projection, _projection != null }, - { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue }, + { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue && !operationContext.IsRootContextTimeoutConfigured() }, { "writeConcern", writeConcern, writeConcern != null }, { "collation", () => Collation.ToBsonDocument(), Collation != null }, { "comment", Comment, Comment != null }, diff --git a/src/MongoDB.Driver/Core/Operations/FindOneAndReplaceOperation.cs b/src/MongoDB.Driver/Core/Operations/FindOneAndReplaceOperation.cs index f7aaa59e809..a69e2a651c1 100644 --- a/src/MongoDB.Driver/Core/Operations/FindOneAndReplaceOperation.cs +++ b/src/MongoDB.Driver/Core/Operations/FindOneAndReplaceOperation.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -103,7 +103,7 @@ public BsonDocument Sort set { _sort = value; } } - public override BsonDocument CreateCommand(ICoreSessionHandle session, ConnectionDescription connectionDescription, long? transactionNumber) + public override BsonDocument CreateCommand(OperationContext operationContext, ICoreSessionHandle session, ConnectionDescription connectionDescription, long? transactionNumber) { var wireVersion = connectionDescription.MaxWireVersion; FindProjectionChecker.ThrowIfAggregationExpressionIsUsedWhenNotSupported(_projection, wireVersion); @@ -126,7 +126,7 @@ public override BsonDocument CreateCommand(ICoreSessionHandle session, Connectio { "sort", _sort, _sort != null }, { "fields", _projection, _projection != null }, { "upsert", true, _isUpsert }, - { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue }, + { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue && !operationContext.IsRootContextTimeoutConfigured() }, { "writeConcern", writeConcern, writeConcern != null }, { "bypassDocumentValidation", () => _bypassDocumentValidation.Value, _bypassDocumentValidation.HasValue }, { "collation", () => Collation.ToBsonDocument(), Collation != null }, diff --git a/src/MongoDB.Driver/Core/Operations/FindOneAndUpdateOperation.cs b/src/MongoDB.Driver/Core/Operations/FindOneAndUpdateOperation.cs index 42f1e1702d2..bd0aca46a50 100644 --- a/src/MongoDB.Driver/Core/Operations/FindOneAndUpdateOperation.cs +++ b/src/MongoDB.Driver/Core/Operations/FindOneAndUpdateOperation.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -112,7 +112,7 @@ public BsonValue Update get { return _update; } } - public override BsonDocument CreateCommand(ICoreSessionHandle session, ConnectionDescription connectionDescription, long? transactionNumber) + public override BsonDocument CreateCommand(OperationContext operationContext, ICoreSessionHandle session, ConnectionDescription connectionDescription, long? transactionNumber) { var wireVersion = connectionDescription.MaxWireVersion; FindProjectionChecker.ThrowIfAggregationExpressionIsUsedWhenNotSupported(_projection, wireVersion); @@ -135,7 +135,7 @@ public override BsonDocument CreateCommand(ICoreSessionHandle session, Connectio { "sort", _sort, _sort != null }, { "fields", _projection, _projection != null }, { "upsert", true, _isUpsert }, - { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue }, + { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue && !operationContext.IsRootContextTimeoutConfigured() }, { "writeConcern", writeConcern, writeConcern != null }, { "bypassDocumentValidation", () => _bypassDocumentValidation.Value, _bypassDocumentValidation.HasValue }, { "collation", () => Collation.ToBsonDocument(), Collation != null }, diff --git a/src/MongoDB.Driver/Core/Operations/FindOperation.cs b/src/MongoDB.Driver/Core/Operations/FindOperation.cs index 364d71bccfa..ec42b994f37 100644 --- a/src/MongoDB.Driver/Core/Operations/FindOperation.cs +++ b/src/MongoDB.Driver/Core/Operations/FindOperation.cs @@ -1,4 +1,4 @@ -/* Copyright 2015-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -237,7 +237,7 @@ public BsonDocument Sort set { _sort = value; } } - public BsonDocument CreateCommand(ConnectionDescription connectionDescription, ICoreSession session) + public BsonDocument CreateCommand(OperationContext operationContext, ICoreSession session, ConnectionDescription connectionDescription) { var wireVersion = connectionDescription.MaxWireVersion; FindProjectionChecker.ThrowIfAggregationExpressionIsUsedWhenNotSupported(_projection, wireVersion); @@ -254,7 +254,6 @@ public BsonDocument CreateCommand(ConnectionDescription connectionDescription, I var effectiveComment = _comment; var effectiveHint = _hint; var effectiveMax = _max; - var effectiveMaxTime = _maxTime; var effectiveMin = _min; var effectiveReturnKey = _returnKey; var effectiveShowRecordId = _showRecordId; @@ -273,7 +272,7 @@ public BsonDocument CreateCommand(ConnectionDescription connectionDescription, I { "batchSize", () => batchSize.Value, batchSize.HasValue && batchSize > 0 }, { "singleBatch", () => _limit < 0 || _singleBatch.Value, _limit < 0 || _singleBatch.HasValue }, { "comment", effectiveComment, effectiveComment != null }, - { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(effectiveMaxTime.Value), effectiveMaxTime.HasValue }, + { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue && !operationContext.IsRootContextTimeoutConfigured() }, { "max", effectiveMax, effectiveMax != null }, { "min", effectiveMin, effectiveMin != null }, { "returnKey", () => effectiveReturnKey.Value, effectiveReturnKey.HasValue }, @@ -307,7 +306,7 @@ public IAsyncCursor Execute(OperationContext operationContext, Retrya using (EventContext.BeginFind(_batchSize, _limit)) { - var operation = CreateOperation(context); + var operation = CreateOperation(operationContext, context); var commandResult = operation.Execute(operationContext, context); return CreateCursor(context.ChannelSource, context.Channel, commandResult); } @@ -330,7 +329,7 @@ public async Task> ExecuteAsync(OperationContext operati using (EventContext.BeginFind(_batchSize, _limit)) { - var operation = CreateOperation(context); + var operation = CreateOperation(operationContext, context); var commandResult = await operation.ExecuteAsync(operationContext, context).ConfigureAwait(false); return CreateCursor(context.ChannelSource, context.Channel, commandResult); } @@ -375,9 +374,9 @@ private CursorBatch CreateFirstCursorBatch(BsonDocument cursorDocumen private IDisposable BeginOperation() => EventContext.BeginOperation(null, "find"); - private ReadCommandOperation CreateOperation(RetryableReadContext context) + private ReadCommandOperation CreateOperation(OperationContext operationContext, RetryableReadContext context) { - var command = CreateCommand(context.Channel.ConnectionDescription, context.Binding.Session); + var command = CreateCommand(operationContext, context.Binding.Session, context.Channel.ConnectionDescription); var operation = new ReadCommandOperation( _collectionNamespace.DatabaseNamespace, command, diff --git a/src/MongoDB.Driver/Core/Operations/MapReduceOperation.cs b/src/MongoDB.Driver/Core/Operations/MapReduceOperation.cs index a68b2227278..21f2a99d684 100644 --- a/src/MongoDB.Driver/Core/Operations/MapReduceOperation.cs +++ b/src/MongoDB.Driver/Core/Operations/MapReduceOperation.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -95,7 +95,7 @@ public IAsyncCursor Execute(OperationContext operationContext, IReadBin using (var channel = channelSource.GetChannel(operationContext)) using (var channelBinding = new ChannelReadBinding(channelSource.Server, channel, binding.ReadPreference, binding.Session.Fork())) { - var operation = CreateOperation(channelBinding.Session, channel.ConnectionDescription); + var operation = CreateOperation(operationContext, channelBinding.Session, channel.ConnectionDescription); var result = operation.Execute(operationContext, channelBinding); return new SingleBatchAsyncCursor(result); } @@ -110,16 +110,16 @@ public async Task> ExecuteAsync(OperationContext operation using (var channel = await channelSource.GetChannelAsync(operationContext).ConfigureAwait(false)) using (var channelBinding = new ChannelReadBinding(channelSource.Server, channel, binding.ReadPreference, binding.Session.Fork())) { - var operation = CreateOperation(channelBinding.Session, channel.ConnectionDescription); + var operation = CreateOperation(operationContext, channelBinding.Session, channel.ConnectionDescription); var result = await operation.ExecuteAsync(operationContext, channelBinding).ConfigureAwait(false); return new SingleBatchAsyncCursor(result); } } /// - protected internal override BsonDocument CreateCommand(ICoreSessionHandle session, ConnectionDescription connectionDescription) + protected internal override BsonDocument CreateCommand(OperationContext operationContext, ICoreSessionHandle session, ConnectionDescription connectionDescription) { - var command = base.CreateCommand(session, connectionDescription); + var command = base.CreateCommand(operationContext, session, connectionDescription); var readConcern = ReadConcernHelper.GetReadConcernForCommand(session, connectionDescription, _readConcern); if (readConcern != null) @@ -130,9 +130,9 @@ protected internal override BsonDocument CreateCommand(ICoreSessionHandle sessio return command; } - private ReadCommandOperation CreateOperation(ICoreSessionHandle session, ConnectionDescription connectionDescription) + private ReadCommandOperation CreateOperation(OperationContext operationContext, ICoreSessionHandle session, ConnectionDescription connectionDescription) { - var command = CreateCommand(session, connectionDescription); + var command = CreateCommand(operationContext, session, connectionDescription); var resultArraySerializer = new ArraySerializer(_resultSerializer); var resultSerializer = new ElementDeserializer("results", resultArraySerializer); return new ReadCommandOperation(CollectionNamespace.DatabaseNamespace, command, resultSerializer, MessageEncoderSettings) diff --git a/src/MongoDB.Driver/Core/Operations/MapReduceOperationBase.cs b/src/MongoDB.Driver/Core/Operations/MapReduceOperationBase.cs index 5840e28ac78..f1f455352bc 100644 --- a/src/MongoDB.Driver/Core/Operations/MapReduceOperationBase.cs +++ b/src/MongoDB.Driver/Core/Operations/MapReduceOperationBase.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -221,15 +221,7 @@ public bool? Verbose } // methods - /// - /// Creates the command. - /// - /// The session. - /// The connection description. - /// - /// The command. - /// - protected internal virtual BsonDocument CreateCommand(ICoreSessionHandle session, ConnectionDescription connectionDescription) + protected internal virtual BsonDocument CreateCommand(OperationContext operationContext, ICoreSessionHandle session, ConnectionDescription connectionDescription) { return new BsonDocument { @@ -244,7 +236,7 @@ protected internal virtual BsonDocument CreateCommand(ICoreSessionHandle session { "scope", _scope, _scope != null }, { "jsMode", () => _javaScriptMode.Value, _javaScriptMode.HasValue }, { "verbose", () => _verbose.Value, _verbose.HasValue }, - { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue }, + { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue && !operationContext.IsRootContextTimeoutConfigured() }, { "collation", () => _collation.ToBsonDocument(), _collation != null } }; } diff --git a/src/MongoDB.Driver/Core/Operations/MapReduceOutputToCollectionOperation.cs b/src/MongoDB.Driver/Core/Operations/MapReduceOutputToCollectionOperation.cs index 99e32b1adcd..2fe04c0ace8 100644 --- a/src/MongoDB.Driver/Core/Operations/MapReduceOutputToCollectionOperation.cs +++ b/src/MongoDB.Driver/Core/Operations/MapReduceOutputToCollectionOperation.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -139,9 +139,9 @@ public WriteConcern WriteConcern // methods /// - protected internal override BsonDocument CreateCommand(ICoreSessionHandle session, ConnectionDescription connectionDescription) + protected internal override BsonDocument CreateCommand(OperationContext operationContext, ICoreSessionHandle session, ConnectionDescription connectionDescription) { - var command = base.CreateCommand(session, connectionDescription); + var command = base.CreateCommand(operationContext, session, connectionDescription); if (_bypassDocumentValidation.HasValue) { @@ -177,7 +177,7 @@ public BsonDocument Execute(OperationContext operationContext, IWriteBinding bin using (var channel = channelSource.GetChannel(operationContext)) using (var channelBinding = new ChannelReadWriteBinding(channelSource.Server, channel, binding.Session.Fork())) { - var operation = CreateOperation(channelBinding.Session, channel.ConnectionDescription); + var operation = CreateOperation(operationContext, channelBinding.Session, channel.ConnectionDescription); return operation.Execute(operationContext, channelBinding); } } @@ -191,14 +191,14 @@ public async Task ExecuteAsync(OperationContext operationContext, using (var channel = await channelSource.GetChannelAsync(operationContext).ConfigureAwait(false)) using (var channelBinding = new ChannelReadWriteBinding(channelSource.Server, channel, binding.Session.Fork())) { - var operation = CreateOperation(channelBinding.Session, channel.ConnectionDescription); + var operation = CreateOperation(operationContext, channelBinding.Session, channel.ConnectionDescription); return await operation.ExecuteAsync(operationContext, channelBinding).ConfigureAwait(false); } } - private WriteCommandOperation CreateOperation(ICoreSessionHandle session, ConnectionDescription connectionDescription) + private WriteCommandOperation CreateOperation(OperationContext operationContext, ICoreSessionHandle session, ConnectionDescription connectionDescription) { - var command = CreateCommand(session, connectionDescription); + var command = CreateCommand(operationContext, session, connectionDescription); return new WriteCommandOperation(CollectionNamespace.DatabaseNamespace, command, BsonDocumentSerializer.Instance, MessageEncoderSettings); } } diff --git a/src/MongoDB.Driver/Core/WireProtocol/CommandUsingCommandMessageWireProtocol.cs b/src/MongoDB.Driver/Core/WireProtocol/CommandUsingCommandMessageWireProtocol.cs index 25481d385a6..afd19dbf1f6 100644 --- a/src/MongoDB.Driver/Core/WireProtocol/CommandUsingCommandMessageWireProtocol.cs +++ b/src/MongoDB.Driver/Core/WireProtocol/CommandUsingCommandMessageWireProtocol.cs @@ -376,13 +376,14 @@ private Type0CommandMessageSection CreateType0Section(OperationCon if (operationContext.IsRootContextTimeoutConfigured() && _roundTripTime > TimeSpan.Zero) { - var serverTimeout = operationContext.RemainingTimeout - _roundTripTime; - if (serverTimeout < TimeSpan.Zero) + var serverTimeout = operationContext.RemainingTimeout; + if (serverTimeout != Timeout.InfiniteTimeSpan) { - throw new TimeoutException(); + serverTimeout -= _roundTripTime; } - AddIfNotAlreadyAdded("maxTimeMS", (long)serverTimeout.TotalMilliseconds); + var serverTimeoutMs = MaxTimeHelper.ToMaxTimeMS(serverTimeout); + AddIfNotAlreadyAdded("maxTimeMS", serverTimeoutMs); } var elementAppendingSerializer = new ElementAppendingSerializer(BsonDocumentSerializer.Instance, extraElements); diff --git a/src/MongoDB.Driver/MongoCollectionImpl.cs b/src/MongoDB.Driver/MongoCollectionImpl.cs index f24827a585b..310d2ca29c3 100644 --- a/src/MongoDB.Driver/MongoCollectionImpl.cs +++ b/src/MongoDB.Driver/MongoCollectionImpl.cs @@ -211,7 +211,7 @@ public override BulkWriteResult BulkWrite(IClientSessionHandle sessio var operation = CreateBulkWriteOperation(session, requestsArray, options); try { - var result = ExecuteWriteOperation(session, operation, options.Timeout, cancellationToken); + var result = ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken); return BulkWriteResult.FromCore(result, requestsArray); } catch (MongoBulkWriteOperationException ex) @@ -239,7 +239,7 @@ public override async Task> BulkWriteAsync(IClientSes var operation = CreateBulkWriteOperation(session, requestsArray, options); try { - var result = await ExecuteWriteOperationAsync(session, operation, options.Timeout, cancellationToken).ConfigureAwait(false); + var result = await ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken).ConfigureAwait(false); return BulkWriteResult.FromCore(result, requestsArray); } catch (MongoBulkWriteOperationException ex) @@ -262,7 +262,7 @@ public override long Count(IClientSessionHandle session, FilterDefinition CountAsync(IClientSessionHandle session, FilterDefini Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateCountOperation(filter, options); - return ExecuteReadOperationAsync(session, operation, options.Timeout, cancellationToken); + return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken); } public override long CountDocuments(FilterDefinition filter, CountOptions options, CancellationToken cancellationToken = default) @@ -294,7 +294,7 @@ public override long CountDocuments(IClientSessionHandle session, FilterDefiniti Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateCountDocumentsOperation(filter, options); - return ExecuteReadOperation(session, operation, options.Timeout, cancellationToken); + return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken); } public override async Task CountDocumentsAsync(FilterDefinition filter, CountOptions options, CancellationToken cancellationToken = default) @@ -309,7 +309,7 @@ public override Task CountDocumentsAsync(IClientSessionHandle session, Fil Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateCountDocumentsOperation(filter, options); - return ExecuteReadOperationAsync(session, operation, options.Timeout, cancellationToken); + return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken); } public override IAsyncCursor Distinct(FieldDefinition field, FilterDefinition filter, DistinctOptions options, CancellationToken cancellationToken = default) @@ -325,7 +325,7 @@ public override IAsyncCursor Distinct(IClientSessionHandle sessi Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateDistinctOperation(field, filter, options); - return ExecuteReadOperation(session, operation, options.Timeout, cancellationToken); + return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken); } public override async Task> DistinctAsync(FieldDefinition field, FilterDefinition filter, DistinctOptions options, CancellationToken cancellationToken = default) @@ -341,7 +341,7 @@ public override Task> DistinctAsync(IClientSessionH Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateDistinctOperation(field, filter, options); - return ExecuteReadOperationAsync(session, operation, options.Timeout, cancellationToken); + return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken); } public override IAsyncCursor DistinctMany(FieldDefinition> field, FilterDefinition filter, DistinctOptions options, CancellationToken cancellationToken = default) @@ -357,7 +357,7 @@ public override IAsyncCursor DistinctMany(IClientSessionHandle ses Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateDistinctManyOperation(field, filter, options); - return ExecuteReadOperation(session, operation, options.Timeout, cancellationToken); + return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken); } public override async Task> DistinctManyAsync(FieldDefinition> field, FilterDefinition filter, DistinctOptions options, CancellationToken cancellationToken = default) @@ -373,21 +373,21 @@ public override Task> DistinctManyAsync(IClientSessio Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateDistinctManyOperation(field, filter, options); - return ExecuteReadOperationAsync(session, operation, options.Timeout, cancellationToken); + return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken); } public override long EstimatedDocumentCount(EstimatedDocumentCountOptions options, CancellationToken cancellationToken = default) { using var session = _operationExecutor.StartImplicitSession(); var operation = CreateEstimatedDocumentCountOperation(options); - return ExecuteReadOperation(session, operation, options.Timeout, cancellationToken); + return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken); } public override async Task EstimatedDocumentCountAsync(EstimatedDocumentCountOptions options, CancellationToken cancellationToken = default) { using var session = _operationExecutor.StartImplicitSession(); var operation = CreateEstimatedDocumentCountOperation(options); - return await ExecuteReadOperationAsync(session, operation, options.Timeout, cancellationToken).ConfigureAwait(false); + return await ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken).ConfigureAwait(false); } public override IAsyncCursor FindSync(FilterDefinition filter, FindOptions options, CancellationToken cancellationToken = default) @@ -402,7 +402,7 @@ public override IAsyncCursor FindSync(IClientSessionHa Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateFindOperation(filter, options); - return ExecuteReadOperation(session, operation, options.Timeout, cancellationToken); + return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken); } public override async Task> FindAsync(FilterDefinition filter, FindOptions options, CancellationToken cancellationToken = default) @@ -417,7 +417,7 @@ public override Task> FindAsync(IClientSe Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateFindOperation(filter, options); - return ExecuteReadOperationAsync(session, operation, options.Timeout, cancellationToken); + return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken); } public override TProjection FindOneAndDelete(FilterDefinition filter, FindOneAndDeleteOptions options, CancellationToken cancellationToken = default) @@ -432,7 +432,7 @@ public override TProjection FindOneAndDelete(IClientSessionHandle s Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateFindOneAndDeleteOperation(filter, options); - return ExecuteWriteOperation(session, operation, options.Timeout, cancellationToken); + return ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken); } public override async Task FindOneAndDeleteAsync(FilterDefinition filter, FindOneAndDeleteOptions options, CancellationToken cancellationToken = default) @@ -447,7 +447,7 @@ public override Task FindOneAndDeleteAsync(IClientSess Ensure.IsNotNull(filter, nameof(filter)); var operation = CreateFindOneAndDeleteOperation(filter, options); - return ExecuteWriteOperationAsync(session, operation, options.Timeout, cancellationToken); + return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken); } public override TProjection FindOneAndReplace(FilterDefinition filter, TDocument replacement, FindOneAndReplaceOptions options, CancellationToken cancellationToken = default) @@ -463,7 +463,7 @@ public override TProjection FindOneAndReplace(IClientSessionHandle var replacementObject = Ensure.IsNotNull((object)replacement, nameof(replacement)); // only box once if it's a struct var operation = CreateFindOneAndReplaceOperation(filter, replacementObject, options); - return ExecuteWriteOperation(session, operation, options.Timeout, cancellationToken); + return ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken); } public override async Task FindOneAndReplaceAsync(FilterDefinition filter, TDocument replacement, FindOneAndReplaceOptions options, CancellationToken cancellationToken = default) @@ -479,7 +479,7 @@ public override Task FindOneAndReplaceAsync(IClientSes var replacementObject = Ensure.IsNotNull((object)replacement, nameof(replacement)); // only box once if it's a struct var operation = CreateFindOneAndReplaceOperation(filter, replacementObject, options); - return ExecuteWriteOperationAsync(session, operation, options.Timeout, cancellationToken); + return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken); } public override TProjection FindOneAndUpdate(FilterDefinition filter, UpdateDefinition update, FindOneAndUpdateOptions options, CancellationToken cancellationToken = default) @@ -501,7 +501,7 @@ public override TProjection FindOneAndUpdate(IClientSessionHandle s } var operation = CreateFindOneAndUpdateOperation(filter, update, options); - return ExecuteWriteOperation(session, operation, options.Timeout, cancellationToken); + return ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken); } public override async Task FindOneAndUpdateAsync(FilterDefinition filter, UpdateDefinition update, FindOneAndUpdateOptions options, CancellationToken cancellationToken = default) @@ -522,7 +522,7 @@ public override Task FindOneAndUpdateAsync(IClientSess } var operation = CreateFindOneAndUpdateOperation(filter, update, options); - return ExecuteWriteOperationAsync(session, operation, options.Timeout, cancellationToken); + return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken); } [Obsolete("Use Aggregation pipeline instead.")] @@ -795,8 +795,8 @@ private IAsyncCursor CreateAggregateToCollectionResultCursor(I var forkedSession = session.Fork(); var deferredCursor = new DeferredAsyncCursor( () => forkedSession.Dispose(), - ct => ExecuteReadOperation(forkedSession, findOperation, ReadPreference.Primary, options.Timeout, ct), - ct => ExecuteReadOperationAsync(forkedSession, findOperation, ReadPreference.Primary, options.Timeout, ct)); + ct => ExecuteReadOperation(forkedSession, findOperation, ReadPreference.Primary, options?.Timeout, ct), + ct => ExecuteReadOperationAsync(forkedSession, findOperation, ReadPreference.Primary, options?.Timeout, ct)); return deferredCursor; } @@ -1224,8 +1224,8 @@ private IAsyncCursor CreateMapReduceOutputToCollectionResultCursor( () => forkedSession.Dispose(), - ct => ExecuteReadOperation(forkedSession, findOperation, ReadPreference.Primary, options.Timeout, ct), - ct => ExecuteReadOperationAsync(forkedSession, findOperation, ReadPreference.Primary, options.Timeout, ct)); + ct => ExecuteReadOperation(forkedSession, findOperation, ReadPreference.Primary, options?.Timeout, ct), + ct => ExecuteReadOperationAsync(forkedSession, findOperation, ReadPreference.Primary, options?.Timeout, ct)); return deferredCursor; } @@ -1413,7 +1413,7 @@ public override IEnumerable CreateMany( Ensure.IsNotNull(models, nameof(models)); var operation = CreateCreateIndexesOperation(models, options); - _collection.ExecuteWriteOperation(session, operation, options.Timeout, cancellationToken); + _collection.ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken); return operation.Requests.Select(x => x.GetIndexName()); } @@ -1442,7 +1442,7 @@ public override async Task> CreateManyAsync( Ensure.IsNotNull(models, nameof(models)); var operation = CreateCreateIndexesOperation(models, options); - await _collection.ExecuteWriteOperationAsync(session, operation, options.Timeout, cancellationToken).ConfigureAwait(false); + await _collection.ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken).ConfigureAwait(false); return operation.Requests.Select(x => x.GetIndexName()); } @@ -1462,7 +1462,7 @@ public override void DropAll(IClientSessionHandle session, DropIndexOptions opti { Ensure.IsNotNull(session, nameof(session)); var operation = CreateDropAllOperation(options); - _collection.ExecuteWriteOperation(session, operation, options.Timeout, cancellationToken); + _collection.ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken); } public override Task DropAllAsync(CancellationToken cancellationToken) @@ -1481,7 +1481,7 @@ public override Task DropAllAsync(IClientSessionHandle session, DropIndexOptions { Ensure.IsNotNull(session, nameof(session)); var operation = CreateDropAllOperation(options); - return _collection.ExecuteWriteOperationAsync(session, operation, options.Timeout, cancellationToken); + return _collection.ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken); } public override void DropOne(string name, CancellationToken cancellationToken = default) @@ -1506,7 +1506,7 @@ public override void DropOne(IClientSessionHandle session, string name, DropInde } var operation = CreateDropOneOperation(name, options); - _collection.ExecuteWriteOperation(session, operation, options.Timeout, cancellationToken); + _collection.ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken); } public override Task DropOneAsync(string name, CancellationToken cancellationToken = default) @@ -1531,7 +1531,7 @@ public override Task DropOneAsync(IClientSessionHandle session, string name, Dro } var operation = CreateDropOneOperation(name, options); - return _collection.ExecuteWriteOperationAsync(session, operation, options.Timeout, cancellationToken); + return _collection.ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken); } public override IAsyncCursor List(CancellationToken cancellationToken = default) @@ -1550,7 +1550,7 @@ public override IAsyncCursor List(IClientSessionHandle session, Li { Ensure.IsNotNull(session, nameof(session)); var operation = CreateListIndexesOperation(options); - return _collection.ExecuteReadOperation(session, operation, options.Timeout, cancellationToken); + return _collection.ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken); } public override Task> ListAsync(CancellationToken cancellationToken = default) @@ -1569,7 +1569,7 @@ public override Task> ListAsync(IClientSessionHandle { Ensure.IsNotNull(session, nameof(session)); var operation = CreateListIndexesOperation(options); - return _collection.ExecuteReadOperationAsync(session, operation, options.Timeout, cancellationToken); + return _collection.ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken); } // private methods diff --git a/src/MongoDB.Driver/MongoDatabaseSettings.cs b/src/MongoDB.Driver/MongoDatabaseSettings.cs index c1c82935600..ddffef09f9b 100644 --- a/src/MongoDB.Driver/MongoDatabaseSettings.cs +++ b/src/MongoDB.Driver/MongoDatabaseSettings.cs @@ -190,7 +190,7 @@ public override bool Equals(object obj) _readConcern.Value == rhs._readConcern.Value && object.Equals(_readEncoding, rhs._readEncoding) && object.Equals(_readPreference.Value, rhs._readPreference.Value) && - _timeout.Value == rhs._timeout.Value && + _timeout == rhs._timeout && _writeConcern.Value == rhs._writeConcern.Value && object.Equals(_writeEncoding, rhs._writeEncoding); } @@ -244,7 +244,7 @@ public override int GetHashCode() hash = 37 * hash + ((_readConcern.Value == null) ? 0 : _readConcern.GetHashCode()); hash = 37 * hash + ((_readEncoding.Value == null) ? 0 : _readEncoding.GetHashCode()); hash = 37 * hash + ((_readPreference.Value == null) ? 0 : _readPreference.Value.GetHashCode()); - hash = 37 * hash + _timeout.Value.GetHashCode(); + hash = 37 * hash + _timeout?.GetHashCode() ?? 0; hash = 37 * hash + ((_writeConcern.Value == null) ? 0 : _writeConcern.Value.GetHashCode()); hash = 37 * hash + ((_writeEncoding.Value == null) ? 0 : _writeEncoding.GetHashCode()); return hash; diff --git a/src/MongoDB.Driver/MongoUrl.cs b/src/MongoDB.Driver/MongoUrl.cs index c2e51c855dc..b7d972aaaff 100644 --- a/src/MongoDB.Driver/MongoUrl.cs +++ b/src/MongoDB.Driver/MongoUrl.cs @@ -758,11 +758,5 @@ public override string ToString() { return _url; } - - // private methods - private bool AnyWriteConcernSettingsAreSet() - { - return _fsync != null || _journal != null || _w != null || _wTimeout != null; - } } } diff --git a/src/MongoDB.Driver/MongoUrlBuilder.cs b/src/MongoDB.Driver/MongoUrlBuilder.cs index a9baecaa78b..a02a144b6b8 100644 --- a/src/MongoDB.Driver/MongoUrlBuilder.cs +++ b/src/MongoDB.Driver/MongoUrlBuilder.cs @@ -116,7 +116,7 @@ public MongoUrlBuilder() _socketTimeout = MongoDefaults.SocketTimeout; _srvMaxHosts = null; _srvServiceName = MongoInternalDefaults.MongoClientSettings.SrvServiceName; - _timeout = System.Threading.Timeout.InfiniteTimeSpan; + _timeout = null; _username = null; _useTls = false; _w = null; @@ -969,12 +969,10 @@ public override string ToString() { query.AppendFormat("socketTimeout={0}&", FormatTimeSpan(_socketTimeout)); } - if (_timeout.HasValue) { query.AppendFormat("timeout={0}&", FormatTimeSpan(_timeout.Value)); } - #pragma warning disable 618 if (_waitQueueMultiple != 0.0 && _waitQueueMultiple != MongoDefaults.WaitQueueMultiple) #pragma warning restore 618 @@ -1064,7 +1062,7 @@ private void InitializeFromConnectionString(ConnectionString connectionString) _socketTimeout = connectionString.SocketTimeout.GetValueOrDefault(MongoDefaults.SocketTimeout); _srvMaxHosts = connectionString.SrvMaxHosts; _srvServiceName = connectionString.SrvServiceName ?? MongoInternalDefaults.MongoClientSettings.SrvServiceName; - _timeout = connectionString.Timeout.GetValueOrDefault(System.Threading.Timeout.InfiniteTimeSpan); + _timeout = connectionString.Timeout; _tlsDisableCertificateRevocationCheck = connectionString.TlsDisableCertificateRevocationCheck; _username = connectionString.Username; _useTls = connectionString.Tls.GetValueOrDefault(false); @@ -1085,11 +1083,6 @@ private void InitializeFromConnectionString(ConnectionString connectionString) _wTimeout = connectionString.WTimeout; } - private bool AnyWriteConcernSettingsAreSet() - { - return _fsync != null || _journal != null || _w != null || _wTimeout != null; - } - private string FormatTimeSpan(TimeSpan value) { const int msInOneSecond = 1000; // milliseconds diff --git a/src/MongoDB.Driver/OperationContext.cs b/src/MongoDB.Driver/OperationContext.cs index ac6e7737dd9..d2a18e6e729 100644 --- a/src/MongoDB.Driver/OperationContext.cs +++ b/src/MongoDB.Driver/OperationContext.cs @@ -24,7 +24,7 @@ namespace MongoDB.Driver internal sealed class OperationContext : IDisposable { // TODO: this static field is temporary here and will be removed in a future PRs in scope of CSOT. - public static readonly OperationContext NoTimeout = new(System.Threading.Timeout.InfiniteTimeSpan, CancellationToken.None); + public static readonly OperationContext NoTimeout = new(null, CancellationToken.None); private CancellationTokenSource _remainingTimeoutCancellationTokenSource; private CancellationTokenSource _combinedCancellationTokenSource; @@ -37,7 +37,7 @@ public OperationContext(TimeSpan? timeout, CancellationToken cancellationToken) internal OperationContext(Stopwatch stopwatch, TimeSpan? timeout, CancellationToken cancellationToken) { Stopwatch = stopwatch; - Timeout = Ensure.IsNullOrValidTimeout(timeout, nameof(timeout)); + Timeout = Ensure.IsNullOrInfiniteOrGreaterThanOrEqualToZero(timeout, nameof(timeout)); CancellationToken = cancellationToken; RootContext = this; } diff --git a/tests/MongoDB.Driver.Tests/Core/Operations/AggregateOperationTests.cs b/tests/MongoDB.Driver.Tests/Core/Operations/AggregateOperationTests.cs index cf3cc8b3206..cd6292147d7 100644 --- a/tests/MongoDB.Driver.Tests/Core/Operations/AggregateOperationTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Operations/AggregateOperationTests.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -308,7 +308,7 @@ public void CreateCommand_should_return_the_expected_result() var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -334,7 +334,7 @@ public void CreateCommand_should_return_the_expected_result_when_AllowDiskUse_is var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -359,7 +359,7 @@ public void CreateCommand_should_return_the_expected_result_when_BatchSize_is_se var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var cursor = new BsonDocument { @@ -389,7 +389,7 @@ public void CreateCommand_should_return_the_expected_result_when_Collation_is_se var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -415,7 +415,7 @@ public void CreateCommand_should_return_expected_result_when_Comment_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -442,7 +442,7 @@ public void CreateCommand_should_return_the_expected_result_when_Hint_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -469,7 +469,7 @@ public void CreateCommand_should_return_expected_result_when_Let_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(Feature.AggregateOptionsLet.FirstSupportedWireVersion); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -497,7 +497,7 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_set(long var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -510,6 +510,24 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_set(long result["maxTimeMS"].BsonType.Should().Be(BsonType.Int32); } + [Theory] + [InlineData(42)] + [InlineData(-1)] + public void CreateCommand_should_ignore_maxtime_if_timeout_specified(int timeoutMs) + { + var subject = new AggregateOperation(_collectionNamespace, __pipeline, __resultSerializer, _messageEncoderSettings) + { + MaxTime = TimeSpan.FromSeconds(10) + }; + var connectionDescription = OperationTestHelper.CreateConnectionDescription(); + var session = OperationTestHelper.CreateSession(); + + var operationContext = new OperationContext(TimeSpan.FromMilliseconds(timeoutMs), CancellationToken.None); + var result = subject.CreateCommand(operationContext, session, connectionDescription); + + result.Should().NotContain("maxTimeMS"); + } + [Theory] [ParameterAttributeData] public void CreateCommand_should_return_the_expected_result_when_ReadConcern_is_set( @@ -525,7 +543,7 @@ public void CreateCommand_should_return_the_expected_result_when_ReadConcern_is_ var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -552,7 +570,7 @@ public void CreateCommand_should_return_the_expected_result_when_using_causal_co var connectionDescription = OperationTestHelper.CreateConnectionDescription(supportsSessions: true); var session = OperationTestHelper.CreateSession(true, new BsonTimestamp(100)); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedReadConcernDocument = readConcern.ToBsonDocument(); expectedReadConcernDocument["afterClusterTime"] = new BsonTimestamp(100); diff --git a/tests/MongoDB.Driver.Tests/Core/Operations/AggregateToCollectionOperationTests.cs b/tests/MongoDB.Driver.Tests/Core/Operations/AggregateToCollectionOperationTests.cs index b45edc47149..dc202ef4679 100644 --- a/tests/MongoDB.Driver.Tests/Core/Operations/AggregateToCollectionOperationTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Operations/AggregateToCollectionOperationTests.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ using System.Collections.Generic; using System.Linq; using System.Net; +using System.Threading; using System.Threading.Tasks; using FluentAssertions; using MongoDB.Bson; @@ -306,7 +307,7 @@ public void CreateCommand_should_return_expected_result() var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -330,7 +331,7 @@ public void CreateCommand_should_return_expected_result_when_AllowDiskUse_is_set var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -355,7 +356,7 @@ public void CreateCommand_should_return_expected_result_when_BypassDocumentValid var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -381,7 +382,7 @@ public void CreateCommand_should_return_expected_result_when_Collation_is_set( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -406,7 +407,7 @@ public void CreateCommand_should_return_expected_result_when_Comment_is_set( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -432,7 +433,7 @@ public void CreateCommand_should_return_the_expected_result_when_Hint_is_set( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -458,7 +459,7 @@ public void CreateCommand_should_return_the_expected_result_when_Let_is_set( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -486,7 +487,7 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_set(long var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -499,6 +500,24 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_set(long result["maxTimeMS"].BsonType.Should().Be(BsonType.Int32); } + [Theory] + [InlineData(42)] + [InlineData(-1)] + public void CreateCommand_should_ignore_maxtime_if_timeout_specified(int timeoutMs) + { + var subject = new AggregateToCollectionOperation(_collectionNamespace, __pipeline, _messageEncoderSettings) + { + MaxTime = TimeSpan.FromSeconds(10) + }; + var session = OperationTestHelper.CreateSession(); + var connectionDescription = OperationTestHelper.CreateConnectionDescription(); + + var operationContext = new OperationContext(TimeSpan.FromMilliseconds(timeoutMs), CancellationToken.None); + var result = subject.CreateCommand(operationContext, session, connectionDescription); + + result.Should().NotContain("maxTimeMS"); + } + [Theory] [ParameterAttributeData] public void CreateCommand_should_return_expected_result_when_ReadConcern_is_set( @@ -513,7 +532,7 @@ public void CreateCommand_should_return_expected_result_when_ReadConcern_is_set( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -539,7 +558,7 @@ public void CreateCommand_should_return_expected_result_when_WriteConcern_is_set var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { diff --git a/tests/MongoDB.Driver.Tests/Core/Operations/CountOperationTests.cs b/tests/MongoDB.Driver.Tests/Core/Operations/CountOperationTests.cs index 0d930fbf801..e1a5e6d7622 100644 --- a/tests/MongoDB.Driver.Tests/Core/Operations/CountOperationTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Operations/CountOperationTests.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ */ using System; +using System.Threading; using System.Threading.Tasks; using FluentAssertions; using MongoDB.Bson; @@ -202,7 +203,7 @@ public void CreateCommand_should_return_expected_result() var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -225,7 +226,7 @@ public void CreateCommand_should_return_expected_result_when_Comment_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -250,7 +251,7 @@ public void CreateCommand_should_return_expected_result_when_Collation_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -275,7 +276,7 @@ public void CreateCommand_should_return_expected_result_when_Filter_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -300,7 +301,7 @@ public void CreateCommand_should_return_expected_result_when_Hint_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -324,7 +325,7 @@ public void CreateCommand_should_return_expected_result_when_Limit_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -350,7 +351,7 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_set(long var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -361,6 +362,24 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_set(long result["maxTimeMS"].BsonType.Should().Be(BsonType.Int32); } + [Theory] + [InlineData(42)] + [InlineData(-1)] + public void CreateCommand_should_ignore_maxtime_if_timeout_specified(int timeoutMs) + { + var subject = new CountOperation(_collectionNamespace, _messageEncoderSettings) + { + MaxTime = TimeSpan.FromTicks(10) + }; + var connectionDescription = OperationTestHelper.CreateConnectionDescription(); + var session = OperationTestHelper.CreateSession(); + + var operationContext = new OperationContext(TimeSpan.FromMilliseconds(timeoutMs), CancellationToken.None); + var result = subject.CreateCommand(operationContext, session, connectionDescription); + + result.Should().NotContain("maxTimeMS"); + } + [Theory] [ParameterAttributeData] public void CreateCommand_should_return_expected_result_when_ReadConcern_is_set( @@ -376,7 +395,7 @@ public void CreateCommand_should_return_expected_result_when_ReadConcern_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -401,7 +420,7 @@ public void CreateCommand_should_return_the_expected_result_when_using_causal_co var connectionDescription = OperationTestHelper.CreateConnectionDescription(supportsSessions: true); var session = OperationTestHelper.CreateSession(true, new BsonTimestamp(100)); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedReadConcernDocument = readConcern.ToBsonDocument(); expectedReadConcernDocument["afterClusterTime"] = new BsonTimestamp(100); @@ -428,7 +447,7 @@ public void CreateCommand_should_return_expected_result_when_Skip_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { diff --git a/tests/MongoDB.Driver.Tests/Core/Operations/CreateCollectionOperationTests.cs b/tests/MongoDB.Driver.Tests/Core/Operations/CreateCollectionOperationTests.cs index a89f27c1a0a..bac15cbae75 100644 --- a/tests/MongoDB.Driver.Tests/Core/Operations/CreateCollectionOperationTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Operations/CreateCollectionOperationTests.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ using System; using System.Linq; -using System.Threading; using System.Threading.Tasks; using FluentAssertions; using MongoDB.Bson; @@ -476,7 +475,7 @@ void AssertCommand((IWriteOperation Operation, bool IsMainOperatio var result = operation switch { CreateCollectionOperation createCollectionOperation => createCollectionOperation.CreateCommand(session), - CreateIndexesOperation createIndexesOperation => createIndexesOperation.CreateCommand(session, OperationTestHelper.CreateConnectionDescription()), + CreateIndexesOperation createIndexesOperation => createIndexesOperation.CreateCommand(OperationContext.NoTimeout, session, OperationTestHelper.CreateConnectionDescription()), _ => throw new Exception($"Unexpected operation {operation}."), }; result.Should().Be(expectedResult); diff --git a/tests/MongoDB.Driver.Tests/Core/Operations/CreateIndexesOperationTests.cs b/tests/MongoDB.Driver.Tests/Core/Operations/CreateIndexesOperationTests.cs index b6d385e80cb..7ae617e7cc3 100644 --- a/tests/MongoDB.Driver.Tests/Core/Operations/CreateIndexesOperationTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Operations/CreateIndexesOperationTests.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; using FluentAssertions; using MongoDB.Bson; @@ -92,7 +93,7 @@ public void CreateCommand_should_return_expected_result_when_creating_one_index( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -114,7 +115,7 @@ public void CreateCommand_should_return_expected_result_when_creating_two_indexe var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -138,7 +139,7 @@ public void CreateCommand_should_return_expected_result_when_CommitQuorum_with_m var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(Feature.CreateIndexCommitQuorum.FirstSupportedWireVersion); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -164,7 +165,7 @@ public void CreateCommand_should_return_expected_result_when_CommitQuorum_with_w var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(Feature.CreateIndexCommitQuorum.FirstSupportedWireVersion); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -186,12 +187,14 @@ public void CreateCommand_should_return_expected_result_when_CommitQuorum_with_w public void CreateCommand_should_return_expected_result_when_MaxTime_is_Set(long maxTimeTicks, int expectedMaxTimeMS) { var requests = new[] { new CreateIndexRequest(new BsonDocument("x", 1)) }; - var subject = new CreateIndexesOperation(_collectionNamespace, requests, _messageEncoderSettings); - subject.MaxTime = TimeSpan.FromTicks(maxTimeTicks); + var subject = new CreateIndexesOperation(_collectionNamespace, requests, _messageEncoderSettings) + { + MaxTime = TimeSpan.FromTicks(maxTimeTicks) + }; var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -203,6 +206,25 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_Set(long result["maxTimeMS"].BsonType.Should().Be(BsonType.Int32); } + [Theory] + [InlineData(42)] + [InlineData(-1)] + public void CreateCommand_should_ignore_maxtime_if_timeout_specified(int timeoutMs) + { + var requests = new[] { new CreateIndexRequest(new BsonDocument("x", 1)) }; + var subject = new CreateIndexesOperation(_collectionNamespace, requests, _messageEncoderSettings) + { + MaxTime = TimeSpan.FromTicks(10) + }; + var session = OperationTestHelper.CreateSession(); + var connectionDescription = OperationTestHelper.CreateConnectionDescription(); + + var operationContext = new OperationContext(TimeSpan.FromMilliseconds(timeoutMs), CancellationToken.None); + var result = subject.CreateCommand(operationContext, session, connectionDescription); + + result.Should().NotContain("maxTimeMS"); + } + [Theory] [ParameterAttributeData] public void CreateCommand_should_return_expected_result_when_WriteConcern_is_set( @@ -218,7 +240,7 @@ public void CreateCommand_should_return_expected_result_when_WriteConcern_is_set var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -241,7 +263,7 @@ public void CreateCommand_should_throw_when_commitQuorum_is_specified_and_not_su var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(Feature.CreateIndexCommitQuorum.LastNotSupportedWireVersion); - var exception = Record.Exception(() => subject.CreateCommand(session, connectionDescription)); + var exception = Record.Exception(() => subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription)); exception.Should().BeOfType(); } diff --git a/tests/MongoDB.Driver.Tests/Core/Operations/DistinctOperationTests.cs b/tests/MongoDB.Driver.Tests/Core/Operations/DistinctOperationTests.cs index 1c89d5c9eb4..2fc426b15ff 100644 --- a/tests/MongoDB.Driver.Tests/Core/Operations/DistinctOperationTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Operations/DistinctOperationTests.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ */ using System; +using System.Threading; using System.Threading.Tasks; using FluentAssertions; using MongoDB.Bson; @@ -186,7 +187,7 @@ public void CreateCommand_should_return_expected_result() var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -211,7 +212,7 @@ public void CreateCommand_should_return_expected_result_when_Collation_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -237,7 +238,7 @@ public void CreateCommand_should_return_expected_result_when_Filter_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -265,7 +266,7 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_set(long var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -277,6 +278,24 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_set(long result["maxTimeMS"].BsonType.Should().Be(BsonType.Int32); } + [Theory] + [InlineData(42)] + [InlineData(-1)] + public void CreateCommand_should_ignore_maxtime_if_timeout_specified(int timeoutMs) + { + var subject = new DistinctOperation(_collectionNamespace, _valueSerializer, _fieldName, _messageEncoderSettings) + { + MaxTime = TimeSpan.FromTicks(10) + }; + var session = OperationTestHelper.CreateSession(); + var connectionDescription = OperationTestHelper.CreateConnectionDescription(); + + var operationContext = new OperationContext(TimeSpan.FromMilliseconds(timeoutMs), CancellationToken.None); + var result = subject.CreateCommand(operationContext, session, connectionDescription); + + result.Should().NotContain("maxTimeMS"); + } + [Theory] [ParameterAttributeData] public void CreateCommand_should_return_expected_result_when_ReadConcern_is_set( @@ -292,7 +311,7 @@ public void CreateCommand_should_return_expected_result_when_ReadConcern_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -318,7 +337,7 @@ public void CreateCommand_should_return_the_expected_result_when_using_causal_co var connectionDescription = OperationTestHelper.CreateConnectionDescription(supportsSessions: true); var session = OperationTestHelper.CreateSession(true, new BsonTimestamp(100)); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedReadConcernDocument = readConcern.ToBsonDocument(); expectedReadConcernDocument["afterClusterTime"] = new BsonTimestamp(100); diff --git a/tests/MongoDB.Driver.Tests/Core/Operations/DropIndexOperationTests.cs b/tests/MongoDB.Driver.Tests/Core/Operations/DropIndexOperationTests.cs index be3f8dc584a..4c0d2de63be 100644 --- a/tests/MongoDB.Driver.Tests/Core/Operations/DropIndexOperationTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Operations/DropIndexOperationTests.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ using System; using System.Linq; +using System.Threading; using System.Threading.Tasks; using FluentAssertions; using MongoDB.Bson; @@ -56,29 +57,30 @@ public void constructor_with_collectionNamespace_indexName_messageEncoderSetting [Fact] public void constructor_with_collectionNamespace_indexName_messageEncoderSettings_should_throw_when_collectionNamespace_is_null() { - var indexName = "x_1"; - - Action action = () => { new DropIndexOperation(null, indexName, _messageEncoderSettings); }; + var exception = Record.Exception(() => { new DropIndexOperation(null, "x_1", _messageEncoderSettings); }); - action.ShouldThrow().And.ParamName.Should().Be("collectionNamespace"); + exception.Should().BeOfType().Subject + .ParamName.Should().Be("collectionNamespace"); } - [Fact] - public void constructor_with_collectionNamespace_indexName_messageEncoderSettings_should_throw_when_indexName_is_null() + [Theory] + [InlineData(null)] + [InlineData("")] + public void constructor_with_collectionNamespace_indexName_messageEncoderSettings_should_throw_when_indexName_is_empty(string indexName) { - Action action = () => { new DropIndexOperation(_collectionNamespace, (string)null, _messageEncoderSettings); }; + var exception = Record.Exception(() => { new DropIndexOperation(_collectionNamespace, indexName, _messageEncoderSettings); }); - action.ShouldThrow().And.ParamName.Should().Be("indexName"); + exception.Should().BeOfType().Subject + .ParamName.Should().Be("indexName"); } [Fact] public void constructor_with_collectionNamespace_indexName_messageEncoderSettings_should_throw_when_messageEncoderSettings_is_null() { - var indexName = "x_1"; + var exception = Record.Exception(() => { new DropIndexOperation(_collectionNamespace, "x_1", null); }); - Action action = () => { new DropIndexOperation(_collectionNamespace, indexName, null); }; - - action.ShouldThrow().And.ParamName.Should().Be("messageEncoderSettings"); + exception.Should().BeOfType().Subject + .ParamName.Should().Be("messageEncoderSettings"); } [Fact] @@ -100,17 +102,19 @@ public void constructor_with_collectionNamespace_keys_messageEncoderSettings_sho { var keys = new BsonDocument { { "x", 1 } }; - Action action = () => { new DropIndexOperation(null, keys, _messageEncoderSettings); }; + var exception = Record.Exception(() => { new DropIndexOperation(null, keys, _messageEncoderSettings); }); - action.ShouldThrow().And.ParamName.Should().Be("collectionNamespace"); + exception.Should().BeOfType().Subject + .ParamName.Should().Be("collectionNamespace"); } [Fact] public void constructor_with_collectionNamespace_keys_messageEncoderSettings_should_throw_when_indexName_is_null() { - Action action = () => { new DropIndexOperation(_collectionNamespace, (BsonDocument)null, _messageEncoderSettings); }; + var exception = Record.Exception(() => { new DropIndexOperation(_collectionNamespace, (BsonDocument)null, _messageEncoderSettings); }); - action.ShouldThrow().And.ParamName.Should().Be("keys"); + exception.Should().BeOfType().Subject + .ParamName.Should().Be("keys"); } [Fact] @@ -118,9 +122,10 @@ public void constructor_with_collectionNamespace_keys_messageEncoderSettings_sho { var keys = new BsonDocument { { "x", 1 } }; - Action action = () => { new DropIndexOperation(_collectionNamespace, keys, null); }; + var exception = Record.Exception(() => { new DropIndexOperation(_collectionNamespace, keys, null); }); - action.ShouldThrow().And.ParamName.Should().Be("messageEncoderSettings"); + exception.Should().BeOfType().Subject + .ParamName.Should().Be("messageEncoderSettings"); } [Fact] @@ -135,7 +140,7 @@ public void CreateCommand_should_return_expectedResult() }; var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session); result.Should().Be(expectedResult); } @@ -151,21 +156,40 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_Set(long { var indexName = "x_1"; var maxTime = TimeSpan.FromTicks(maxTimeTicks); - var subject = new DropIndexOperation(_collectionNamespace, indexName, _messageEncoderSettings); - subject.MaxTime = maxTime; + var subject = new DropIndexOperation(_collectionNamespace, indexName, _messageEncoderSettings) + { + MaxTime = maxTime + }; var expectedResult = new BsonDocument { { "dropIndexes", _collectionNamespace.CollectionName }, { "index", indexName }, - {"maxTimeMS", expectedMaxTimeMS } + { "maxTimeMS", expectedMaxTimeMS } }; var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session); result.Should().Be(expectedResult); result["maxTimeMS"].BsonType.Should().Be(BsonType.Int32); + } + + [Theory] + [InlineData(42)] + [InlineData(-1)] + public void CreateCommand_should_ignore_maxtime_if_timeout_specified(int timeoutMs) + { + var indexName = "x_1"; + var subject = new DropIndexOperation(_collectionNamespace, indexName, _messageEncoderSettings) + { + MaxTime = TimeSpan.FromSeconds(10) + }; + var session = OperationTestHelper.CreateSession(); + + var operationContext = new OperationContext(TimeSpan.FromMilliseconds(timeoutMs), CancellationToken.None); + var result = subject.CreateCommand(operationContext, session); + result.Should().NotContain("maxTimeMS"); } [Theory] @@ -181,9 +205,8 @@ public void CreateCommand_should_return_expectedResult_when_WriteConcern_is_set( WriteConcern = writeConcern }; var session = OperationTestHelper.CreateSession(); - var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session); var expectedResult = new BsonDocument { diff --git a/tests/MongoDB.Driver.Tests/Core/Operations/EstimatedDocumentCountOperationTests.cs b/tests/MongoDB.Driver.Tests/Core/Operations/EstimatedDocumentCountOperationTests.cs index 14e9ce31484..bc947aabc96 100644 --- a/tests/MongoDB.Driver.Tests/Core/Operations/EstimatedDocumentCountOperationTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Operations/EstimatedDocumentCountOperationTests.cs @@ -1,4 +1,4 @@ -/* Copyright 2021-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -328,7 +328,7 @@ private void AssertCommandDocument(BsonDocument actualResult, int? expectedMaxTi private BsonDocument CreateCommand(EstimatedDocumentCountOperation subject, ConnectionDescription connectionDescription, ICoreSession session) { var countOperation = (CountOperation)subject.CreateCountOperation(); - return countOperation.CreateCommand(connectionDescription, session); + return countOperation.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); } private void EnsureTestData() diff --git a/tests/MongoDB.Driver.Tests/Core/Operations/FindOneAndDeleteOperationTests.cs b/tests/MongoDB.Driver.Tests/Core/Operations/FindOneAndDeleteOperationTests.cs index ff475667efe..61878488ea2 100644 --- a/tests/MongoDB.Driver.Tests/Core/Operations/FindOneAndDeleteOperationTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Operations/FindOneAndDeleteOperationTests.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ */ using System; +using System.Threading; using System.Threading.Tasks; using FluentAssertions; using MongoDB.Bson; @@ -121,7 +122,7 @@ public void CreateCommand_should_return_expected_result_when_Hint_is_set( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(Feature.HintForFindAndModifyFeature.FirstSupportedWireVersion); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -293,7 +294,7 @@ public void CreateCommand_should_return_the_expected_result( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, transactionNumber); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, transactionNumber); var expectedResult = new BsonDocument { @@ -320,7 +321,7 @@ public void CreateCommand_should_return_the_expected_result_when_Collation_is_se var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -348,7 +349,7 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_set(long var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -361,6 +362,24 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_set(long result["maxTimeMS"].BsonType.Should().Be(BsonType.Int32); } + [Theory] + [InlineData(42)] + [InlineData(-1)] + public void CreateCommand_should_ignore_maxtime_if_timeout_specified(int timeoutMs) + { + var subject = new FindOneAndDeleteOperation(_collectionNamespace, _filter, BsonDocumentSerializer.Instance, _messageEncoderSettings) + { + MaxTime = TimeSpan.FromTicks(10) + }; + var session = OperationTestHelper.CreateSession(); + var connectionDescription = OperationTestHelper.CreateConnectionDescription(); + + var operationContext = new OperationContext(TimeSpan.FromMilliseconds(timeoutMs), CancellationToken.None); + var result = subject.CreateCommand(operationContext, session, connectionDescription, null); + + result.Should().NotContain("maxTimeMS"); + } + [Theory] [ParameterAttributeData] public void CreateCommand_should_return_the_expected_result_when_Projection_is_set( @@ -375,7 +394,7 @@ public void CreateCommand_should_return_the_expected_result_when_Projection_is_s var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -401,7 +420,7 @@ public void CreateCommand_should_return_the_expected_result_when_Sort_is_set( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -427,7 +446,7 @@ public void CreateCommand_should_return_the_expected_result_when_WriteConcern_is var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { diff --git a/tests/MongoDB.Driver.Tests/Core/Operations/FindOneAndReplaceOperationTests.cs b/tests/MongoDB.Driver.Tests/Core/Operations/FindOneAndReplaceOperationTests.cs index f201c3664ba..2f76e17ad86 100644 --- a/tests/MongoDB.Driver.Tests/Core/Operations/FindOneAndReplaceOperationTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Operations/FindOneAndReplaceOperationTests.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ */ using System; +using System.Threading; using System.Threading.Tasks; using FluentAssertions; using MongoDB.Bson; @@ -280,7 +281,7 @@ public void CreateCommand_should_return_expected_result( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, transactionNumber); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, transactionNumber); var expectedResult = new BsonDocument { @@ -306,7 +307,7 @@ public void CreateCommand_should_return_expected_result_when_BypassDocumentValid var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -332,7 +333,7 @@ public void CreateCommand_should_return_expected_result_when_Collation_is_set( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -357,7 +358,7 @@ public void CreateCommand_should_return_expected_result_when_Hint_is_set( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(Feature.HintForFindAndModifyFeature.FirstSupportedWireVersion); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -382,7 +383,7 @@ public void CreateCommand_should_return_expected_result_when_IsUpsert_is_set( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -410,7 +411,7 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_set(long var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -423,6 +424,24 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_set(long result["maxTimeMS"].BsonType.Should().Be(BsonType.Int32); } + [Theory] + [InlineData(42)] + [InlineData(-1)] + public void CreateCommand_should_ignore_maxtime_if_timeout_specified(int timeoutMs) + { + var subject = new FindOneAndReplaceOperation(_collectionNamespace, _filter, _replacement, BsonDocumentSerializer.Instance, _messageEncoderSettings) + { + MaxTime = TimeSpan.FromTicks(10) + }; + var session = OperationTestHelper.CreateSession(); + var connectionDescription = OperationTestHelper.CreateConnectionDescription(); + + var operationContext = new OperationContext(TimeSpan.FromMilliseconds(timeoutMs), CancellationToken.None); + var result = subject.CreateCommand(operationContext, session, connectionDescription, null); + + result.Should().NotContain("maxTimeMS"); + } + [Theory] [ParameterAttributeData] public void CreateCommand_should_return_expected_result_when_Projection_is_set( @@ -437,7 +456,7 @@ public void CreateCommand_should_return_expected_result_when_Projection_is_set( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -462,7 +481,7 @@ public void CreateCommand_should_return_expected_result_when_ReturnDocument_is_s var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -488,7 +507,7 @@ public void CreateCommand_should_return_expected_result_when_Sort_is_set( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -514,7 +533,7 @@ public void CreateCommand_should_return_expected_result_when_WriteConcern_is_set var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { diff --git a/tests/MongoDB.Driver.Tests/Core/Operations/FindOneAndUpdateOperationTests.cs b/tests/MongoDB.Driver.Tests/Core/Operations/FindOneAndUpdateOperationTests.cs index 3a621869207..4bb1568adf6 100644 --- a/tests/MongoDB.Driver.Tests/Core/Operations/FindOneAndUpdateOperationTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Operations/FindOneAndUpdateOperationTests.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ */ using System; +using System.Threading; using System.Threading.Tasks; using FluentAssertions; using MongoDB.Bson; @@ -274,7 +275,7 @@ public void CreateCommand_should_return_expected_result( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, transactionNumber); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, transactionNumber); var expectedResult = new BsonDocument { @@ -300,7 +301,7 @@ public void CreateCommand_should_return_expected_result_when_BypassDocumentValid var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -326,7 +327,7 @@ public void CreateCommand_should_return_expected_result_when_Collation_is_set( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -351,7 +352,7 @@ public void CreateCommand_should_return_expected_result_when_Hint_is_set( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(Feature.HintForFindAndModifyFeature.FirstSupportedWireVersion); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -376,7 +377,7 @@ public void CreateCommand_should_return_expected_result_when_IsUpsert_is_set( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -404,7 +405,7 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_set(long var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -417,6 +418,25 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_set(long result["maxTimeMS"].BsonType.Should().Be(BsonType.Int32); } + [Theory] + [InlineData(42)] + [InlineData(-1)] + public void CreateCommand_should_ignore_maxtime_if_timeout_specified(int timeoutMs) + { + var subject = new FindOneAndUpdateOperation(_collectionNamespace, _filter, _update, BsonDocumentSerializer.Instance, _messageEncoderSettings) + { + MaxTime = TimeSpan.FromTicks(10) + }; + var session = OperationTestHelper.CreateSession(); + var connectionDescription = OperationTestHelper.CreateConnectionDescription(); + + + var operationContext = new OperationContext(TimeSpan.FromMilliseconds(timeoutMs), CancellationToken.None); + var result = subject.CreateCommand(operationContext, session, connectionDescription, null); + + result.Should().NotContain("maxTimeMS"); + } + [Theory] [ParameterAttributeData] public void CreateCommand_should_return_expected_result_when_Projection_is_set( @@ -431,7 +451,7 @@ public void CreateCommand_should_return_expected_result_when_Projection_is_set( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -456,7 +476,7 @@ public void CreateCommand_should_return_expected_result_when_ReturnDocument_is_s var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -482,7 +502,7 @@ public void CreateCommand_should_return_expected_result_when_Sort_is_set( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { @@ -508,7 +528,7 @@ public void CreateCommand_should_return_expected_result_when_WriteConcern_is_set var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription, null); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription, null); var expectedResult = new BsonDocument { diff --git a/tests/MongoDB.Driver.Tests/Core/Operations/FindOperationTests.cs b/tests/MongoDB.Driver.Tests/Core/Operations/FindOperationTests.cs index 793ecdb6459..e540885a514 100644 --- a/tests/MongoDB.Driver.Tests/Core/Operations/FindOperationTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Operations/FindOperationTests.cs @@ -1,4 +1,4 @@ -/* Copyright 2015-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ */ using System; +using System.Threading; using System.Threading.Tasks; using FluentAssertions; using MongoDB.Bson; @@ -191,7 +192,7 @@ public void CreateCommand_should_return_expected_result() var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -216,7 +217,7 @@ public void CreateCommand_should_return_expected_result_when_AllowDiskUse_is_set var connectionDescription = OperationTestHelper.CreateConnectionDescription(serverType: serverType); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -242,7 +243,7 @@ public void CreateCommand_should_return_expected_result_when_AllowPartialResults var connectionDescription = OperationTestHelper.CreateConnectionDescription(serverType: serverType); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -267,7 +268,7 @@ public void CreateCommand_should_return_expected_result_when_Collation_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -291,7 +292,7 @@ public void CreateCommand_should_return_expected_result_when_Comment_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -315,7 +316,7 @@ public void CreateCommand_should_return_expected_result_when_CursorType_is_Set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -341,7 +342,7 @@ public void CreateCommand_should_return_expected_result_when_Filter_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -366,7 +367,7 @@ public void CreateCommand_should_return_expected_result_when_Hint_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -393,7 +394,7 @@ public void CreateCommand_should_return_expected_result_when_Limit_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -419,7 +420,7 @@ public void CreateCommand_should_return_expected_result_when_Max_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -445,7 +446,7 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_set(long var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -456,6 +457,24 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_set(long result["maxTimeMS"].BsonType.Should().Be(BsonType.Int32); } + [Theory] + [InlineData(42)] + [InlineData(-1)] + public void CreateCommand_should_ignore_maxtime_if_timeout_specified(int timeoutMs) + { + var subject = new FindOperation(_collectionNamespace, BsonDocumentSerializer.Instance, _messageEncoderSettings) + { + MaxTime = TimeSpan.FromTicks(10) + }; + var connectionDescription = OperationTestHelper.CreateConnectionDescription(); + var session = OperationTestHelper.CreateSession(); + + var operationContext = new OperationContext(TimeSpan.FromMilliseconds(timeoutMs), CancellationToken.None); + var result = subject.CreateCommand(operationContext, session, connectionDescription); + + result.Should().NotContain("maxTimeMS"); + } + [Theory] [ParameterAttributeData] public void CreateCommand_should_return_expected_result_when_Min_is_set( @@ -471,7 +490,7 @@ public void CreateCommand_should_return_expected_result_when_Min_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -495,7 +514,7 @@ public void CreateCommand_should_return_expected_result_when_NoCursorTimeout_is_ var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -521,7 +540,7 @@ public void CreateCommand_should_return_expected_result_when_OplogReplay_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -546,7 +565,7 @@ public void CreateCommand_should_return_expected_result_when_Projection_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -571,7 +590,7 @@ public void CreateCommand_should_return_expected_result_when_ReadConcern_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -595,7 +614,7 @@ public void CreateCommand_should_return_expected_result_when_ReturnKey_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -619,7 +638,7 @@ public void CreateCommand_should_return_expected_result_when_ShowRecordId_is_set var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -643,7 +662,7 @@ public void CreateCommand_should_return_expected_result_when_Skip_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -668,7 +687,7 @@ public void CreateCommand_should_return_expected_result_when_Sort_is_set( var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -693,7 +712,7 @@ public void CreateCommand_should_return_the_expected_result_when_using_causal_co var connectionDescription = OperationTestHelper.CreateConnectionDescription(supportsSessions: true); var session = OperationTestHelper.CreateSession(true, new BsonTimestamp(100)); - var result = subject.CreateCommand(connectionDescription, session); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedReadConcernDocument = readConcern.ToBsonDocument(); expectedReadConcernDocument["afterClusterTime"] = new BsonTimestamp(100); diff --git a/tests/MongoDB.Driver.Tests/Core/Operations/MapReduceOperationBaseTests.cs b/tests/MongoDB.Driver.Tests/Core/Operations/MapReduceOperationBaseTests.cs index 4213fdeffb4..8840542784f 100644 --- a/tests/MongoDB.Driver.Tests/Core/Operations/MapReduceOperationBaseTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Operations/MapReduceOperationBaseTests.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,10 +14,10 @@ */ using System; +using System.Threading; using FluentAssertions; using MongoDB.Bson; using MongoDB.TestHelpers.XunitExtensions; -using MongoDB.Driver.Core.Misc; using MongoDB.Driver.Core.WireProtocol.Messages.Encoders; using Xunit; @@ -125,7 +125,7 @@ public void CreateCommand_should_return_the_expected_result() var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -152,7 +152,7 @@ public void CreateCommand_should_return_the_expected_result_when_Collation_is_pr var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -179,7 +179,7 @@ public void CreateCommand_should_return_the_expected_result_when_Filter_is_provi var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -206,7 +206,7 @@ public void CreateCommand_should_return_the_expected_result_when_FinalizeFunctio var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -234,7 +234,7 @@ public void CreateCommand_should_return_the_expected_result_when_JavaScriptMode_ var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -260,7 +260,7 @@ public void CreateCommand_should_return_the_expected_result_when_Limit_is_provid var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -289,7 +289,7 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_set(long var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -303,6 +303,24 @@ public void CreateCommand_should_return_expected_result_when_MaxTime_is_set(long result["maxTimeMS"].BsonType.Should().Be(BsonType.Int32); } + [Theory] + [InlineData(42)] + [InlineData(-1)] + public void CreateCommand_should_ignore_maxtime_if_timeout_specified(int timeoutMs) + { + var subject = new FakeMapReduceOperation(_collectionNamespace, _mapFunction, _reduceFunction, _messageEncoderSettings) + { + MaxTime = TimeSpan.FromTicks(10) + }; + var session = OperationTestHelper.CreateSession(); + var connectionDescription = OperationTestHelper.CreateConnectionDescription(); + + var operationContext = new OperationContext(TimeSpan.FromMilliseconds(timeoutMs), CancellationToken.None); + var result = subject.CreateCommand(operationContext, session, connectionDescription); + + result.Should().NotContain("maxTimeMS"); + } + [Theory] [ParameterAttributeData] public void CreateCommand_should_return_the_expected_result_when_Scope_is_provided( @@ -317,7 +335,7 @@ public void CreateCommand_should_return_the_expected_result_when_Scope_is_provid var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -344,7 +362,7 @@ public void CreateCommand_should_return_the_expected_result_when_Sort_is_provide var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -370,7 +388,7 @@ public void CreateCommand_should_return_the_expected_result_when_Verbose_is_prov var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { diff --git a/tests/MongoDB.Driver.Tests/Core/Operations/MapReduceOperationTests.cs b/tests/MongoDB.Driver.Tests/Core/Operations/MapReduceOperationTests.cs index 27caafdb348..dfc5d489c68 100644 --- a/tests/MongoDB.Driver.Tests/Core/Operations/MapReduceOperationTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Operations/MapReduceOperationTests.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -507,7 +507,7 @@ public void CreateCommand_should_return_expected_result_when_ReadConcern_is_set( var session = OperationTestHelper.CreateSession(); var connectionDescription = OperationTestHelper.CreateConnectionDescription(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -536,7 +536,7 @@ public void CreateCommand_should_return_the_expected_result_when_using_causal_co var session = OperationTestHelper.CreateSession(isCausallyConsistent: true, operationTime: new BsonTimestamp(100)); var connectionDescription = OperationTestHelper.CreateConnectionDescription(supportsSessions: true); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedReadConcernDocument = readConcern.ToBsonDocument(); expectedReadConcernDocument["afterClusterTime"] = new BsonTimestamp(100); diff --git a/tests/MongoDB.Driver.Tests/Core/Operations/MapReduceOutputToCollectionOperationTests.cs b/tests/MongoDB.Driver.Tests/Core/Operations/MapReduceOutputToCollectionOperationTests.cs index 5255ae0d989..beeef0c685d 100644 --- a/tests/MongoDB.Driver.Tests/Core/Operations/MapReduceOutputToCollectionOperationTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Operations/MapReduceOutputToCollectionOperationTests.cs @@ -1,4 +1,4 @@ -/* Copyright 2013-present MongoDB Inc. +/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,10 +18,7 @@ using FluentAssertions; using MongoDB.Bson; using MongoDB.TestHelpers.XunitExtensions; -using MongoDB.Driver.Core.Bindings; using MongoDB.Driver.Core.Clusters; -using MongoDB.Driver.Core.Connections; -using MongoDB.Driver.Core.Misc; using MongoDB.Driver.Core.TestHelpers.XunitExtensions; using Xunit; @@ -217,7 +214,7 @@ public void CreateCommand_should_return_expected_result_when_BypassDocumentValid var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { @@ -246,7 +243,7 @@ public void CreateCommand_should_return_expected_result_when_WriteConcern_is_set var connectionDescription = OperationTestHelper.CreateConnectionDescription(); var session = OperationTestHelper.CreateSession(); - var result = subject.CreateCommand(session, connectionDescription); + var result = subject.CreateCommand(OperationContext.NoTimeout, session, connectionDescription); var expectedResult = new BsonDocument { diff --git a/tests/MongoDB.Driver.Tests/Core/Operations/RetryableReadOperationExecutorTests.cs b/tests/MongoDB.Driver.Tests/Core/Operations/RetryableReadOperationExecutorTests.cs index 4eec630f34d..6b537fee55a 100644 --- a/tests/MongoDB.Driver.Tests/Core/Operations/RetryableReadOperationExecutorTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Operations/RetryableReadOperationExecutorTests.cs @@ -54,7 +54,7 @@ public void ShouldRetryOperation_should_return_expected_result( { var retryableReadContext = CreateSubject(isRetryRequested, isInTransaction); var exception =CoreExceptionHelper.CreateException(isRetriableException ? nameof(MongoNodeIsRecoveringException) : nameof(IOException)); - var operationContext = new OperationContext(hasTimeout ? TimeSpan.FromSeconds(42) : Timeout.InfiniteTimeSpan, CancellationToken.None); + var operationContext = new OperationContext(hasTimeout ? TimeSpan.FromSeconds(42) : null, CancellationToken.None); var result = RetryableReadOperationExecutorReflector.ShouldRetryOperation(operationContext, retryableReadContext, exception, attempt); diff --git a/tests/MongoDB.Driver.Tests/MongoUrlBuilderTests.cs b/tests/MongoDB.Driver.Tests/MongoUrlBuilderTests.cs index 72c42a285f2..59620de15ef 100644 --- a/tests/MongoDB.Driver.Tests/MongoUrlBuilderTests.cs +++ b/tests/MongoDB.Driver.Tests/MongoUrlBuilderTests.cs @@ -447,7 +447,7 @@ public void TestDefaults() Assert.Equal(MongoDefaults.LocalThreshold, builder.LocalThreshold); Assert.Equal(MongoDefaults.ServerSelectionTimeout, builder.ServerSelectionTimeout); Assert.Equal(MongoDefaults.SocketTimeout, builder.SocketTimeout); - Assert.Equal(Timeout.InfiniteTimeSpan, builder.Timeout); + Assert.Equal(null, builder.Timeout); Assert.Equal(MongoInternalDefaults.MongoClientSettings.SrvServiceName, builder.SrvServiceName); Assert.Equal(null, builder.Username); #pragma warning disable 618 @@ -1157,7 +1157,7 @@ public void TestTimeout(int? ms, string formatString, string[] values) var canonicalConnectionString = string.Format(formatString, values[0]); foreach (var builder in EnumerateBuiltAndParsedBuilders(built, formatString, values)) { - Assert.Equal(timeout ?? Timeout.InfiniteTimeSpan, builder.Timeout); + Assert.Equal(timeout, builder.Timeout); Assert.Equal(canonicalConnectionString, builder.ToString()); } } diff --git a/tests/MongoDB.Driver.Tests/OperationExecutorTests.cs b/tests/MongoDB.Driver.Tests/OperationExecutorTests.cs index 3d683a7ac39..c703c27acdf 100644 --- a/tests/MongoDB.Driver.Tests/OperationExecutorTests.cs +++ b/tests/MongoDB.Driver.Tests/OperationExecutorTests.cs @@ -66,7 +66,7 @@ await Record.ExceptionAsync(() => subject.ExecuteReadOperationAsync(session, ope Record.Exception(() => subject.ExecuteReadOperation(session, operation, null, true, Timeout.InfiniteTimeSpan, CancellationToken.None)); exception.Should().BeOfType() - .Subject.ParamName.Should().Be("options"); + .Subject.ParamName.Should().Be("readPreference"); } [Theory] From 26d617a74430fc58394e4a5d48e3430adf1c320d Mon Sep 17 00:00:00 2001 From: Oleksandr Poliakov Date: Wed, 23 Jul 2025 09:14:03 -0700 Subject: [PATCH 4/9] fix nullreference exception --- src/MongoDB.Driver/MongoCollectionSettings.cs | 2 +- src/MongoDB.Driver/MongoDatabaseSettings.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/MongoDB.Driver/MongoCollectionSettings.cs b/src/MongoDB.Driver/MongoCollectionSettings.cs index 0ee8d0f467a..f268074d09f 100644 --- a/src/MongoDB.Driver/MongoCollectionSettings.cs +++ b/src/MongoDB.Driver/MongoCollectionSettings.cs @@ -126,7 +126,7 @@ public IBsonSerializerRegistry SerializerRegistry /// public TimeSpan? Timeout { - get { return _timeout.Value; } + get { return _timeout; } set { if (_isFrozen) { throw new InvalidOperationException("MongoCollectionSettings is frozen."); } diff --git a/src/MongoDB.Driver/MongoDatabaseSettings.cs b/src/MongoDB.Driver/MongoDatabaseSettings.cs index ddffef09f9b..4b80b6023e3 100644 --- a/src/MongoDB.Driver/MongoDatabaseSettings.cs +++ b/src/MongoDB.Driver/MongoDatabaseSettings.cs @@ -111,7 +111,7 @@ public IBsonSerializerRegistry SerializerRegistry /// public TimeSpan? Timeout { - get { return _timeout.Value; } + get { return _timeout; } set { if (_isFrozen) { throw new InvalidOperationException("MongoCollectionSettings is frozen."); } From 5227d00ba0b816c07e318fc00604457408d8adcf Mon Sep 17 00:00:00 2001 From: Oleksandr Poliakov Date: Wed, 23 Jul 2025 10:19:09 -0700 Subject: [PATCH 5/9] fix tests --- .../WireProtocol/CommandUsingCommandMessageWireProtocol.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/MongoDB.Driver/Core/WireProtocol/CommandUsingCommandMessageWireProtocol.cs b/src/MongoDB.Driver/Core/WireProtocol/CommandUsingCommandMessageWireProtocol.cs index afd19dbf1f6..7f572c96297 100644 --- a/src/MongoDB.Driver/Core/WireProtocol/CommandUsingCommandMessageWireProtocol.cs +++ b/src/MongoDB.Driver/Core/WireProtocol/CommandUsingCommandMessageWireProtocol.cs @@ -380,10 +380,10 @@ private Type0CommandMessageSection CreateType0Section(OperationCon if (serverTimeout != Timeout.InfiniteTimeSpan) { serverTimeout -= _roundTripTime; - } - var serverTimeoutMs = MaxTimeHelper.ToMaxTimeMS(serverTimeout); - AddIfNotAlreadyAdded("maxTimeMS", serverTimeoutMs); + var serverTimeoutMs = MaxTimeHelper.ToMaxTimeMS(serverTimeout); + AddIfNotAlreadyAdded("maxTimeMS", serverTimeoutMs); + } } var elementAppendingSerializer = new ElementAppendingSerializer(BsonDocumentSerializer.Instance, extraElements); From 58c015dfb1188c4d30cee71cf68213351ecae8eb Mon Sep 17 00:00:00 2001 From: Oleksandr Poliakov Date: Wed, 23 Jul 2025 11:57:31 -0700 Subject: [PATCH 6/9] Fix tests --- .../Core/Bindings/CoreSession.cs | 8 ++-- src/MongoDB.Driver/Core/Misc/Feature.cs | 4 +- .../Core/Operations/AsyncCursor.cs | 16 +++---- .../Core/Operations/ChangeStreamCursor.cs | 4 +- src/MongoDB.Driver/GridFS/GridFSBucket.cs | 48 +++++++++---------- .../GridFS/GridFSForwardOnlyDownloadStream.cs | 4 +- .../GridFS/GridFSForwardOnlyUploadStream.cs | 4 +- .../GridFS/GridFSSeekableDownloadStream.cs | 4 +- .../Core/Operations/AsyncCursorTests.cs | 2 +- .../Operations/DropIndexOperationTests.cs | 2 +- 10 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/MongoDB.Driver/Core/Bindings/CoreSession.cs b/src/MongoDB.Driver/Core/Bindings/CoreSession.cs index 073492ea4da..d91eee1610e 100644 --- a/src/MongoDB.Driver/Core/Bindings/CoreSession.cs +++ b/src/MongoDB.Driver/Core/Bindings/CoreSession.cs @@ -146,7 +146,7 @@ public bool IsInTransaction EnsureAbortTransactionCanBeCalled(nameof(AbortTransaction)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); try { if (_currentTransaction.IsEmpty) @@ -197,7 +197,7 @@ public bool IsInTransaction EnsureAbortTransactionCanBeCalled(nameof(AbortTransaction)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); try { if (_currentTransaction.IsEmpty) @@ -297,7 +297,7 @@ public long AdvanceTransactionNumber() EnsureCommitTransactionCanBeCalled(nameof(CommitTransaction)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); try { _isCommitTransactionInProgress = true; @@ -334,7 +334,7 @@ public long AdvanceTransactionNumber() EnsureCommitTransactionCanBeCalled(nameof(CommitTransaction)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); try { _isCommitTransactionInProgress = true; diff --git a/src/MongoDB.Driver/Core/Misc/Feature.cs b/src/MongoDB.Driver/Core/Misc/Feature.cs index fecba2788f6..47bf7bb65f9 100644 --- a/src/MongoDB.Driver/Core/Misc/Feature.cs +++ b/src/MongoDB.Driver/Core/Misc/Feature.cs @@ -570,7 +570,7 @@ public void ThrowIfNotSupported(IMongoClient client, CancellationToken cancellat { var cluster = client.GetClusterInternal(); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); using (var binding = new ReadWriteBindingHandle(new WritableServerBinding(cluster, NoCoreSession.NewHandle()))) using (var channelSource = binding.GetWriteChannelSource(operationContext)) using (var channel = channelSource.GetChannel(operationContext)) @@ -589,7 +589,7 @@ public async Task ThrowIfNotSupportedAsync(IMongoClient client, CancellationToke { var cluster = client.GetClusterInternal(); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); using (var binding = new ReadWriteBindingHandle(new WritableServerBinding(cluster, NoCoreSession.NewHandle()))) using (var channelSource = await binding.GetWriteChannelSourceAsync(operationContext).ConfigureAwait(false)) using (var channel = await channelSource.GetChannelAsync(operationContext).ConfigureAwait(false)) diff --git a/src/MongoDB.Driver/Core/Operations/AsyncCursor.cs b/src/MongoDB.Driver/Core/Operations/AsyncCursor.cs index dd5c7e0ba9f..6791ae3a44a 100644 --- a/src/MongoDB.Driver/Core/Operations/AsyncCursor.cs +++ b/src/MongoDB.Driver/Core/Operations/AsyncCursor.cs @@ -220,7 +220,7 @@ private CursorBatch ExecuteGetMoreCommand(IChannelHandle channel, Can try { // TODO: CSOT: Implement operation context support for Cursors - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); result = channel.Command( operationContext, _channelSource.Session, @@ -250,7 +250,7 @@ private async Task> ExecuteGetMoreCommandAsync(IChannelHa try { // TODO: CSOT: Implement operation context support for Cursors - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); result = await channel.CommandAsync( operationContext, _channelSource.Session, @@ -276,7 +276,7 @@ private async Task> ExecuteGetMoreCommandAsync(IChannelHa private void ExecuteKillCursorsCommand(IChannelHandle channel, CancellationToken cancellationToken) { // TODO: CSOT: Implement operation context support for Cursors - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); var command = CreateKillCursorsCommand(); var result = channel.Command( operationContext, @@ -298,7 +298,7 @@ private void ExecuteKillCursorsCommand(IChannelHandle channel, CancellationToken private async Task ExecuteKillCursorsCommandAsync(IChannelHandle channel, CancellationToken cancellationToken) { // TODO: CSOT: Implement operation context support for Cursors - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); var command = CreateKillCursorsCommand(); var result = await channel.CommandAsync( operationContext, @@ -418,7 +418,7 @@ private void DisposeChannelSourceIfNoLongerNeeded() private CursorBatch GetNextBatch(CancellationToken cancellationToken) { // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); using (EventContext.BeginOperation(_operationId)) using (var channel = _channelSource.GetChannel(operationContext)) { @@ -429,7 +429,7 @@ private CursorBatch GetNextBatch(CancellationToken cancellationToken) private async Task> GetNextBatchAsync(CancellationToken cancellationToken) { // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); using (EventContext.BeginOperation(_operationId)) using (var channel = await _channelSource.GetChannelAsync(operationContext).ConfigureAwait(false)) { @@ -445,7 +445,7 @@ private bool IsMongoCursorNotFoundException(MongoCommandException exception) private void KillCursors(CancellationToken cancellationToken) { // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); using (EventContext.BeginOperation(_operationId)) using (EventContext.BeginKillCursors(_collectionNamespace)) using (var channel = _channelSource.GetChannel(operationContext.WithTimeout(TimeSpan.FromSeconds(10)))) @@ -460,7 +460,7 @@ private void KillCursors(CancellationToken cancellationToken) private async Task KillCursorsAsync(CancellationToken cancellationToken) { // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); using (EventContext.BeginOperation(_operationId)) using (EventContext.BeginKillCursors(_collectionNamespace)) using (var channel = await _channelSource.GetChannelAsync(operationContext.WithTimeout(TimeSpan.FromSeconds(10))).ConfigureAwait(false)) diff --git a/src/MongoDB.Driver/Core/Operations/ChangeStreamCursor.cs b/src/MongoDB.Driver/Core/Operations/ChangeStreamCursor.cs index afd01623847..f43cb30a168 100644 --- a/src/MongoDB.Driver/Core/Operations/ChangeStreamCursor.cs +++ b/src/MongoDB.Driver/Core/Operations/ChangeStreamCursor.cs @@ -262,7 +262,7 @@ private IAsyncCursor Resume(CancellationToken cancellationToken { ReconfigureOperationResumeValues(); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); return _changeStreamOperation.Resume(operationContext, _binding); } @@ -270,7 +270,7 @@ private async Task> ResumeAsync(CancellationToken { ReconfigureOperationResumeValues(); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); return await _changeStreamOperation.ResumeAsync(operationContext, _binding).ConfigureAwait(false); } diff --git a/src/MongoDB.Driver/GridFS/GridFSBucket.cs b/src/MongoDB.Driver/GridFS/GridFSBucket.cs index 7bd029044b8..7e65af290a3 100644 --- a/src/MongoDB.Driver/GridFS/GridFSBucket.cs +++ b/src/MongoDB.Driver/GridFS/GridFSBucket.cs @@ -84,7 +84,7 @@ public ImmutableGridFSBucketOptions Options { Ensure.IsNotNull((object)id, nameof(id)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); using (var binding = GetSingleServerReadWriteBinding(operationContext)) { var filesCollectionDeleteOperation = CreateDeleteFileOperation(id); @@ -105,7 +105,7 @@ public ImmutableGridFSBucketOptions Options { Ensure.IsNotNull((object)id, nameof(id)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); using (var binding = await GetSingleServerReadWriteBindingAsync(operationContext).ConfigureAwait(false)) { var filesCollectionDeleteOperation = CreateDeleteFileOperation(id); @@ -126,7 +126,7 @@ public ImmutableGridFSBucketOptions Options { Ensure.IsNotNull((object)id, nameof(id)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); options = options ?? new GridFSDownloadOptions(); using (var binding = GetSingleServerReadBinding(operationContext)) { @@ -140,7 +140,7 @@ public ImmutableGridFSBucketOptions Options { Ensure.IsNotNull((object)id, nameof(id)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); options = options ?? new GridFSDownloadOptions(); using (var binding = await GetSingleServerReadBindingAsync(operationContext).ConfigureAwait(false)) { @@ -154,7 +154,7 @@ public ImmutableGridFSBucketOptions Options { Ensure.IsNotNull(filename, nameof(filename)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); options = options ?? new GridFSDownloadByNameOptions(); using (var binding = GetSingleServerReadBinding(operationContext)) @@ -169,7 +169,7 @@ public ImmutableGridFSBucketOptions Options { Ensure.IsNotNull(filename, nameof(filename)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); options = options ?? new GridFSDownloadByNameOptions(); using (var binding = await GetSingleServerReadBindingAsync(operationContext).ConfigureAwait(false)) @@ -185,7 +185,7 @@ public ImmutableGridFSBucketOptions Options Ensure.IsNotNull((object)id, nameof(id)); Ensure.IsNotNull(destination, nameof(destination)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); options = options ?? new GridFSDownloadOptions(); using (var binding = GetSingleServerReadBinding(operationContext)) { @@ -200,7 +200,7 @@ public ImmutableGridFSBucketOptions Options Ensure.IsNotNull((object)id, nameof(id)); Ensure.IsNotNull(destination, nameof(destination)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); options = options ?? new GridFSDownloadOptions(); using (var binding = await GetSingleServerReadBindingAsync(operationContext).ConfigureAwait(false)) { @@ -215,7 +215,7 @@ public ImmutableGridFSBucketOptions Options Ensure.IsNotNull(filename, nameof(filename)); Ensure.IsNotNull(destination, nameof(destination)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); options = options ?? new GridFSDownloadByNameOptions(); using (var binding = GetSingleServerReadBinding(operationContext)) @@ -231,7 +231,7 @@ public ImmutableGridFSBucketOptions Options Ensure.IsNotNull(filename, nameof(filename)); Ensure.IsNotNull(destination, nameof(destination)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); options = options ?? new GridFSDownloadByNameOptions(); using (var binding = await GetSingleServerReadBindingAsync(operationContext).ConfigureAwait(false)) @@ -245,7 +245,7 @@ public ImmutableGridFSBucketOptions Options public void Drop(CancellationToken cancellationToken = default(CancellationToken)) { // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); var filesCollectionNamespace = this.GetFilesCollectionNamespace(); var chunksCollectionNamespace = this.GetChunksCollectionNamespace(); var messageEncoderSettings = this.GetMessageEncoderSettings(); @@ -264,7 +264,7 @@ public ImmutableGridFSBucketOptions Options public async Task DropAsync(CancellationToken cancellationToken = default(CancellationToken)) { // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); var filesCollectionNamespace = this.GetFilesCollectionNamespace(); var chunksCollectionNamespace = this.GetChunksCollectionNamespace(); var messageEncoderSettings = this.GetMessageEncoderSettings(); @@ -284,7 +284,7 @@ public ImmutableGridFSBucketOptions Options { Ensure.IsNotNull(filter, nameof(filter)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); options = options ?? new GridFSFindOptions(); var translationOptions = _database.Client.Settings.TranslationOptions; @@ -300,7 +300,7 @@ public ImmutableGridFSBucketOptions Options { Ensure.IsNotNull(filter, nameof(filter)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); options = options ?? new GridFSFindOptions(); var translationOptions = _database.Client.Settings.TranslationOptions; @@ -316,7 +316,7 @@ public ImmutableGridFSBucketOptions Options { Ensure.IsNotNull((object)id, nameof(id)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); options = options ?? new GridFSDownloadOptions(); using (var binding = GetSingleServerReadBinding(operationContext)) { @@ -330,7 +330,7 @@ public ImmutableGridFSBucketOptions Options { Ensure.IsNotNull((object)id, nameof(id)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); options = options ?? new GridFSDownloadOptions(); using (var binding = await GetSingleServerReadBindingAsync(operationContext).ConfigureAwait(false)) { @@ -344,7 +344,7 @@ public ImmutableGridFSBucketOptions Options { Ensure.IsNotNull(filename, nameof(filename)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); options = options ?? new GridFSDownloadByNameOptions(); using (var binding = GetSingleServerReadBinding(operationContext)) @@ -359,7 +359,7 @@ public ImmutableGridFSBucketOptions Options { Ensure.IsNotNull(filename, nameof(filename)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); options = options ?? new GridFSDownloadByNameOptions(); using (var binding = await GetSingleServerReadBindingAsync(operationContext).ConfigureAwait(false)) @@ -375,7 +375,7 @@ public ImmutableGridFSBucketOptions Options Ensure.IsNotNull((object)id, nameof(id)); Ensure.IsNotNull(filename, nameof(filename)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); options = options ?? new GridFSUploadOptions(); using (var binding = GetSingleServerReadWriteBinding(operationContext)) @@ -391,7 +391,7 @@ public ImmutableGridFSBucketOptions Options Ensure.IsNotNull((object)id, nameof(id)); Ensure.IsNotNull(filename, nameof(filename)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); options = options ?? new GridFSUploadOptions(); using (var binding = await GetSingleServerReadWriteBindingAsync(operationContext).ConfigureAwait(false)) @@ -407,7 +407,7 @@ public ImmutableGridFSBucketOptions Options Ensure.IsNotNull((object)id, nameof(id)); Ensure.IsNotNull(newFilename, nameof(newFilename)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); var renameOperation = CreateRenameOperation(id, newFilename); using (var binding = GetSingleServerReadWriteBinding(operationContext)) { @@ -426,7 +426,7 @@ public ImmutableGridFSBucketOptions Options Ensure.IsNotNull((object)id, nameof(id)); Ensure.IsNotNull(newFilename, nameof(newFilename)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); var renameOperation = CreateRenameOperation(id, newFilename); using (var binding = await GetSingleServerReadWriteBindingAsync(operationContext).ConfigureAwait(false)) { @@ -446,7 +446,7 @@ public ImmutableGridFSBucketOptions Options Ensure.IsNotNull(filename, nameof(filename)); Ensure.IsNotNull(source, nameof(source)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); options = options ?? new GridFSUploadOptions(); using (var sourceStream = new MemoryStream(source)) @@ -462,7 +462,7 @@ public ImmutableGridFSBucketOptions Options Ensure.IsNotNull(filename, nameof(filename)); Ensure.IsNotNull(source, nameof(source)); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); options = options ?? new GridFSUploadOptions(); using (var sourceStream = new MemoryStream(source)) diff --git a/src/MongoDB.Driver/GridFS/GridFSForwardOnlyDownloadStream.cs b/src/MongoDB.Driver/GridFS/GridFSForwardOnlyDownloadStream.cs index 23f5e48f877..d3c400afd76 100644 --- a/src/MongoDB.Driver/GridFS/GridFSForwardOnlyDownloadStream.cs +++ b/src/MongoDB.Driver/GridFS/GridFSForwardOnlyDownloadStream.cs @@ -197,7 +197,7 @@ private void GetFirstBatch(CancellationToken cancellationToken) { var operation = CreateFirstBatchOperation(); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); _cursor = operation.Execute(operationContext, Binding); GetNextBatch(cancellationToken); } @@ -206,7 +206,7 @@ private async Task GetFirstBatchAsync(CancellationToken cancellationToken) { var operation = CreateFirstBatchOperation(); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); _cursor = await operation.ExecuteAsync(operationContext, Binding).ConfigureAwait(false); await GetNextBatchAsync(cancellationToken).ConfigureAwait(false); } diff --git a/src/MongoDB.Driver/GridFS/GridFSForwardOnlyUploadStream.cs b/src/MongoDB.Driver/GridFS/GridFSForwardOnlyUploadStream.cs index f77fc81f56f..9b21d21e476 100644 --- a/src/MongoDB.Driver/GridFS/GridFSForwardOnlyUploadStream.cs +++ b/src/MongoDB.Driver/GridFS/GridFSForwardOnlyUploadStream.cs @@ -123,7 +123,7 @@ public override long Position var operation = CreateAbortOperation(); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); operation.Execute(operationContext, _binding); } @@ -138,7 +138,7 @@ public override long Position var operation = CreateAbortOperation(); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); await operation.ExecuteAsync(operationContext, _binding).ConfigureAwait(false); } diff --git a/src/MongoDB.Driver/GridFS/GridFSSeekableDownloadStream.cs b/src/MongoDB.Driver/GridFS/GridFSSeekableDownloadStream.cs index 843412df7ef..921bbac4232 100644 --- a/src/MongoDB.Driver/GridFS/GridFSSeekableDownloadStream.cs +++ b/src/MongoDB.Driver/GridFS/GridFSSeekableDownloadStream.cs @@ -173,7 +173,7 @@ private void GetChunk(long n, CancellationToken cancellationToken) { var operation = CreateGetChunkOperation(n); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); using (var cursor = operation.Execute(operationContext, Binding)) { var documents = cursor.ToList(); @@ -186,7 +186,7 @@ private async Task GetChunkAsync(long n, CancellationToken cancellationToken) { var operation = CreateGetChunkOperation(n); // TODO: CSOT implement proper way to obtain the operationContext - var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken); + var operationContext = new OperationContext(null, cancellationToken); using (var cursor = await operation.ExecuteAsync(operationContext, Binding).ConfigureAwait(false)) { var documents = await cursor.ToListAsync().ConfigureAwait(false); diff --git a/tests/MongoDB.Driver.Tests/Core/Operations/AsyncCursorTests.cs b/tests/MongoDB.Driver.Tests/Core/Operations/AsyncCursorTests.cs index 3728762b355..804bf16939b 100644 --- a/tests/MongoDB.Driver.Tests/Core/Operations/AsyncCursorTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Operations/AsyncCursorTests.cs @@ -692,7 +692,7 @@ private IReadOnlyList GetFirstBatchUsingFindCommand(IChannelHandle { "batchSize", batchSize } }; var result = channel.Command( - new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken), + new OperationContext(null, cancellationToken), _session, ReadPreference.Primary, _databaseNamespace, diff --git a/tests/MongoDB.Driver.Tests/Core/Operations/DropIndexOperationTests.cs b/tests/MongoDB.Driver.Tests/Core/Operations/DropIndexOperationTests.cs index 4c0d2de63be..799c36a9186 100644 --- a/tests/MongoDB.Driver.Tests/Core/Operations/DropIndexOperationTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Operations/DropIndexOperationTests.cs @@ -70,7 +70,7 @@ public void constructor_with_collectionNamespace_indexName_messageEncoderSetting { var exception = Record.Exception(() => { new DropIndexOperation(_collectionNamespace, indexName, _messageEncoderSettings); }); - exception.Should().BeOfType().Subject + exception.Should().BeAssignableTo().Subject .ParamName.Should().Be("indexName"); } From 7dabafc56fba4e79b548ff0b749223cc554c6287 Mon Sep 17 00:00:00 2001 From: Oleksandr Poliakov Date: Thu, 24 Jul 2025 16:47:11 -0700 Subject: [PATCH 7/9] pr --- src/MongoDB.Driver/AggregateOptions.cs | 2 +- src/MongoDB.Driver/CountOptions.cs | 2 +- src/MongoDB.Driver/CreateManyIndexesOptions.cs | 2 +- src/MongoDB.Driver/CreateOneIndexOptions.cs | 2 +- src/MongoDB.Driver/DistinctOptions.cs | 2 +- src/MongoDB.Driver/DropIndexOptions.cs | 2 +- src/MongoDB.Driver/EstimatedDocumentCountOptions.cs | 2 +- src/MongoDB.Driver/FindOneAndDeleteOptions.cs | 2 +- src/MongoDB.Driver/FindOneAndReplaceOptions.cs | 2 +- src/MongoDB.Driver/FindOneAndUpdateOptions.cs | 2 +- src/MongoDB.Driver/FindOptions.cs | 2 +- src/MongoDB.Driver/MapReduceOptions.cs | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/MongoDB.Driver/AggregateOptions.cs b/src/MongoDB.Driver/AggregateOptions.cs index 91070eed189..65267d669a8 100644 --- a/src/MongoDB.Driver/AggregateOptions.cs +++ b/src/MongoDB.Driver/AggregateOptions.cs @@ -122,7 +122,7 @@ public TimeSpan? MaxAwaitTime /// /// Gets or sets the maximum time. /// - [Obsolete("Use Timeout instead")] + [Obsolete("MaxTime is obsolete and will be removed in a future version. Use Timeout instead.")] public TimeSpan? MaxTime { get { return _maxTime; } diff --git a/src/MongoDB.Driver/CountOptions.cs b/src/MongoDB.Driver/CountOptions.cs index 5c50d56f1c4..5507b26e50c 100644 --- a/src/MongoDB.Driver/CountOptions.cs +++ b/src/MongoDB.Driver/CountOptions.cs @@ -73,7 +73,7 @@ public long? Limit /// /// Gets or sets the maximum time. /// - [Obsolete("Use Timeout instead")] + [Obsolete("MaxTime is obsolete and will be removed in a future version. Use Timeout instead.")] public TimeSpan? MaxTime { get { return _maxTime; } diff --git a/src/MongoDB.Driver/CreateManyIndexesOptions.cs b/src/MongoDB.Driver/CreateManyIndexesOptions.cs index 21515e68a95..ab372a81fd7 100644 --- a/src/MongoDB.Driver/CreateManyIndexesOptions.cs +++ b/src/MongoDB.Driver/CreateManyIndexesOptions.cs @@ -55,7 +55,7 @@ public CreateIndexCommitQuorum CommitQuorum /// Gets or sets the maximum time. /// /// The maximum time. - [Obsolete("Use Timeout instead")] + [Obsolete("MaxTime is obsolete and will be removed in a future version. Use Timeout instead.")] public TimeSpan? MaxTime { get { return _maxTime; } diff --git a/src/MongoDB.Driver/CreateOneIndexOptions.cs b/src/MongoDB.Driver/CreateOneIndexOptions.cs index 59379ab9199..553a4e81d12 100644 --- a/src/MongoDB.Driver/CreateOneIndexOptions.cs +++ b/src/MongoDB.Driver/CreateOneIndexOptions.cs @@ -43,7 +43,7 @@ public CreateIndexCommitQuorum CommitQuorum /// Gets or sets the maximum time. /// /// The maximum time. - [Obsolete("Use Timeout instead")] + [Obsolete("MaxTime is obsolete and will be removed in a future version. Use Timeout instead.")] public TimeSpan? MaxTime { get { return _maxTime; } diff --git a/src/MongoDB.Driver/DistinctOptions.cs b/src/MongoDB.Driver/DistinctOptions.cs index c1516c2d7e1..12cffefc521 100644 --- a/src/MongoDB.Driver/DistinctOptions.cs +++ b/src/MongoDB.Driver/DistinctOptions.cs @@ -52,7 +52,7 @@ public BsonValue Comment /// /// Gets or sets the maximum time. /// - [Obsolete("Use Timeout instead")] + [Obsolete("MaxTime is obsolete and will be removed in a future version. Use Timeout instead.")] public TimeSpan? MaxTime { get { return _maxTime; } diff --git a/src/MongoDB.Driver/DropIndexOptions.cs b/src/MongoDB.Driver/DropIndexOptions.cs index 5a3aad472c8..e4e4060e607 100644 --- a/src/MongoDB.Driver/DropIndexOptions.cs +++ b/src/MongoDB.Driver/DropIndexOptions.cs @@ -44,7 +44,7 @@ public BsonValue Comment /// Gets or sets the maximum time. /// /// The maximum time. - [Obsolete("Use Timeout instead")] + [Obsolete("MaxTime is obsolete and will be removed in a future version. Use Timeout instead.")] public TimeSpan? MaxTime { get { return _maxTime; } diff --git a/src/MongoDB.Driver/EstimatedDocumentCountOptions.cs b/src/MongoDB.Driver/EstimatedDocumentCountOptions.cs index 993464a1a37..2dc5740075e 100644 --- a/src/MongoDB.Driver/EstimatedDocumentCountOptions.cs +++ b/src/MongoDB.Driver/EstimatedDocumentCountOptions.cs @@ -42,7 +42,7 @@ public BsonValue Comment /// /// Gets or sets the maximum time. /// - [Obsolete("Use Timeout instead")] + [Obsolete("MaxTime is obsolete and will be removed in a future version. Use Timeout instead.")] public TimeSpan? MaxTime { get { return _maxTime; } diff --git a/src/MongoDB.Driver/FindOneAndDeleteOptions.cs b/src/MongoDB.Driver/FindOneAndDeleteOptions.cs index a62cd05468a..3a50bb2c27a 100644 --- a/src/MongoDB.Driver/FindOneAndDeleteOptions.cs +++ b/src/MongoDB.Driver/FindOneAndDeleteOptions.cs @@ -76,7 +76,7 @@ public BsonDocument Let /// /// Gets or sets the maximum time. /// - [Obsolete("Use Timeout instead")] + [Obsolete("MaxTime is obsolete and will be removed in a future version. Use Timeout instead.")] public TimeSpan? MaxTime { get { return _maxTime; } diff --git a/src/MongoDB.Driver/FindOneAndReplaceOptions.cs b/src/MongoDB.Driver/FindOneAndReplaceOptions.cs index 885086c7320..c6353cc3105 100644 --- a/src/MongoDB.Driver/FindOneAndReplaceOptions.cs +++ b/src/MongoDB.Driver/FindOneAndReplaceOptions.cs @@ -106,7 +106,7 @@ public bool IsUpsert /// /// Gets or sets the maximum time. /// - [Obsolete("Use Timeout instead")] + [Obsolete("MaxTime is obsolete and will be removed in a future version. Use Timeout instead.")] public TimeSpan? MaxTime { get { return _maxTime; } diff --git a/src/MongoDB.Driver/FindOneAndUpdateOptions.cs b/src/MongoDB.Driver/FindOneAndUpdateOptions.cs index f3e937721ba..ba976fcf635 100644 --- a/src/MongoDB.Driver/FindOneAndUpdateOptions.cs +++ b/src/MongoDB.Driver/FindOneAndUpdateOptions.cs @@ -120,7 +120,7 @@ public BsonDocument Let /// /// Gets or sets the maximum time. /// - [Obsolete("Use Timeout instead")] + [Obsolete("MaxTime is obsolete and will be removed in a future version. Use Timeout instead.")] public TimeSpan? MaxTime { get { return _maxTime; } diff --git a/src/MongoDB.Driver/FindOptions.cs b/src/MongoDB.Driver/FindOptions.cs index 527f6c8f2b1..29569dcdb23 100644 --- a/src/MongoDB.Driver/FindOptions.cs +++ b/src/MongoDB.Driver/FindOptions.cs @@ -147,7 +147,7 @@ public TimeSpan? MaxAwaitTime /// /// Gets or sets the maximum time. /// - [Obsolete("Use Timeout instead")] + [Obsolete("MaxTime is obsolete and will be removed in a future version. Use Timeout instead.")] public TimeSpan? MaxTime { get { return _maxTime; } diff --git a/src/MongoDB.Driver/MapReduceOptions.cs b/src/MongoDB.Driver/MapReduceOptions.cs index b10762c4477..b898f58b55d 100644 --- a/src/MongoDB.Driver/MapReduceOptions.cs +++ b/src/MongoDB.Driver/MapReduceOptions.cs @@ -102,7 +102,7 @@ public long? Limit /// /// Gets or sets the maximum time. /// - [Obsolete("Use Timeout instead")] + [Obsolete("MaxTime is obsolete and will be removed in a future version. Use Timeout instead.")] public TimeSpan? MaxTime { get { return _maxTime; } From 7bf05ad17a764591160759f1922e500c81b7f669 Mon Sep 17 00:00:00 2001 From: Oleksandr Poliakov Date: Fri, 25 Jul 2025 09:00:22 -0700 Subject: [PATCH 8/9] pr --- src/MongoDB.Driver/Core/Configuration/ConnectionString.cs | 4 ++-- src/MongoDB.Driver/Core/Servers/RoundTripTimeMonitor.cs | 2 +- src/MongoDB.Driver/MongoUrlBuilder.cs | 2 +- .../Core/Configuration/ConnectionStringTests.cs | 2 ++ tests/MongoDB.Driver.Tests/MongoUrlBuilderTests.cs | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/MongoDB.Driver/Core/Configuration/ConnectionString.cs b/src/MongoDB.Driver/Core/Configuration/ConnectionString.cs index 40c8787d542..e92479d1cc3 100644 --- a/src/MongoDB.Driver/Core/Configuration/ConnectionString.cs +++ b/src/MongoDB.Driver/Core/Configuration/ConnectionString.cs @@ -469,7 +469,7 @@ public bool? Ssl public bool? SslVerifyCertificate => !_tlsInsecure; /// - /// Gets the per-operation timeout + /// Gets the per-operation timeout. /// public TimeSpan? Timeout => _timeout; @@ -1096,7 +1096,7 @@ private void ParseOption(string name, string value) break; case "timeout": case "timeoutms": - _timeout = ParseTimeSpan(name, value); + _timeout = value == "0" ? System.Threading.Timeout.InfiniteTimeSpan : ParseTimeSpan(name, value); break; case "tlsdisablecertificaterevocationcheck": var tlsDisableCertificateRevocationCheckValue = ParseBoolean(name, value); diff --git a/src/MongoDB.Driver/Core/Servers/RoundTripTimeMonitor.cs b/src/MongoDB.Driver/Core/Servers/RoundTripTimeMonitor.cs index ee352025f0c..0521743d5ae 100644 --- a/src/MongoDB.Driver/Core/Servers/RoundTripTimeMonitor.cs +++ b/src/MongoDB.Driver/Core/Servers/RoundTripTimeMonitor.cs @@ -125,7 +125,7 @@ private void MonitorServer() _logger?.LogDebug(_serverId, "Monitoring started"); var helloOk = false; - using var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, _cancellationToken); + using var operationContext = new OperationContext(null, _cancellationToken); while (!operationContext.IsCancelledOrTimedOut()) { try diff --git a/src/MongoDB.Driver/MongoUrlBuilder.cs b/src/MongoDB.Driver/MongoUrlBuilder.cs index a02a144b6b8..e8302eb09be 100644 --- a/src/MongoDB.Driver/MongoUrlBuilder.cs +++ b/src/MongoDB.Driver/MongoUrlBuilder.cs @@ -971,7 +971,7 @@ public override string ToString() } if (_timeout.HasValue) { - query.AppendFormat("timeout={0}&", FormatTimeSpan(_timeout.Value)); + query.AppendFormat("timeout={0}&", _timeout == System.Threading.Timeout.InfiniteTimeSpan ? "0" : FormatTimeSpan(_timeout.Value)); } #pragma warning disable 618 if (_waitQueueMultiple != 0.0 && _waitQueueMultiple != MongoDefaults.WaitQueueMultiple) diff --git a/tests/MongoDB.Driver.Tests/Core/Configuration/ConnectionStringTests.cs b/tests/MongoDB.Driver.Tests/Core/Configuration/ConnectionStringTests.cs index 16d7fbacc76..f42955da715 100644 --- a/tests/MongoDB.Driver.Tests/Core/Configuration/ConnectionStringTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Configuration/ConnectionStringTests.cs @@ -1052,6 +1052,8 @@ public void When_sslVerifyCertificate_is_specified(string connectionString, bool } [Theory] + [InlineData("mongodb://localhost?timeoutMS=0", -1)] + [InlineData("mongodb://localhost?timeout=0", -1)] [InlineData("mongodb://localhost?timeout=15ms", 15)] [InlineData("mongodb://localhost?timeoutMS=15", 15)] [InlineData("mongodb://localhost?timeout=15", 1000 * 15)] diff --git a/tests/MongoDB.Driver.Tests/MongoUrlBuilderTests.cs b/tests/MongoDB.Driver.Tests/MongoUrlBuilderTests.cs index 59620de15ef..f45282623dc 100644 --- a/tests/MongoDB.Driver.Tests/MongoUrlBuilderTests.cs +++ b/tests/MongoDB.Driver.Tests/MongoUrlBuilderTests.cs @@ -16,7 +16,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; using FluentAssertions; using MongoDB.Bson.IO; using MongoDB.Driver.Core.Compression; @@ -1143,6 +1142,7 @@ public void TestSocketTimeout_Range() [Theory] [InlineData(null, "mongodb://localhost", new[] { "" })] + [InlineData(-1, "mongodb://localhost/?timeout{0}", new[] { "=0", "MS=0" })] [InlineData(500, "mongodb://localhost/?timeout{0}", new[] { "=500ms", "=0.5", "=0.5s", "=00:00:00.5", "MS=500" })] [InlineData(30000, "mongodb://localhost/?timeout{0}", new[] { "=30s", "=30000ms", "=30", "=0.5m", "=00:00:30", "MS=30000" })] [InlineData(1800000, "mongodb://localhost/?timeout{0}", new[] { "=30m", "=1800000ms", "=1800", "=1800s", "=0.5h", "=00:30:00", "MS=1800000" })] From 3655c7c672a79fac7b16b81838fc359f74f83a58 Mon Sep 17 00:00:00 2001 From: Oleksandr Poliakov Date: Fri, 25 Jul 2025 16:14:18 -0700 Subject: [PATCH 9/9] Missed options --- src/MongoDB.Driver/DeleteOptions.cs | 12 +++++++ src/MongoDB.Driver/InsertManyOptions.cs | 15 ++++++++- src/MongoDB.Driver/MongoCollectionBase.cs | 41 +++++++++++++++-------- src/MongoDB.Driver/ReplaceOptions.cs | 14 +++++++- src/MongoDB.Driver/UpdateOptions.cs | 12 +++++++ 5 files changed, 78 insertions(+), 16 deletions(-) diff --git a/src/MongoDB.Driver/DeleteOptions.cs b/src/MongoDB.Driver/DeleteOptions.cs index e8e31e98758..385bea2d8fc 100644 --- a/src/MongoDB.Driver/DeleteOptions.cs +++ b/src/MongoDB.Driver/DeleteOptions.cs @@ -13,7 +13,9 @@ * limitations under the License. */ +using System; using MongoDB.Bson; +using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver { @@ -27,6 +29,7 @@ public sealed class DeleteOptions private BsonValue _comment; private BsonValue _hint; private BsonDocument _let; + private TimeSpan? _timeout; // properties /// @@ -64,5 +67,14 @@ public BsonDocument Let get { return _let; } set { _let = value; } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } } diff --git a/src/MongoDB.Driver/InsertManyOptions.cs b/src/MongoDB.Driver/InsertManyOptions.cs index 088fda4723a..07d0d8df773 100644 --- a/src/MongoDB.Driver/InsertManyOptions.cs +++ b/src/MongoDB.Driver/InsertManyOptions.cs @@ -11,9 +11,12 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * + * */ + +using System; using MongoDB.Bson; +using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver { @@ -26,6 +29,7 @@ public sealed class InsertManyOptions private bool? _bypassDocumentValidation; private BsonValue _comment; private bool _isOrdered; + private TimeSpan? _timeout; // constructors /// @@ -63,5 +67,14 @@ public bool IsOrdered get { return _isOrdered; } set { _isOrdered = value; } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } } diff --git a/src/MongoDB.Driver/MongoCollectionBase.cs b/src/MongoDB.Driver/MongoCollectionBase.cs index 48f71e0f1ae..b7c937de1c0 100644 --- a/src/MongoDB.Driver/MongoCollectionBase.cs +++ b/src/MongoDB.Driver/MongoCollectionBase.cs @@ -164,7 +164,8 @@ private DeleteResult DeleteMany(FilterDefinition filter, DeleteOption var bulkWriteOptions = new BulkWriteOptions { Comment = options.Comment, - Let = options.Let + Let = options.Let, + Timeout = options.Timeout }; var result = bulkWriteFunc(new[] { model }, bulkWriteOptions); return DeleteResult.FromCore(result); @@ -205,7 +206,8 @@ private async Task DeleteManyAsync(FilterDefinition fil var bulkWriteOptions = new BulkWriteOptions { Comment = options.Comment, - Let = options.Let + Let = options.Let, + Timeout = options.Timeout }; var result = await bulkWriteFuncAsync(new[] { model }, bulkWriteOptions).ConfigureAwait(false); return DeleteResult.FromCore(result); @@ -246,7 +248,8 @@ private DeleteResult DeleteOne(FilterDefinition filter, DeleteOptions var bulkWriteOptions = new BulkWriteOptions { Comment = options.Comment, - Let = options.Let + Let = options.Let, + Timeout = options.Timeout }; var result = bulkWrite(new[] { model }, bulkWriteOptions); return DeleteResult.FromCore(result); @@ -287,7 +290,8 @@ private async Task DeleteOneAsync(FilterDefinition filt var bulkWriteOptions = new BulkWriteOptions { Comment = options.Comment, - Let = options.Let + Let = options.Let, + Timeout = options.Timeout }; var result = await bulkWriteAsync(new[] { model }, bulkWriteOptions).ConfigureAwait(false); return DeleteResult.FromCore(result); @@ -436,7 +440,7 @@ private void InsertOne(TDocument document, InsertOneOptions options, Action documents, InsertManyOptions opti { BypassDocumentValidation = options.BypassDocumentValidation, Comment = options.Comment, - IsOrdered = options.IsOrdered + IsOrdered = options.IsOrdered, + Timeout = options.Timeout }; bulkWrite(models, bulkWriteOptions); } @@ -525,7 +531,8 @@ private Task InsertManyAsync(IEnumerable documents, InsertManyOptions { BypassDocumentValidation = options.BypassDocumentValidation, Comment = options.Comment, - IsOrdered = options.IsOrdered + IsOrdered = options.IsOrdered, + Timeout = options.Timeout }; return bulkWriteAsync(models, bulkWriteOptions); } @@ -599,7 +606,8 @@ private ReplaceOneResult ReplaceOne(FilterDefinition filter, TDocumen { BypassDocumentValidation = options.BypassDocumentValidation, Comment = options.Comment, - Let = options.Let + Let = options.Let, + Timeout = options.Timeout }; var result = bulkWrite(new[] { model }, bulkWriteOptions); return ReplaceOneResult.FromCore(result); @@ -657,7 +665,8 @@ private async Task ReplaceOneAsync(FilterDefinition { BypassDocumentValidation = options.BypassDocumentValidation, Comment = options.Comment, - Let = options.Let + Let = options.Let, + Timeout = options.Timeout }; var result = await bulkWriteAsync(new[] { model }, bulkWriteOptions).ConfigureAwait(false); return ReplaceOneResult.FromCore(result); @@ -698,7 +707,8 @@ private UpdateResult UpdateMany(FilterDefinition filter, UpdateDefini { BypassDocumentValidation = options.BypassDocumentValidation, Comment = options.Comment, - Let = options.Let + Let = options.Let, + Timeout = options.Timeout }; var result = bulkWrite(new[] { model }, bulkWriteOptions); return UpdateResult.FromCore(result); @@ -739,7 +749,8 @@ private async Task UpdateManyAsync(FilterDefinition fil { BypassDocumentValidation = options.BypassDocumentValidation, Comment = options.Comment, - Let = options.Let + Let = options.Let, + Timeout = options.Timeout }; var result = await bulkWriteAsync(new[] { model }, bulkWriteOptions).ConfigureAwait(false); return UpdateResult.FromCore(result); @@ -785,7 +796,8 @@ private UpdateResult UpdateOne(FilterDefinition filter, UpdateDefinit { BypassDocumentValidation = options.BypassDocumentValidation, Comment = options.Comment, - Let = options.Let + Let = options.Let, + Timeout = options.Timeout }; var result = bulkWrite(new[] { model }, bulkWriteOptions); return UpdateResult.FromCore(result); @@ -831,7 +843,8 @@ private async Task UpdateOneAsync(FilterDefinition filt { BypassDocumentValidation = options.BypassDocumentValidation, Comment = options.Comment, - Let = options.Let + Let = options.Let, + Timeout = options.Timeout }; var result = await bulkWriteAsync(new[] { model }, bulkWriteOptions).ConfigureAwait(false); return UpdateResult.FromCore(result); diff --git a/src/MongoDB.Driver/ReplaceOptions.cs b/src/MongoDB.Driver/ReplaceOptions.cs index 78757fa355d..8c9fce2fa25 100644 --- a/src/MongoDB.Driver/ReplaceOptions.cs +++ b/src/MongoDB.Driver/ReplaceOptions.cs @@ -15,6 +15,7 @@ using System; using MongoDB.Bson; +using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver { @@ -49,7 +50,8 @@ internal static ReplaceOptions From(UpdateOptions updateOptions) Collation = updateOptions.Collation, Hint = updateOptions.Hint, IsUpsert = updateOptions.IsUpsert, - Let = updateOptions.Let + Let = updateOptions.Let, + Timeout = updateOptions.Timeout }; } } @@ -62,6 +64,7 @@ internal static ReplaceOptions From(UpdateOptions updateOptions) private BsonValue _hint; private bool _isUpsert; private BsonDocument _let; + private TimeSpan? _timeout; // properties /// @@ -117,6 +120,15 @@ public BsonDocument Let get { return _let; } set { _let = value; } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } /// diff --git a/src/MongoDB.Driver/UpdateOptions.cs b/src/MongoDB.Driver/UpdateOptions.cs index 165a81fb00b..86241a6cfc8 100644 --- a/src/MongoDB.Driver/UpdateOptions.cs +++ b/src/MongoDB.Driver/UpdateOptions.cs @@ -13,8 +13,10 @@ * limitations under the License. */ +using System; using System.Collections.Generic; using MongoDB.Bson; +using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver { @@ -31,6 +33,7 @@ public class UpdateOptions private BsonValue _hint; private bool _isUpsert; private BsonDocument _let; + private TimeSpan? _timeout; // properties /// @@ -98,6 +101,15 @@ public BsonDocument Let get { return _let; } set { _let = value; } } + + /// + /// Gets or sets the operation timeout. + /// + public TimeSpan? Timeout + { + get => _timeout; + set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } } ///