Skip to content

Commit 726ab47

Browse files
authored
CSHARP-4504: Do not perform server selection to determine sessions support (#1095)
1 parent b8db3d4 commit 726ab47

File tree

7 files changed

+136
-235
lines changed

7 files changed

+136
-235
lines changed

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -521,11 +521,6 @@ private void EnsureTransactionsAreSupported()
521521

522522
var connectedDataBearingServers = _cluster.Description.Servers.Where(s => s.State == ServerState.Connected && s.IsDataBearing).ToList();
523523

524-
if (connectedDataBearingServers.Count == 0)
525-
{
526-
throw new NotSupportedException("StartTransaction cannot determine if transactions are supported because there are no connected servers.");
527-
}
528-
529524
foreach (var connectedDataBearingServer in connectedDataBearingServers)
530525
{
531526
var serverType = connectedDataBearingServer.Type;

src/MongoDB.Driver.Core/Core/WireProtocol/CommandUsingCommandMessageWireProtocol.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,20 @@ private Type0CommandMessageSection<BsonDocument> CreateType0Section(ConnectionDe
334334

335335
if (_session.Id != null)
336336
{
337-
if (IsSessionAcknowledged())
337+
var areSessionsSupported = connectionDescription.HelloResult.LogicalSessionTimeout.HasValue;
338+
339+
if (!areSessionsSupported)
340+
{
341+
if (_session.IsImplicit)
342+
{
343+
// do not set sessionId if session is implicit and sessions are not supported
344+
}
345+
else
346+
{
347+
throw new MongoClientException("Sessions are not supported.");
348+
}
349+
}
350+
else if (IsSessionAcknowledged())
338351
{
339352
AddIfNotAlreadyAdded("lsid", _session.Id);
340353
}
@@ -351,7 +364,6 @@ private Type0CommandMessageSection<BsonDocument> CreateType0Section(ConnectionDe
351364
}
352365
}
353366

354-
355367
var snapshotReadConcernDocument = ReadConcernHelper.GetReadConcernForSnapshotSesssion(_session, connectionDescription);
356368
if (snapshotReadConcernDocument != null)
357369
{

src/MongoDB.Driver/Encryption/MongocryptdFactory.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using System.Linq;
2222
using System.Reflection;
2323
using MongoDB.Driver.Core;
24+
using MongoDB.Driver.Core.Events;
2425
using MongoDB.Driver.Core.Misc;
2526

2627
namespace MongoDB.Driver.Encryption
@@ -74,18 +75,26 @@ public static string ExtractCryptSharedLibPath(IReadOnlyDictionary<string, objec
7475
internal class MongocryptdFactory
7576
{
7677
private readonly bool? _bypassQueryAnalysis;
78+
private readonly IEventSubscriber _eventSubscriber;
7779
private readonly IReadOnlyDictionary<string, object> _extraOptions;
7880

79-
public MongocryptdFactory(IReadOnlyDictionary<string, object> extraOptions, bool? bypassQueryAnalysis)
81+
public MongocryptdFactory(IReadOnlyDictionary<string, object> extraOptions, bool? bypassQueryAnalysis, IEventSubscriber eventSubscriber = null)
8082
{
8183
_bypassQueryAnalysis = bypassQueryAnalysis;
84+
_eventSubscriber = eventSubscriber;
8285
_extraOptions = extraOptions ?? new Dictionary<string, object>();
8386
}
8487

8588
// public methods
8689
public IMongoClient CreateMongocryptdClient()
8790
{
8891
var clientSettings = CreateMongocryptdClientSettings();
92+
93+
if (_eventSubscriber != null)
94+
{
95+
clientSettings.ClusterConfigurator = c => c.Subscribe(_eventSubscriber);
96+
}
97+
8998
return new MongoClient(clientSettings);
9099
}
91100

src/MongoDB.Driver/MongoClient.cs

Lines changed: 9 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
*/
1515

1616
using System;
17-
using System.Collections.Generic;
1817
using System.Linq;
1918
using System.Threading;
2019
using System.Threading.Tasks;
@@ -24,10 +23,8 @@
2423
using MongoDB.Bson.Serialization.Serializers;
2524
using MongoDB.Driver.Core.Bindings;
2625
using MongoDB.Driver.Core.Clusters;
27-
using MongoDB.Driver.Core.Clusters.ServerSelectors;
2826
using MongoDB.Driver.Core.Misc;
2927
using MongoDB.Driver.Core.Operations;
30-
using MongoDB.Driver.Core.Servers;
3128
using MongoDB.Driver.Core.WireProtocol.Messages.Encoders;
3229
using MongoDB.Driver.Encryption;
3330
using MongoDB.Driver.Linq;
@@ -37,23 +34,6 @@ namespace MongoDB.Driver
3734
/// <inheritdoc/>
3835
public class MongoClient : MongoClientBase
3936
{
40-
#region static
41-
// private static methods
42-
private static IEnumerable<ServerDescription> SelectServersThatDetermineWhetherSessionsAreSupported(ClusterDescription cluster, IEnumerable<ServerDescription> servers)
43-
{
44-
var connectedServers = servers.Where(s => s.State == ServerState.Connected);
45-
46-
if (cluster.IsDirectConnection)
47-
{
48-
return connectedServers;
49-
}
50-
else
51-
{
52-
return connectedServers.Where(s => s.IsDataBearing);
53-
}
54-
}
55-
#endregion
56-
5737
// private fields
5838
private readonly ICluster _cluster;
5939
private readonly AutoEncryptionLibMongoCryptController _libMongoCryptController;
@@ -146,9 +126,6 @@ internal void ConfigureAutoEncryptionMessageEncoderSettings(MessageEncoderSettin
146126
}
147127
}
148128

149-
// private static methods
150-
151-
152129
// public methods
153130
/// <inheritdoc/>
154131
public sealed override void DropDatabase(string name, CancellationToken cancellationToken = default(CancellationToken))
@@ -346,32 +323,28 @@ public sealed override Task<IAsyncCursor<BsonDocument>> ListDatabasesAsync(
346323
/// <returns>A session.</returns>
347324
internal IClientSessionHandle StartImplicitSession(CancellationToken cancellationToken)
348325
{
349-
var areSessionsSupported = AreSessionsSupported(cancellationToken);
350-
return StartImplicitSession(areSessionsSupported);
326+
return StartImplicitSession();
351327
}
352328

353329
/// <summary>
354330
/// Starts an implicit session.
355331
/// </summary>
356332
/// <returns>A Task whose result is a session.</returns>
357-
internal async Task<IClientSessionHandle> StartImplicitSessionAsync(CancellationToken cancellationToken)
333+
internal Task<IClientSessionHandle> StartImplicitSessionAsync(CancellationToken cancellationToken)
358334
{
359-
var areSessionsSupported = await AreSessionsSupportedAsync(cancellationToken).ConfigureAwait(false);
360-
return StartImplicitSession(areSessionsSupported);
335+
return Task.FromResult(StartImplicitSession());
361336
}
362337

363338
/// <inheritdoc/>
364339
public sealed override IClientSessionHandle StartSession(ClientSessionOptions options = null, CancellationToken cancellationToken = default(CancellationToken))
365340
{
366-
var areSessionsSupported = AreSessionsSupported(cancellationToken);
367-
return StartSession(options, areSessionsSupported);
341+
return StartSession(options);
368342
}
369343

370344
/// <inheritdoc/>
371-
public sealed override async Task<IClientSessionHandle> StartSessionAsync(ClientSessionOptions options = null, CancellationToken cancellationToken = default(CancellationToken))
345+
public sealed override Task<IClientSessionHandle> StartSessionAsync(ClientSessionOptions options = null, CancellationToken cancellationToken = default(CancellationToken))
372346
{
373-
var areSessionsSupported = await AreSessionsSupportedAsync(cancellationToken).ConfigureAwait(false);
374-
return StartSession(options, areSessionsSupported);
347+
return Task.FromResult(StartSession(options));
375348
}
376349

377350
/// <inheritdoc/>
@@ -446,52 +419,6 @@ public override IMongoClient WithWriteConcern(WriteConcern writeConcern)
446419
}
447420

448421
// private methods
449-
private bool AreSessionsSupported(CancellationToken cancellationToken)
450-
{
451-
return AreSessionsSupported(_cluster.Description) ?? AreSessionsSupportedAfterServerSelection(cancellationToken);
452-
}
453-
454-
private async Task<bool> AreSessionsSupportedAsync(CancellationToken cancellationToken)
455-
{
456-
return AreSessionsSupported(_cluster.Description) ?? await AreSessionsSupportedAfterServerSelectionAsync(cancellationToken).ConfigureAwait(false);
457-
}
458-
459-
private bool? AreSessionsSupported(ClusterDescription clusterDescription)
460-
{
461-
if (clusterDescription.LogicalSessionTimeout.HasValue || clusterDescription.Type == ClusterType.LoadBalanced)
462-
{
463-
return true;
464-
}
465-
else
466-
{
467-
var selectedServers = SelectServersThatDetermineWhetherSessionsAreSupported(clusterDescription, clusterDescription.Servers).ToList();
468-
if (selectedServers.Count == 0)
469-
{
470-
return null;
471-
}
472-
else
473-
{
474-
return false;
475-
}
476-
}
477-
}
478-
479-
private bool AreSessionsSupportedAfterServerSelection(CancellationToken cancellationToken)
480-
{
481-
var selector = new AreSessionsSupportedServerSelector();
482-
var selectedServer = _cluster.SelectServer(selector, cancellationToken);
483-
var clusterDescription = selector.ClusterDescription ?? _cluster.Description; // LB cluster doesn't use server selector, so clusterDescription is null for this case
484-
return AreSessionsSupported(clusterDescription) ?? false;
485-
}
486-
487-
private async Task<bool> AreSessionsSupportedAfterServerSelectionAsync(CancellationToken cancellationToken)
488-
{
489-
var selector = new AreSessionsSupportedServerSelector();
490-
var selectedServer = await _cluster.SelectServerAsync(selector, cancellationToken).ConfigureAwait(false);
491-
var clusterDescription = selector.ClusterDescription ?? _cluster.Description; // LB cluster doesn't use server selector, so clusterDescription is null for this case
492-
return AreSessionsSupported(clusterDescription) ?? false;
493-
}
494-
495422
private IAsyncCursor<string> CreateDatabaseNamesCursor(IAsyncCursor<BsonDocument> cursor)
496423
{
497424
return new BatchTransformingAsyncCursor<BsonDocument, string>(
@@ -608,15 +535,15 @@ private MessageEncoderSettings GetMessageEncoderSettings()
608535
return messageEncoderSettings;
609536
}
610537

611-
private IClientSessionHandle StartImplicitSession(bool areSessionsSupported)
538+
private IClientSessionHandle StartImplicitSession()
612539
{
613540
var options = new ClientSessionOptions { CausalConsistency = false, Snapshot = false };
614541

615542
ICoreSessionHandle coreSession;
616543
#pragma warning disable 618
617544
var areMultipleUsersAuthenticated = _settings.Credentials.Count() > 1;
618545
#pragma warning restore
619-
if (areSessionsSupported && !areMultipleUsersAuthenticated)
546+
if (!areMultipleUsersAuthenticated)
620547
{
621548
coreSession = _cluster.StartSession(options.ToCore(isImplicit: true));
622549
}
@@ -628,13 +555,8 @@ private IClientSessionHandle StartImplicitSession(bool areSessionsSupported)
628555
return new ClientSessionHandle(this, options, coreSession);
629556
}
630557

631-
private IClientSessionHandle StartSession(ClientSessionOptions options, bool areSessionsSupported)
558+
private IClientSessionHandle StartSession(ClientSessionOptions options)
632559
{
633-
if (!areSessionsSupported)
634-
{
635-
throw new NotSupportedException("Sessions are not supported by this version of the server.");
636-
}
637-
638560
if (options != null && options.Snapshot && options.CausalConsistency == true)
639561
{
640562
throw new NotSupportedException("Combining both causal consistency and snapshot options is not supported.");
@@ -677,17 +599,5 @@ private async Task<TResult> UsingImplicitSessionAsync<TResult>(Func<IClientSessi
677599
return await funcAsync(session).ConfigureAwait(false);
678600
}
679601
}
680-
681-
// nested types
682-
private class AreSessionsSupportedServerSelector : IServerSelector
683-
{
684-
public ClusterDescription ClusterDescription;
685-
686-
public IEnumerable<ServerDescription> SelectServers(ClusterDescription cluster, IEnumerable<ServerDescription> servers)
687-
{
688-
ClusterDescription = cluster;
689-
return SelectServersThatDetermineWhetherSessionsAreSupported(cluster, servers);
690-
}
691-
}
692602
}
693603
}

tests/MongoDB.Driver.Core.Tests/Core/Bindings/CoreSessionTests.cs

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,17 @@
1414
*/
1515

1616
using System;
17-
using System.Collections;
1817
using System.Collections.Generic;
1918
using System.Linq;
2019
using System.Net;
2120
using FluentAssertions;
2221
using MongoDB.Bson;
2322
using MongoDB.Bson.TestHelpers;
24-
using MongoDB.TestHelpers.XunitExtensions;
2523
using MongoDB.Driver.Core.Clusters;
2624
using MongoDB.Driver.Core.Misc;
2725
using MongoDB.Driver.Core.Servers;
2826
using MongoDB.Driver.Core.TestHelpers.XunitExtensions;
27+
using MongoDB.TestHelpers.XunitExtensions;
2928
using Moq;
3029
using Xunit;
3130

@@ -250,20 +249,6 @@ public void WasUsed_should_call_serverSession()
250249
Mock.Get(subject.ServerSession).Verify(m => m.WasUsed(), Times.Once);
251250
}
252251

253-
[Theory]
254-
[ParameterAttributeData]
255-
public void EnsureTransactionsAreSupported_should_throw_when_there_are_no_connected_servers(
256-
[Values(0, 1, 2, 3)] int numberOfDisconnectedServers)
257-
{
258-
var clusterDescription = CreateClusterDescriptionWithDisconnectedServers(numberOfDisconnectedServers);
259-
var subject = CreateSubject(clusterDescription);
260-
261-
var exception = Record.Exception(() => subject.EnsureTransactionsAreSupported());
262-
263-
var e = exception.Should().BeOfType<NotSupportedException>().Subject;
264-
e.Message.Should().Be("StartTransaction cannot determine if transactions are supported because there are no connected servers.");
265-
}
266-
267252
[Theory]
268253
[ParameterAttributeData]
269254
public void EnsureTransactionsAreSupported_should_not_throw_when_there_are_no_connected_servers_with_LB(
@@ -273,7 +258,7 @@ public void EnsureTransactionsAreSupported_should_not_throw_when_there_are_no_co
273258
clusterDescription = clusterDescription.WithType(ClusterType.LoadBalanced);
274259
var subject = CreateSubject(clusterDescription);
275260

276-
subject.EnsureTransactionsAreSupported();
261+
subject.EnsureTransactionsAreSupported();
277262
}
278263

279264
// EnsureTransactionsAreSupported scenario codes
@@ -325,7 +310,7 @@ public void EnsureTransactionsAreSupported_should_ignore_disconnected_servers(st
325310
[InlineData("CA,DU")]
326311
[InlineData("CA,CA")]
327312
[InlineData("CA,DL")]
328-
public void EnsureTransactionsAreSupported_should_throw_when_there_are_no_connected_data_bearing_servers(string scenarios)
313+
public void EnsureTransactionsAreSupported_should_ignore_no_data_bearing_servers(string scenarios)
329314
{
330315
var clusterId = new ClusterId(1);
331316
var servers =
@@ -342,10 +327,7 @@ public void EnsureTransactionsAreSupported_should_throw_when_there_are_no_connec
342327
var cluster = CreateClusterDescription(clusterId, servers: servers);
343328
var subject = CreateSubject(cluster);
344329

345-
var exception = Record.Exception(() => subject.EnsureTransactionsAreSupported());
346-
347-
var e = exception.Should().BeOfType<NotSupportedException>().Subject;
348-
e.Message.Should().Be("StartTransaction cannot determine if transactions are supported because there are no connected servers.");
330+
subject.EnsureTransactionsAreSupported();
349331
}
350332

351333
[Theory]

0 commit comments

Comments
 (0)