diff --git a/src/MongoDB.Driver/AggregateOptions.cs b/src/MongoDB.Driver/AggregateOptions.cs index cafe47e785b..65267d669a8 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("MaxTime is obsolete and will be removed in a future version. 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/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/Configuration/ConnectionString.cs b/src/MongoDB.Driver/Core/Configuration/ConnectionString.cs index 79349c035cc..e92479d1cc3 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,11 @@ public bool? Ssl [Obsolete("Use TlsInsecure instead.")] public bool? SslVerifyCertificate => !_tlsInsecure; + /// + /// Gets the per-operation timeout. + /// + public TimeSpan? Timeout => _timeout; + /// /// Gets whether to use TLS. /// @@ -1089,6 +1094,10 @@ private void ParseOption(string name, string value) var sslVerifyCertificateValue = ParseBoolean(name, value); _tlsInsecure = EnsureTlsInsecureIsValid(!sslVerifyCertificateValue); break; + case "timeout": + case "timeoutms": + _timeout = value == "0" ? System.Threading.Timeout.InfiniteTimeSpan : ParseTimeSpan(name, value); + break; case "tlsdisablecertificaterevocationcheck": var tlsDisableCertificateRevocationCheckValue = ParseBoolean(name, value); _tlsDisableCertificateRevocationCheck = diff --git a/src/MongoDB.Driver/Core/Misc/Ensure.cs b/src/MongoDB.Driver/Core/Misc/Ensure.cs index 7fbab39b9b7..8cd1163f7f1 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 ArgumentOutOfRangeException($"Invalid timeout: {value}.", paramName); } /// 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/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/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/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/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/Core/WireProtocol/CommandUsingCommandMessageWireProtocol.cs b/src/MongoDB.Driver/Core/WireProtocol/CommandUsingCommandMessageWireProtocol.cs index 25481d385a6..7f572c96297 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/CountOptions.cs b/src/MongoDB.Driver/CountOptions.cs index 2a85963cda7..5507b26e50c 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("MaxTime is obsolete and will be removed in a future version. 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..ab372a81fd7 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("MaxTime is obsolete and will be removed in a future version. 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..553a4e81d12 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("MaxTime is obsolete and will be removed in a future version. 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/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/DistinctOptions.cs b/src/MongoDB.Driver/DistinctOptions.cs index 5aee87e814e..12cffefc521 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("MaxTime is obsolete and will be removed in a future version. 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..e4e4060e607 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("MaxTime is obsolete and will be removed in a future version. 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..2dc5740075e 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("MaxTime is obsolete and will be removed in a future version. 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..3a50bb2c27a 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("MaxTime is obsolete and will be removed in a future version. 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..c6353cc3105 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("MaxTime is obsolete and will be removed in a future version. 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..ba976fcf635 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("MaxTime is obsolete and will be removed in a future version. 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..29569dcdb23 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("MaxTime is obsolete and will be removed in a future version. 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/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/src/MongoDB.Driver/IInheritableMongoClientSettings.cs b/src/MongoDB.Driver/IInheritableMongoClientSettings.cs index 04eb99990f3..2e54fda9d4c 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..edf59ca8b4e 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. @@ -18,7 +18,6 @@ using MongoDB.Bson; using MongoDB.Driver.Core.Clusters; using MongoDB.Driver.Core.Misc; -using MongoDB.Driver.Core.Operations; namespace MongoDB.Driver { diff --git a/src/MongoDB.Driver/IMongoCollectionExtensions.cs b/src/MongoDB.Driver/IMongoCollectionExtensions.cs index fe5277a10d3..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 }; } diff --git a/src/MongoDB.Driver/IMongoDatabaseExtensions.cs b/src/MongoDB.Driver/IMongoDatabaseExtensions.cs index 81c1bb67174..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. 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/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/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..b898f58b55d 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("MaxTime is obsolete and will be removed in a future version. 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 0df21ba32cc..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: Timeout.InfiniteTimeSpan, DefaultReadPreference: _settings.ReadPreference); - _writeOperationOptions = new(Timeout: Timeout.InfiniteTimeSpan); 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); } /// @@ -549,6 +546,7 @@ private ListDatabasesOptions CreateListDatabasesOptionsFromListDatabaseNamesOpti listDatabasesOptions.AuthorizedDatabases = options.AuthorizedDatabases; listDatabasesOptions.Filter = options.Filter; listDatabasesOptions.Comment = options.Comment; + listDatabasesOptions.Timeout = options.Timeout; } return listDatabasesOptions; @@ -565,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 d7da362ca92..fd76f48f141 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,19 @@ public SslSettings SslSettings } } + /// + /// Gets or sets the per-operation timeout + /// + public TimeSpan? Timeout + { + get { return _timeout; } + set + { + ThrowIfFrozen(); + _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } + } + /// /// Gets or sets the translation options. /// @@ -881,6 +895,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 +950,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 +1020,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 +1108,7 @@ public override int GetHashCode() .Hash(_srvMaxHosts) .Hash(_srvServiceName) .Hash(_sslSettings) + .Hash(_timeout) .Hash(_translationOptions) .Hash(_useTls) .Hash(_waitQueueSize) @@ -1172,6 +1190,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..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); @@ -435,7 +439,8 @@ 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); } @@ -524,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); } @@ -598,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); @@ -656,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); @@ -697,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); @@ -738,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); @@ -784,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); @@ -830,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/MongoCollectionImpl.cs b/src/MongoDB.Driver/MongoCollectionImpl.cs index 8ad05198a18..310d2ca29c3 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: Timeout.InfiniteTimeSpan, DefaultReadPreference: _settings.ReadPreference); - _writeOperationOptions = new(Timeout: Timeout.InfiniteTimeSpan); } // 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) @@ -769,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 @@ -786,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 }; @@ -794,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; } @@ -815,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, }; @@ -953,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, }; @@ -964,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 }; } @@ -988,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), @@ -1052,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 @@ -1127,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), @@ -1165,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 @@ -1190,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, ReadOperationOptions options, CancellationToken cancellationToken) - => _operationExecutor.ExecuteReadOperation(session, operation, options, true, cancellationToken); + private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, TimeSpan? timeout, CancellationToken cancellationToken) + => ExecuteReadOperation(session, operation, null, timeout, 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() { @@ -1385,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()); } @@ -1414,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()); } @@ -1434,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) @@ -1453,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) @@ -1478,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) @@ -1503,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) @@ -1522,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) @@ -1541,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 @@ -1553,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); } @@ -1650,7 +1685,8 @@ public async Task> CreateManyAsync(IEnumerable List(string indexName, AggregateOptions aggregateOptions = null, CancellationToken cancellationToken = default) @@ -1700,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 a8489008921..f268074d09f 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 TimeSpan? _timeout; private Setting _writeConcern; private Setting _writeEncoding; @@ -121,6 +121,19 @@ public IBsonSerializerRegistry SerializerRegistry get { return BsonSerializer.SerializerRegistry; } } + /// + /// Gets or sets the per-operation timeout + /// + public TimeSpan? Timeout + { + get { return _timeout; } + set + { + if (_isFrozen) { throw new InvalidOperationException("MongoCollectionSettings is frozen."); } + _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } + } + /// /// Gets or sets the WriteConcern to use. /// @@ -163,6 +176,7 @@ public virtual MongoCollectionSettings Clone() clone._readConcern = _readConcern.Clone(); clone._readEncoding = _readEncoding.Clone(); clone._readPreference = _readPreference.Clone(); + clone._timeout = _timeout; clone._writeConcern = _writeConcern.Clone(); clone._writeEncoding = _writeEncoding.Clone(); return clone; @@ -193,6 +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 == rhs._timeout && _writeConcern.Value == rhs._writeConcern.Value && object.Equals(_writeEncoding, rhs._writeEncoding); } @@ -247,6 +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.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 +287,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.HasValue) + { + parts.Add(string.Format("Timeout={0}", _timeout)); + } parts.Add(string.Format("WriteConcern={0}", _writeConcern)); if (_writeEncoding.HasBeenSet) { @@ -298,6 +318,10 @@ internal void ApplyDefaultValues(MongoDatabaseSettings databaseSettings) { ReadPreference = databaseSettings.ReadPreference; } + if (!_timeout.HasValue) + { + 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..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: Timeout.InfiniteTimeSpan, DefaultReadPreference: _settings.ReadPreference); - _writeOperationOptions = new(Timeout: Timeout.InfiniteTimeSpan); } // 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) @@ -534,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 @@ -556,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 }; @@ -564,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; } @@ -586,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) @@ -743,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 b82ea52828d..4b80b6023e3 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 TimeSpan? _timeout; private Setting _writeConcern; private Setting _writeEncoding; @@ -106,6 +106,19 @@ public IBsonSerializerRegistry SerializerRegistry get { return BsonSerializer.SerializerRegistry; } } + /// + /// Gets or sets the per-operation timeout + /// + public TimeSpan? Timeout + { + get { return _timeout; } + set + { + if (_isFrozen) { throw new InvalidOperationException("MongoCollectionSettings is frozen."); } + _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } + } + /// /// Gets or sets the WriteConcern to use. /// @@ -147,6 +160,7 @@ public MongoDatabaseSettings Clone() clone._readConcern = _readConcern.Clone(); clone._readEncoding = _readEncoding.Clone(); clone._readPreference = _readPreference.Clone(); + clone._timeout = _timeout; clone._writeConcern = _writeConcern.Clone(); clone._writeEncoding = _writeEncoding.Clone(); return clone; @@ -176,6 +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 == rhs._timeout && _writeConcern.Value == rhs._writeConcern.Value && object.Equals(_writeEncoding, rhs._writeEncoding); } @@ -229,6 +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?.GetHashCode() ?? 0; hash = 37 * hash + ((_writeConcern.Value == null) ? 0 : _writeConcern.Value.GetHashCode()); hash = 37 * hash + ((_writeEncoding.Value == null) ? 0 : _writeEncoding.GetHashCode()); return hash; @@ -252,6 +268,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.HasValue) + { + parts.Add(string.Format("Timeout={0}", _timeout.Value)); + } parts.Add(string.Format("WriteConcern={0}", _writeConcern.Value)); if (_writeEncoding.HasBeenSet) { @@ -275,6 +295,10 @@ internal void ApplyDefaultValues(IInheritableMongoClientSettings clientSettings) { ReadPreference = clientSettings.ReadPreference; } + if (!_timeout.HasValue) + { + Timeout = clientSettings.Timeout; + } if (!_writeConcern.HasBeenSet) { WriteConcern = clientSettings.WriteConcern; 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 2c1446fd57c..b7d972aaaff 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,11 @@ public string SrvServiceName get { return _srvServiceName; } } + /// + /// Gets the per-operation timeout + /// + public TimeSpan? Timeout => _timeout; + /// /// Gets whether or not to disable checking certificate revocation status during the TLS handshake. /// @@ -751,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 3858228cbf6..e8302eb09be 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 = null; _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,18 @@ public string SrvServiceName } } + /// + /// Gets or sets the per-operation timeout + /// + public TimeSpan? Timeout + { + get { return _timeout; } + set + { + _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout)); + } + } + /// /// Gets or sets whether to disable certificate revocation checking during the TLS handshake. /// @@ -956,6 +969,10 @@ public override string ToString() { query.AppendFormat("socketTimeout={0}&", FormatTimeSpan(_socketTimeout)); } + if (_timeout.HasValue) + { + query.AppendFormat("timeout={0}&", _timeout == System.Threading.Timeout.InfiniteTimeSpan ? "0" : FormatTimeSpan(_timeout.Value)); + } #pragma warning disable 618 if (_waitQueueMultiple != 0.0 && _waitQueueMultiple != MongoDefaults.WaitQueueMultiple) #pragma warning restore 618 @@ -1045,6 +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; _tlsDisableCertificateRevocationCheck = connectionString.TlsDisableCertificateRevocationCheck; _username = connectionString.Username; _useTls = connectionString.Tls.GetValueOrDefault(false); @@ -1065,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/OfTypeMongoCollection.cs b/src/MongoDB.Driver/OfTypeMongoCollection.cs index a1b1dd69220..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. diff --git a/src/MongoDB.Driver/OperationContext.cs b/src/MongoDB.Driver/OperationContext.cs index a2ea007b93e..d2a18e6e729 100644 --- a/src/MongoDB.Driver/OperationContext.cs +++ b/src/MongoDB.Driver/OperationContext.cs @@ -24,20 +24,20 @@ 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; - 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.IsNullOrInfiniteOrGreaterThanOrEqualToZero(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/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)); + } } /// 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/Core/Configuration/ConnectionStringTests.cs b/tests/MongoDB.Driver.Tests/Core/Configuration/ConnectionStringTests.cs index ded3872bc19..f42955da715 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,22 @@ public void When_sslVerifyCertificate_is_specified(string connectionString, bool #pragma warning restore 618 } + [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)] + [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/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/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/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..799c36a9186 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().BeAssignableTo().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/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/MongoUrlBuilderTests.cs b/tests/MongoDB.Driver.Tests/MongoUrlBuilderTests.cs index 0ed8719d185..f45282623dc 100644 --- a/tests/MongoDB.Driver.Tests/MongoUrlBuilderTests.cs +++ b/tests/MongoDB.Driver.Tests/MongoUrlBuilderTests.cs @@ -94,6 +94,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 +141,7 @@ public void TestAll() "serverMonitoringMode=Poll", "serverSelectionTimeout=10s", "socketTimeout=7s", + "timeout=13s", "waitQueueSize=123", "waitQueueTimeout=8s", "retryReads=false", @@ -185,6 +187,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 +446,7 @@ public void TestDefaults() Assert.Equal(MongoDefaults.LocalThreshold, builder.LocalThreshold); Assert.Equal(MongoDefaults.ServerSelectionTimeout, builder.ServerSelectionTimeout); Assert.Equal(MongoDefaults.SocketTimeout, builder.SocketTimeout); + Assert.Equal(null, builder.Timeout); Assert.Equal(MongoInternalDefaults.MongoClientSettings.SrvServiceName, builder.SrvServiceName); Assert.Equal(null, builder.Username); #pragma warning disable 618 @@ -1136,6 +1140,28 @@ public void TestSocketTimeout_Range() builder.SocketTimeout = TimeSpan.FromSeconds(1); } + [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" })] + [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, 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 diff --git a/tests/MongoDB.Driver.Tests/OperationExecutorTests.cs b/tests/MongoDB.Driver.Tests/OperationExecutorTests.cs index 267d3db0620..c703c27acdf 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,18 +55,18 @@ 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"); + .Subject.ParamName.Should().Be("readPreference"); } [Theory] @@ -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();