Skip to content

Commit 7bd7584

Browse files
author
Oleksandr Poliakov
committed
CSHARP-3549: CSOT: Add timeoutMS to settings
1 parent 23dc1e5 commit 7bd7584

File tree

114 files changed

+1509
-690
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

114 files changed

+1509
-690
lines changed

src/MongoDB.Driver/AggregateOptions.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2015-present MongoDB Inc.
1+
/* Copyright 2010-present MongoDB Inc.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ public class AggregateOptions
3434
private BsonDocument _let;
3535
private TimeSpan? _maxAwaitTime;
3636
private TimeSpan? _maxTime;
37+
private TimeSpan? _timeout;
3738
private ExpressionTranslationOptions _translationOptions;
3839
private bool? _useCursor;
3940

@@ -121,12 +122,22 @@ public TimeSpan? MaxAwaitTime
121122
/// <summary>
122123
/// Gets or sets the maximum time.
123124
/// </summary>
125+
[Obsolete("MaxTime is obsolete and will be removed in a future version. Use Timeout instead.")]
124126
public TimeSpan? MaxTime
125127
{
126128
get { return _maxTime; }
127129
set { _maxTime = Ensure.IsNullOrInfiniteOrGreaterThanOrEqualToZero(value, nameof(value)); }
128130
}
129131

132+
/// <summary>
133+
/// Gets or sets the operation timeout.
134+
/// </summary>
135+
public TimeSpan? Timeout
136+
{
137+
get => _timeout;
138+
set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout));
139+
}
140+
130141
/// <summary>
131142
/// Gets or sets the translation options.
132143
/// </summary>

src/MongoDB.Driver/BulkWriteOptions.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
* limitations under the License.
1414
*/
1515

16+
using System;
1617
using MongoDB.Bson;
18+
using MongoDB.Driver.Core.Misc;
1719

1820
namespace MongoDB.Driver
1921
{
@@ -27,6 +29,7 @@ public sealed class BulkWriteOptions
2729
private BsonValue _comment;
2830
private bool _isOrdered;
2931
private BsonDocument _let;
32+
private TimeSpan? _timeout;
3033

3134
// constructors
3235
/// <summary>
@@ -73,5 +76,14 @@ public BsonDocument Let
7376
get { return _let; }
7477
set { _let = value; }
7578
}
79+
80+
/// <summary>
81+
/// Gets or sets the operation timeout.
82+
/// </summary>
83+
public TimeSpan? Timeout
84+
{
85+
get => _timeout;
86+
set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout));
87+
}
7688
}
7789
}

src/MongoDB.Driver/ChangeStreamOptions.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2017-present MongoDB Inc.
1+
/* Copyright 2010-present MongoDB Inc.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@ public class ChangeStreamOptions
3535
private bool? _showExpandedEvents;
3636
private BsonDocument _startAfter;
3737
private BsonTimestamp _startAtOperationTime;
38+
private TimeSpan? _timeout;
3839

3940
// public properties
4041
/// <summary>
@@ -166,5 +167,14 @@ public BsonTimestamp StartAtOperationTime
166167
get { return _startAtOperationTime; }
167168
set { _startAtOperationTime = value; }
168169
}
170+
171+
/// <summary>
172+
/// Gets or sets the operation timeout.
173+
/// </summary>
174+
public TimeSpan? Timeout
175+
{
176+
get => _timeout;
177+
set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout));
178+
}
169179
}
170180
}

src/MongoDB.Driver/ClientBulkWriteOptions.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
* limitations under the License.
1414
*/
1515

16+
using System;
1617
using MongoDB.Bson;
18+
using MongoDB.Driver.Core.Misc;
1719

1820
namespace MongoDB.Driver
1921
{
@@ -22,6 +24,8 @@ namespace MongoDB.Driver
2224
/// </summary>
2325
public sealed class ClientBulkWriteOptions
2426
{
27+
private TimeSpan? _timeout;
28+
2529
/// <summary>
2630
/// Initializes a new instance of the <see cref="BulkWriteOptions"/> class.
2731
/// </summary>
@@ -75,6 +79,15 @@ public ClientBulkWriteOptions(
7579
/// </summary>
7680
public BsonDocument Let { get; set; }
7781

82+
/// <summary>
83+
/// Gets or sets the operation timeout.
84+
/// </summary>
85+
public TimeSpan? Timeout
86+
{
87+
get => _timeout;
88+
set => _timeout = Ensure.IsNullOrValidTimeout(value, nameof(Timeout));
89+
}
90+
7891
/// <summary>
7992
/// Whether detailed results for each successful operation should be included in the returned results.
8093
/// </summary>

src/MongoDB.Driver/OperationOptionsBase.cs renamed to src/MongoDB.Driver/ClientSessionExtensions.cs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,22 @@
1313
* limitations under the License.
1414
*/
1515

16-
using System;
17-
using System.Threading;
16+
namespace MongoDB.Driver;
1817

19-
namespace MongoDB.Driver
18+
internal static class ClientSessionExtensions
2019
{
21-
internal abstract record OperationOptionsBase(TimeSpan Timeout)
20+
public static ReadPreference GetEffectiveReadPreference(this IClientSession session, ReadPreference defaultReadPreference)
2221
{
23-
public OperationContext ToOperationContext(CancellationToken cancellationToken)
24-
=> new (Timeout, cancellationToken);
22+
if (session.IsInTransaction)
23+
{
24+
var transactionReadPreference = session.WrappedCoreSession.CurrentTransaction.TransactionOptions.ReadPreference;
25+
if (transactionReadPreference != null)
26+
{
27+
return transactionReadPreference;
28+
}
29+
}
30+
31+
return defaultReadPreference ?? ReadPreference.Primary;
2532
}
2633
}
2734

src/MongoDB.Driver/Core/Bindings/CoreSession.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ public bool IsInTransaction
146146
EnsureAbortTransactionCanBeCalled(nameof(AbortTransaction));
147147

148148
// TODO: CSOT implement proper way to obtain the operationContext
149-
var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken);
149+
var operationContext = new OperationContext(null, cancellationToken);
150150
try
151151
{
152152
if (_currentTransaction.IsEmpty)
@@ -197,7 +197,7 @@ public bool IsInTransaction
197197
EnsureAbortTransactionCanBeCalled(nameof(AbortTransaction));
198198

199199
// TODO: CSOT implement proper way to obtain the operationContext
200-
var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken);
200+
var operationContext = new OperationContext(null, cancellationToken);
201201
try
202202
{
203203
if (_currentTransaction.IsEmpty)
@@ -297,7 +297,7 @@ public long AdvanceTransactionNumber()
297297
EnsureCommitTransactionCanBeCalled(nameof(CommitTransaction));
298298

299299
// TODO: CSOT implement proper way to obtain the operationContext
300-
var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken);
300+
var operationContext = new OperationContext(null, cancellationToken);
301301
try
302302
{
303303
_isCommitTransactionInProgress = true;
@@ -334,7 +334,7 @@ public long AdvanceTransactionNumber()
334334
EnsureCommitTransactionCanBeCalled(nameof(CommitTransaction));
335335

336336
// TODO: CSOT implement proper way to obtain the operationContext
337-
var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken);
337+
var operationContext = new OperationContext(null, cancellationToken);
338338
try
339339
{
340340
_isCommitTransactionInProgress = true;

src/MongoDB.Driver/Core/Configuration/ConnectionString.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ public sealed class ConnectionString
9898
private TimeSpan? _socketTimeout;
9999
private int? _srvMaxHosts;
100100
private string _srvServiceName;
101+
private TimeSpan? _timeout;
101102
private bool? _tls;
102103
private bool? _tlsDisableCertificateRevocationCheck;
103104
private bool? _tlsInsecure;
@@ -399,7 +400,6 @@ public bool? RetryReads
399400
get { return _retryReads; }
400401
}
401402

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

471+
/// <summary>
472+
/// Gets the per-operation timeout.
473+
/// </summary>
474+
public TimeSpan? Timeout => _timeout;
475+
471476
/// <summary>
472477
/// Gets whether to use TLS.
473478
/// </summary>
@@ -1089,6 +1094,10 @@ private void ParseOption(string name, string value)
10891094
var sslVerifyCertificateValue = ParseBoolean(name, value);
10901095
_tlsInsecure = EnsureTlsInsecureIsValid(!sslVerifyCertificateValue);
10911096
break;
1097+
case "timeout":
1098+
case "timeoutms":
1099+
_timeout = value == "0" ? System.Threading.Timeout.InfiniteTimeSpan : ParseTimeSpan(name, value);
1100+
break;
10921101
case "tlsdisablecertificaterevocationcheck":
10931102
var tlsDisableCertificateRevocationCheckValue = ParseBoolean(name, value);
10941103
_tlsDisableCertificateRevocationCheck =

src/MongoDB.Driver/Core/Misc/Ensure.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2013-present MongoDB Inc.
1+
/* Copyright 2010-present MongoDB Inc.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -444,11 +444,12 @@ public static string IsNullOrNotEmpty(string value, string paramName)
444444
/// <returns>The value of the parameter.</returns>
445445
public static TimeSpan? IsNullOrValidTimeout(TimeSpan? value, string paramName)
446446
{
447-
if (value != null)
447+
if (value == null)
448448
{
449-
IsValidTimeout(value.Value, paramName);
449+
return null;
450450
}
451-
return value;
451+
452+
return IsValidTimeout(value.Value, paramName);
452453
}
453454

454455
/// <summary>
@@ -459,12 +460,12 @@ public static string IsNullOrNotEmpty(string value, string paramName)
459460
/// <returns>The value of the parameter.</returns>
460461
public static TimeSpan IsValidTimeout(TimeSpan value, string paramName)
461462
{
462-
if (value < TimeSpan.Zero && value != Timeout.InfiniteTimeSpan)
463+
if (value > TimeSpan.Zero || value == Timeout.InfiniteTimeSpan)
463464
{
464-
var message = string.Format("Invalid timeout: {0}.", value);
465-
throw new ArgumentException(message, paramName);
465+
return value;
466466
}
467-
return value;
467+
468+
throw new ArgumentOutOfRangeException($"Invalid timeout: {value}.", paramName);
468469
}
469470

470471
/// <summary>

src/MongoDB.Driver/Core/Misc/Feature.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ public void ThrowIfNotSupported(IMongoClient client, CancellationToken cancellat
570570
{
571571
var cluster = client.GetClusterInternal();
572572
// TODO: CSOT implement proper way to obtain the operationContext
573-
var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken);
573+
var operationContext = new OperationContext(null, cancellationToken);
574574
using (var binding = new ReadWriteBindingHandle(new WritableServerBinding(cluster, NoCoreSession.NewHandle())))
575575
using (var channelSource = binding.GetWriteChannelSource(operationContext))
576576
using (var channel = channelSource.GetChannel(operationContext))
@@ -589,7 +589,7 @@ public async Task ThrowIfNotSupportedAsync(IMongoClient client, CancellationToke
589589
{
590590
var cluster = client.GetClusterInternal();
591591
// TODO: CSOT implement proper way to obtain the operationContext
592-
var operationContext = new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken);
592+
var operationContext = new OperationContext(null, cancellationToken);
593593
using (var binding = new ReadWriteBindingHandle(new WritableServerBinding(cluster, NoCoreSession.NewHandle())))
594594
using (var channelSource = await binding.GetWriteChannelSourceAsync(operationContext).ConfigureAwait(false))
595595
using (var channel = await channelSource.GetChannelAsync(operationContext).ConfigureAwait(false))

src/MongoDB.Driver/Core/Operations/AggregateOperation.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ public IAsyncCursor<TResult> Execute(OperationContext operationContext, Retryabl
288288

289289
using (EventContext.BeginOperation())
290290
{
291-
var operation = CreateOperation(context);
291+
var operation = CreateOperation(operationContext, context);
292292
var result = operation.Execute(operationContext, context);
293293

294294
context.ChannelSource.Session.SetSnapshotTimeIfNeeded(result.AtClusterTime);
@@ -317,7 +317,7 @@ public async Task<IAsyncCursor<TResult>> ExecuteAsync(OperationContext operation
317317

318318
using (EventContext.BeginOperation())
319319
{
320-
var operation = CreateOperation(context);
320+
var operation = CreateOperation(operationContext, context);
321321
var result = await operation.ExecuteAsync(operationContext, context).ConfigureAwait(false);
322322

323323
context.ChannelSource.Session.SetSnapshotTimeIfNeeded(result.AtClusterTime);
@@ -326,15 +326,15 @@ public async Task<IAsyncCursor<TResult>> ExecuteAsync(OperationContext operation
326326
}
327327
}
328328

329-
internal BsonDocument CreateCommand(ConnectionDescription connectionDescription, ICoreSession session)
329+
internal BsonDocument CreateCommand(OperationContext operationContext, ICoreSession session, ConnectionDescription connectionDescription)
330330
{
331331
var readConcern = ReadConcernHelper.GetReadConcernForCommand(session, connectionDescription, _readConcern);
332332
var command = new BsonDocument
333333
{
334334
{ "aggregate", _collectionNamespace == null ? (BsonValue)1 : _collectionNamespace.CollectionName },
335335
{ "pipeline", new BsonArray(_pipeline) },
336336
{ "allowDiskUse", () => _allowDiskUse.Value, _allowDiskUse.HasValue },
337-
{ "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue },
337+
{ "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue && !operationContext.IsRootContextTimeoutConfigured() },
338338
{ "collation", () => _collation.ToBsonDocument(), _collation != null },
339339
{ "hint", _hint, _hint != null },
340340
{ "let", _let, _let != null },
@@ -354,10 +354,10 @@ internal BsonDocument CreateCommand(ConnectionDescription connectionDescription,
354354

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

357-
private ReadCommandOperation<AggregateResult> CreateOperation(RetryableReadContext context)
357+
private ReadCommandOperation<AggregateResult> CreateOperation(OperationContext operationContext, RetryableReadContext context)
358358
{
359359
var databaseNamespace = _collectionNamespace == null ? _databaseNamespace : _collectionNamespace.DatabaseNamespace;
360-
var command = CreateCommand(context.Channel.ConnectionDescription, context.Binding.Session);
360+
var command = CreateCommand(operationContext, context.Binding.Session, context.Channel.ConnectionDescription);
361361
var serializer = new AggregateResultDeserializer(_resultSerializer);
362362
return new ReadCommandOperation<AggregateResult>(databaseNamespace, command, serializer, MessageEncoderSettings)
363363
{

0 commit comments

Comments
 (0)