Skip to content

CSHARP-3549: CSOT: Add timeoutMS to settings #1721

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion src/MongoDB.Driver/AggregateOptions.cs
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -121,12 +122,22 @@ public TimeSpan? MaxAwaitTime
/// <summary>
/// Gets or sets the maximum time.
/// </summary>
[Obsolete("Use Timeout instead")]
public TimeSpan? MaxTime
{
get { return _maxTime; }
set { _maxTime = Ensure.IsNullOrInfiniteOrGreaterThanOrEqualToZero(value, nameof(value)); }
}

/// <summary>
/// Gets or sets the operation timeout.
/// </summary>
public TimeSpan? Timeout
{
get => _timeout;
set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout));
}

/// <summary>
/// Gets or sets the translation options.
/// </summary>
Expand Down
12 changes: 12 additions & 0 deletions src/MongoDB.Driver/BulkWriteOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
* limitations under the License.
*/

using System;
using MongoDB.Bson;
using MongoDB.Driver.Core.Misc;

namespace MongoDB.Driver
{
Expand All @@ -27,6 +29,7 @@ public sealed class BulkWriteOptions
private BsonValue _comment;
private bool _isOrdered;
private BsonDocument _let;
private TimeSpan? _timeout;

// constructors
/// <summary>
Expand Down Expand Up @@ -73,5 +76,14 @@ public BsonDocument Let
get { return _let; }
set { _let = value; }
}

/// <summary>
/// Gets or sets the operation timeout.
/// </summary>
public TimeSpan? Timeout
{
get => _timeout;
set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout));
}
}
}
12 changes: 11 additions & 1 deletion src/MongoDB.Driver/ChangeStreamOptions.cs
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -35,6 +35,7 @@ public class ChangeStreamOptions
private bool? _showExpandedEvents;
private BsonDocument _startAfter;
private BsonTimestamp _startAtOperationTime;
private TimeSpan? _timeout;

// public properties
/// <summary>
Expand Down Expand Up @@ -166,5 +167,14 @@ public BsonTimestamp StartAtOperationTime
get { return _startAtOperationTime; }
set { _startAtOperationTime = value; }
}

/// <summary>
/// Gets or sets the operation timeout.
/// </summary>
public TimeSpan? Timeout
{
get => _timeout;
set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout));
}
}
}
13 changes: 13 additions & 0 deletions src/MongoDB.Driver/ClientBulkWriteOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
* limitations under the License.
*/

using System;
using MongoDB.Bson;
using MongoDB.Driver.Core.Misc;

namespace MongoDB.Driver
{
Expand All @@ -22,6 +24,8 @@ namespace MongoDB.Driver
/// </summary>
public sealed class ClientBulkWriteOptions
{
private TimeSpan? _timeout;

/// <summary>
/// Initializes a new instance of the <see cref="BulkWriteOptions"/> class.
/// </summary>
Expand Down Expand Up @@ -75,6 +79,15 @@ public ClientBulkWriteOptions(
/// </summary>
public BsonDocument Let { get; set; }

/// <summary>
/// Gets or sets the operation timeout.
/// </summary>
public TimeSpan? Timeout
{
get => _timeout;
set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout));
}

/// <summary>
/// Whether detailed results for each successful operation should be included in the returned results.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

11 changes: 10 additions & 1 deletion src/MongoDB.Driver/Core/Configuration/ConnectionString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -399,7 +400,6 @@ public bool? RetryReads
get { return _retryReads; }
}


/// <summary>
/// Gets a value indicating whether or not to retry writes.
/// </summary>
Expand Down Expand Up @@ -468,6 +468,11 @@ public bool? Ssl
[Obsolete("Use TlsInsecure instead.")]
public bool? SslVerifyCertificate => !_tlsInsecure;

/// <summary>
/// Gets the per-operation timeout
/// </summary>
public TimeSpan? Timeout => _timeout;

/// <summary>
/// Gets whether to use TLS.
/// </summary>
Expand Down Expand Up @@ -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 = ParseTimeSpan(name, value);
break;
case "tlsdisablecertificaterevocationcheck":
var tlsDisableCertificateRevocationCheckValue = ParseBoolean(name, value);
_tlsDisableCertificateRevocationCheck =
Expand Down
17 changes: 9 additions & 8 deletions src/MongoDB.Driver/Core/Misc/Ensure.cs
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -444,11 +444,12 @@ public static string IsNullOrNotEmpty(string value, string paramName)
/// <returns>The value of the parameter.</returns>
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);
}

/// <summary>
Expand All @@ -459,12 +460,12 @@ public static string IsNullOrNotEmpty(string value, string paramName)
/// <returns>The value of the parameter.</returns>
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);
}

/// <summary>
Expand Down
12 changes: 6 additions & 6 deletions src/MongoDB.Driver/Core/Operations/AggregateOperation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ public IAsyncCursor<TResult> 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);
Expand Down Expand Up @@ -317,7 +317,7 @@ public async Task<IAsyncCursor<TResult>> 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);
Expand All @@ -326,15 +326,15 @@ public async Task<IAsyncCursor<TResult>> 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
{
{ "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 },
Expand All @@ -354,10 +354,10 @@ internal BsonDocument CreateCommand(ConnectionDescription connectionDescription,

private IDisposable BeginOperation() => EventContext.BeginOperation(null, "aggregate");

private ReadCommandOperation<AggregateResult> CreateOperation(RetryableReadContext context)
private ReadCommandOperation<AggregateResult> 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<AggregateResult>(databaseNamespace, command, serializer, MessageEncoderSettings)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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);
}
}
Expand All @@ -172,12 +172,12 @@ public async Task<BsonDocument> 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)
Expand All @@ -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 },
Expand All @@ -202,9 +202,9 @@ public BsonDocument CreateCommand(ICoreSessionHandle session, ConnectionDescript

private IDisposable BeginOperation() => EventContext.BeginOperation("aggregate");

private WriteCommandOperation<BsonDocument> CreateOperation(ICoreSessionHandle session, ConnectionDescription connectionDescription, ReadPreference effectiveReadPreference)
private WriteCommandOperation<BsonDocument> CreateOperation(OperationContext operationContext, ICoreSessionHandle session, ConnectionDescription connectionDescription, ReadPreference effectiveReadPreference)
{
var command = CreateCommand(session, connectionDescription);
var command = CreateCommand(operationContext, session, connectionDescription);
var operation = new WriteCommandOperation<BsonDocument>(_databaseNamespace, command, BsonDocumentSerializer.Instance, MessageEncoderSettings);
if (effectiveReadPreference != null)
{
Expand Down
14 changes: 7 additions & 7 deletions src/MongoDB.Driver/Core/Operations/CountOperation.cs
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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 }
Expand All @@ -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();
}
Expand All @@ -157,16 +157,16 @@ public async Task<long> ExecuteAsync(OperationContext operationContext, IReadBin

public async Task<long> 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<BsonDocument> CreateOperation(RetryableReadContext context)
private ReadCommandOperation<BsonDocument> 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<BsonDocument>(_collectionNamespace.DatabaseNamespace, command, BsonDocumentSerializer.Instance, _messageEncoderSettings)
{
RetryRequested = _retryRequested // might be overridden by retryable read context
Expand Down
Loading