Skip to content

Commit 3e7b379

Browse files
author
Oleksandr Poliakov
committed
CSHARP-3549: CSOT: Add timeoutMS to settings
1 parent ca6234d commit 3e7b379

18 files changed

+251
-16
lines changed

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

Lines changed: 11 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,12 @@ 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+
// TODO: CSOT: Make it public when CSOT will be ready for GA release
475+
internal TimeSpan? Timeout => _timeout;
476+
471477
/// <summary>
472478
/// Gets whether to use TLS.
473479
/// </summary>
@@ -1089,6 +1095,10 @@ private void ParseOption(string name, string value)
10891095
var sslVerifyCertificateValue = ParseBoolean(name, value);
10901096
_tlsInsecure = EnsureTlsInsecureIsValid(!sslVerifyCertificateValue);
10911097
break;
1098+
case "timeout":
1099+
case "timeoutms":
1100+
_timeout = ParseTimeSpan(name, value);
1101+
break;
10921102
case "tlsdisablecertificaterevocationcheck":
10931103
var tlsDisableCertificateRevocationCheckValue = ParseBoolean(name, value);
10941104
_tlsDisableCertificateRevocationCheck =

src/MongoDB.Driver/IInheritableMongoClientSettings.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
using System;
1717
using System.Text;
18-
using MongoDB.Bson;
1918

2019
namespace MongoDB.Driver
2120
{
@@ -24,6 +23,7 @@ internal interface IInheritableMongoClientSettings
2423
ReadConcern ReadConcern { get; }
2524
UTF8Encoding ReadEncoding { get; }
2625
ReadPreference ReadPreference { get; }
26+
TimeSpan Timeout { get; }
2727
WriteConcern WriteConcern { get; }
2828
UTF8Encoding WriteEncoding { get; }
2929
}

src/MongoDB.Driver/IMongoClientExtensions.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2018-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.
@@ -13,12 +13,12 @@
1313
* limitations under the License.
1414
*/
1515

16+
using System;
1617
using System.Threading;
1718
using System.Threading.Tasks;
1819
using MongoDB.Bson;
1920
using MongoDB.Driver.Core.Clusters;
2021
using MongoDB.Driver.Core.Misc;
21-
using MongoDB.Driver.Core.Operations;
2222

2323
namespace MongoDB.Driver
2424
{
@@ -109,6 +109,18 @@ public static Task<IChangeStreamCursor<ChangeStreamDocument<BsonDocument>>> Watc
109109
return client.WatchAsync(session, emptyPipeline, options, cancellationToken);
110110
}
111111

112+
/// <summary>
113+
/// Returns a new IMongoClient instance with a different timeout setting.
114+
/// </summary>
115+
/// <param name="client">The client.</param>
116+
/// <param name="timeout">The timeout.</param>
117+
// TODO: CSOT: Make it public when CSOT will be ready for GA release
118+
internal static IMongoClient WithTimeout(this IMongoClient client, TimeSpan timeout)
119+
{
120+
Ensure.IsNotNull(client, nameof(client));
121+
return ((MongoClient)client).WithTimeout(timeout);
122+
}
123+
112124
// internal static methods
113125
internal static IClusterInternal GetClusterInternal(this IMongoClient client) => (IClusterInternal)client.Cluster;
114126
}

src/MongoDB.Driver/IMongoCollectionExtensions.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2653,6 +2653,18 @@ public static Task<IChangeStreamCursor<ChangeStreamDocument<TDocument>>> WatchAs
26532653
return collection.WatchAsync(session, emptyPipeline, options, cancellationToken);
26542654
}
26552655

2656+
/// <summary>
2657+
/// Returns a new IMongoDatabase instance with a different timeout setting.
2658+
/// </summary>
2659+
/// <param name="collection">The collection.</param>
2660+
/// <param name="timeout">The timeout.</param>
2661+
// TODO: CSOT: Make it public when CSOT will be ready for GA release
2662+
internal static IMongoCollection<TDocument> WithTimeout<TDocument>(this IMongoCollection<TDocument> collection, TimeSpan timeout)
2663+
{
2664+
Ensure.IsNotNull(collection, nameof(collection));
2665+
return ((MongoCollectionBase<TDocument>)collection).WithTimeout(timeout);
2666+
}
2667+
26562668
// private static methods
26572669
private static IQueryable<TDocument> AsQueryableHelper<TDocument>(IMongoCollection<TDocument> collection, IClientSessionHandle session, AggregateOptions aggregateOptions)
26582670
{

src/MongoDB.Driver/IMongoDatabaseExtensions.cs

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

16+
using System;
1617
using System.Linq;
1718
using System.Threading;
1819
using System.Threading.Tasks;
@@ -167,6 +168,18 @@ public static Task<IChangeStreamCursor<ChangeStreamDocument<BsonDocument>>> Watc
167168
return database.WatchAsync(session, emptyPipeline, options, cancellationToken);
168169
}
169170

171+
/// <summary>
172+
/// Returns a new IMongoDatabase instance with a different timeout setting.
173+
/// </summary>
174+
/// <param name="database">The database.</param>
175+
/// <param name="timeout">The timeout.</param>
176+
// TODO: CSOT: Make it public when CSOT will be ready for GA release
177+
internal static IMongoDatabase WithTimeout(this IMongoDatabase database, TimeSpan timeout)
178+
{
179+
Ensure.IsNotNull(database, nameof(database));
180+
return ((MongoDatabase)database).WithTimeout(timeout);
181+
}
182+
170183
// private static methods
171184
private static IQueryable<NoPipelineInput> AsQueryableHelper(IMongoDatabase database, IClientSessionHandle session, AggregateOptions aggregateOptions)
172185
{

src/MongoDB.Driver/MongoClient.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ internal MongoClient(MongoClientSettings settings, Func<IMongoClient, IOperation
9393
_cluster = _settings.ClusterSource.Get(_settings.ToClusterKey());
9494
_operationExecutor = _operationExecutorFactory(this);
9595
// TODO: CSOT populate the timeout from settings
96-
_readOperationOptions = new(Timeout: Timeout.InfiniteTimeSpan, DefaultReadPreference: _settings.ReadPreference);
97-
_writeOperationOptions = new(Timeout: Timeout.InfiniteTimeSpan);
96+
_readOperationOptions = new(Timeout: _settings.Timeout, DefaultReadPreference: _settings.ReadPreference);
97+
_writeOperationOptions = new(Timeout: _settings.Timeout);
9898

9999
if (settings.AutoEncryptionOptions != null)
100100
{
@@ -471,6 +471,17 @@ public IMongoClient WithReadPreference(ReadPreference readPreference)
471471
return new MongoClient(newSettings, _operationExecutorFactory);
472472
}
473473

474+
// TODO: Should move WithTimeout into IMongoClient interface and made the method public
475+
internal IMongoClient WithTimeout(TimeSpan timeout)
476+
{
477+
Ensure.IsGreaterThanZero(timeout, nameof(timeout));
478+
ThrowIfDisposed();
479+
480+
var newSettings = Settings.Clone();
481+
newSettings.Timeout = timeout;
482+
return new MongoClient(newSettings, _operationExecutorFactory);
483+
}
484+
474485
/// <inheritdoc/>
475486
public IMongoClient WithWriteConcern(WriteConcern writeConcern)
476487
{

src/MongoDB.Driver/MongoClientSettings.cs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
using MongoDB.Driver.Core.Configuration;
2323
using MongoDB.Driver.Core.Misc;
2424
using MongoDB.Driver.Core.Servers;
25-
using MongoDB.Driver.Encryption;
2625
using MongoDB.Shared;
2726

2827
namespace MongoDB.Driver
@@ -74,6 +73,7 @@ public class MongoClientSettings : IEquatable<MongoClientSettings>, IInheritable
7473
private int _srvMaxHosts;
7574
private string _srvServiceName;
7675
private SslSettings _sslSettings;
76+
private TimeSpan _timeout;
7777
private ExpressionTranslationOptions _translationOptions;
7878
private bool _useTls;
7979
private int _waitQueueSize;
@@ -125,6 +125,7 @@ public MongoClientSettings()
125125
_srvMaxHosts = 0;
126126
_srvServiceName = MongoInternalDefaults.MongoClientSettings.SrvServiceName;
127127
_sslSettings = null;
128+
_timeout = System.Threading.Timeout.InfiniteTimeSpan;
128129
_translationOptions = null;
129130
_useTls = false;
130131
#pragma warning disable 618
@@ -666,6 +667,23 @@ public SslSettings SslSettings
666667
}
667668
}
668669

670+
/// <summary>
671+
/// Gets or sets the per-operation timeout
672+
/// </summary>
673+
// TODO: CSOT: Make it public when CSOT will be ready for GA release
674+
internal TimeSpan Timeout
675+
{
676+
get { return _timeout; }
677+
set
678+
{
679+
ThrowIfFrozen();
680+
_timeout = Ensure.IsInfiniteOrGreaterThanZero(value, nameof(Timeout));
681+
}
682+
}
683+
684+
// TODO: CSOT: Remove this explicit interface implementaion in favor of public Timeout property
685+
TimeSpan IInheritableMongoClientSettings.Timeout => _timeout;
686+
669687
/// <summary>
670688
/// Gets or sets the translation options.
671689
/// </summary>
@@ -881,6 +899,7 @@ public static MongoClientSettings FromUrl(MongoUrl url)
881899
{
882900
clientSettings.SslSettings = new SslSettings { CheckCertificateRevocation = false };
883901
}
902+
clientSettings.Timeout = url.Timeout;
884903
clientSettings.UseTls = url.UseTls;
885904
#pragma warning disable 618
886905
clientSettings.WaitQueueSize = url.ComputedWaitQueueSize;
@@ -935,6 +954,7 @@ public MongoClientSettings Clone()
935954
clone._srvMaxHosts = _srvMaxHosts;
936955
clone._srvServiceName = _srvServiceName;
937956
clone._sslSettings = (_sslSettings == null) ? null : _sslSettings.Clone();
957+
clone._timeout = _timeout;
938958
clone._translationOptions = _translationOptions;
939959
clone._useTls = _useTls;
940960
clone._waitQueueSize = _waitQueueSize;
@@ -1004,6 +1024,7 @@ public override bool Equals(object obj)
10041024
_srvMaxHosts == rhs._srvMaxHosts &&
10051025
_srvServiceName == rhs._srvServiceName &&
10061026
_sslSettings == rhs._sslSettings &&
1027+
_timeout == rhs._timeout &&
10071028
object.Equals(_translationOptions, rhs._translationOptions) &&
10081029
_useTls == rhs._useTls &&
10091030
_waitQueueSize == rhs._waitQueueSize &&
@@ -1091,6 +1112,7 @@ public override int GetHashCode()
10911112
.Hash(_srvMaxHosts)
10921113
.Hash(_srvServiceName)
10931114
.Hash(_sslSettings)
1115+
.Hash(_timeout)
10941116
.Hash(_translationOptions)
10951117
.Hash(_useTls)
10961118
.Hash(_waitQueueSize)
@@ -1172,6 +1194,10 @@ public override string ToString()
11721194
{
11731195
sb.AppendFormat("SslSettings={0};", _sslSettings);
11741196
}
1197+
if(_timeout != System.Threading.Timeout.InfiniteTimeSpan)
1198+
{
1199+
sb.AppendFormat("Timeout={0};", _timeout);
1200+
}
11751201
sb.AppendFormat("Tls={0};", _useTls);
11761202
sb.AppendFormat("TlsInsecure={0};", _allowInsecureTls);
11771203
if (_translationOptions != null)

src/MongoDB.Driver/MongoCollectionBase.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,9 @@ public virtual IMongoCollection<TDocument> WithReadConcern(ReadConcern readConce
882882

883883
public abstract IMongoCollection<TDocument> WithReadPreference(ReadPreference readPreference);
884884

885+
// TODO: Should move WithTimeout into IMongoCollection interface and made the method public
886+
internal abstract IMongoCollection<TDocument> WithTimeout(TimeSpan timeout);
887+
885888
public abstract IMongoCollection<TDocument> WithWriteConcern(WriteConcern writeConcern);
886889
}
887890
}

src/MongoDB.Driver/MongoCollectionImpl.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ private MongoCollectionImpl(IMongoDatabase database, CollectionNamespace collect
5959

6060
_messageEncoderSettings = GetMessageEncoderSettings();
6161
// TODO: CSOT populate the timeout from settings
62-
_readOperationOptions = new(Timeout: Timeout.InfiniteTimeSpan, DefaultReadPreference: _settings.ReadPreference);
63-
_writeOperationOptions = new(Timeout: Timeout.InfiniteTimeSpan);
62+
_readOperationOptions = new(Timeout: _settings.Timeout, DefaultReadPreference: _settings.ReadPreference);
63+
_writeOperationOptions = new(Timeout: _settings.Timeout);
6464
}
6565

6666
// properties
@@ -659,6 +659,13 @@ public override IMongoCollection<TDocument> WithReadConcern(ReadConcern readConc
659659
return new MongoCollectionImpl<TDocument>(_database, _collectionNamespace, newSettings, _cluster, _operationExecutor);
660660
}
661661

662+
internal override IMongoCollection<TDocument> WithTimeout(TimeSpan timeout)
663+
{
664+
var newSettings = _settings.Clone();
665+
newSettings.Timeout = timeout;
666+
return new MongoCollectionImpl<TDocument>(_database, _collectionNamespace, newSettings, _cluster, _operationExecutor);
667+
}
668+
662669
public override IMongoCollection<TDocument> WithReadPreference(ReadPreference readPreference)
663670
{
664671
var newSettings = _settings.Clone();

src/MongoDB.Driver/MongoCollectionSettings.cs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
using System;
1717
using System.Collections.Generic;
1818
using System.Text;
19-
using MongoDB.Bson;
2019
using MongoDB.Bson.Serialization;
2120
using MongoDB.Driver.Core.Misc;
2221

@@ -32,6 +31,7 @@ public class MongoCollectionSettings
3231
private Setting<ReadConcern> _readConcern;
3332
private Setting<UTF8Encoding> _readEncoding;
3433
private Setting<ReadPreference> _readPreference;
34+
private Setting<TimeSpan> _timeout;
3535
private Setting<WriteConcern> _writeConcern;
3636
private Setting<UTF8Encoding> _writeEncoding;
3737

@@ -121,6 +121,20 @@ public IBsonSerializerRegistry SerializerRegistry
121121
get { return BsonSerializer.SerializerRegistry; }
122122
}
123123

124+
/// <summary>
125+
/// Gets or sets the per-operation timeout
126+
/// </summary>
127+
// TODO: CSOT: Make it public when CSOT will be ready for GA release
128+
internal TimeSpan Timeout
129+
{
130+
get { return _timeout.Value; }
131+
set
132+
{
133+
if (_isFrozen) { throw new InvalidOperationException("MongoCollectionSettings is frozen."); }
134+
_timeout.Value = Ensure.IsInfiniteOrGreaterThanZero(value, nameof(Timeout));
135+
}
136+
}
137+
124138
/// <summary>
125139
/// Gets or sets the WriteConcern to use.
126140
/// </summary>
@@ -163,6 +177,7 @@ public virtual MongoCollectionSettings Clone()
163177
clone._readConcern = _readConcern.Clone();
164178
clone._readEncoding = _readEncoding.Clone();
165179
clone._readPreference = _readPreference.Clone();
180+
clone._timeout = _timeout.Clone();
166181
clone._writeConcern = _writeConcern.Clone();
167182
clone._writeEncoding = _writeEncoding.Clone();
168183
return clone;
@@ -193,6 +208,7 @@ public override bool Equals(object obj)
193208
object.Equals(_readConcern.Value, rhs._readConcern.Value) &&
194209
object.Equals(_readEncoding, rhs._readEncoding) &&
195210
_readPreference.Value == rhs._readPreference.Value &&
211+
_timeout.Value == rhs._timeout.Value &&
196212
_writeConcern.Value == rhs._writeConcern.Value &&
197213
object.Equals(_writeEncoding, rhs._writeEncoding);
198214
}
@@ -247,6 +263,7 @@ public override int GetHashCode()
247263
hash = 37 * hash + ((_readConcern.Value == null) ? 0 : _readConcern.Value.GetHashCode());
248264
hash = 37 * hash + ((_readEncoding.Value == null) ? 0 : _readEncoding.Value.GetHashCode());
249265
hash = 37 * hash + ((_readPreference.Value == null) ? 0 : _readPreference.Value.GetHashCode());
266+
hash = 37 * hash + _timeout.Value.GetHashCode();
250267
hash = 37 * hash + ((_writeConcern.Value == null) ? 0 : _writeConcern.Value.GetHashCode());
251268
hash = 37 * hash + ((_writeEncoding.Value == null) ? 0 : _writeEncoding.Value.GetHashCode());
252269
return hash;
@@ -271,6 +288,10 @@ public override string ToString()
271288
parts.Add(string.Format("ReadEncoding={0}", (_readEncoding.Value == null) ? "null" : "UTF8Encoding"));
272289
}
273290
parts.Add(string.Format("ReadPreference={0}", _readPreference));
291+
if (_timeout.HasBeenSet)
292+
{
293+
parts.Add(string.Format("Timeout={0}", _timeout));
294+
}
274295
parts.Add(string.Format("WriteConcern={0}", _writeConcern));
275296
if (_writeEncoding.HasBeenSet)
276297
{
@@ -298,6 +319,10 @@ internal void ApplyDefaultValues(MongoDatabaseSettings databaseSettings)
298319
{
299320
ReadPreference = databaseSettings.ReadPreference;
300321
}
322+
if (!_timeout.HasBeenSet)
323+
{
324+
Timeout = databaseSettings.Timeout;
325+
}
301326
if (!_writeConcern.HasBeenSet)
302327
{
303328
WriteConcern = databaseSettings.WriteConcern;

0 commit comments

Comments
 (0)