Skip to content

Commit 4d24256

Browse files
committed
CSHARP-2221: Add ReadPreference to TransactionOptions and update JSON driven transaction tests
1 parent a6d7f79 commit 4d24256

Some content is hidden

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

49 files changed

+1587
-663
lines changed

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,7 @@ public void StartTransaction(TransactionOptions transactionOptions = null)
294294
}
295295

296296
var transactionNumber = AdvanceTransactionNumber();
297-
var readConcern = transactionOptions?.ReadConcern ?? _options.DefaultTransactionOptions?.ReadConcern ?? ReadConcern.Default;
298-
var writeConcern = transactionOptions?.WriteConcern ?? _options.DefaultTransactionOptions?.WriteConcern ?? new WriteConcern();
299-
var effectiveTransactionOptions = new TransactionOptions(readConcern, writeConcern);
297+
var effectiveTransactionOptions = GetEffectiveTransactionOptions(transactionOptions);
300298
var transaction = new CoreTransaction(transactionNumber, effectiveTransactionOptions);
301299

302300
_currentTransaction = transaction;
@@ -346,6 +344,14 @@ private async Task<TResult> ExecuteEndTransactionOnPrimaryAsync<TResult>(IReadOp
346344
}
347345
}
348346

347+
private TransactionOptions GetEffectiveTransactionOptions(TransactionOptions transactionOptions)
348+
{
349+
var readConcern = transactionOptions?.ReadConcern ?? _options.DefaultTransactionOptions?.ReadConcern ?? ReadConcern.Default;
350+
var readPreference = transactionOptions?.ReadPreference ?? _options.DefaultTransactionOptions?.ReadPreference ?? ReadPreference.Primary;
351+
var writeConcern = transactionOptions?.WriteConcern ?? _options.DefaultTransactionOptions?.WriteConcern ?? new WriteConcern();
352+
return new TransactionOptions(readConcern, readPreference, writeConcern);
353+
}
354+
349355
private WriteConcern GetTransactionWriteConcern()
350356
{
351357
return

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,6 @@ private Type0CommandMessageSection<BsonDocument> CreateType0Section(ConnectionDe
191191
{
192192
var transaction = _session.CurrentTransaction;
193193
extraElements.Add(new BsonElement("txnNumber", transaction.TransactionNumber));
194-
extraElements.Add(new BsonElement("stmtId", transaction.StatementId));
195194
if (transaction.StatementId == 0)
196195
{
197196
extraElements.Add(new BsonElement("startTransaction", true));

src/MongoDB.Driver.Core/TransactionOptions.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,23 @@ public class TransactionOptions
2929
{
3030
// private fields
3131
private readonly ReadConcern _readConcern;
32+
private readonly ReadPreference _readPreference;
3233
private readonly WriteConcern _writeConcern;
3334

3435
// public constructors
3536
/// <summary>
3637
/// Initializes a new instance of the <see cref="TransactionOptions" /> class.
3738
/// </summary>
3839
/// <param name="readConcern">The read concern.</param>
40+
/// <param name="readPreference">The read preference.</param>
3941
/// <param name="writeConcern">The write concern.</param>
4042
public TransactionOptions(
4143
Optional<ReadConcern> readConcern = default(Optional<ReadConcern>),
44+
Optional<ReadPreference> readPreference = default(Optional<ReadPreference>),
4245
Optional<WriteConcern> writeConcern = default(Optional<WriteConcern>))
4346
{
4447
_readConcern = readConcern.WithDefault(null);
48+
_readPreference = readPreference.WithDefault(null);
4549
_writeConcern = writeConcern.WithDefault(null);
4650
}
4751

@@ -54,6 +58,14 @@ public TransactionOptions(
5458
/// </value>
5559
public ReadConcern ReadConcern => _readConcern;
5660

61+
/// <summary>
62+
/// Gets the read preference.
63+
/// </summary>
64+
/// <value>
65+
/// The read preference.
66+
/// </value>
67+
public ReadPreference ReadPreference => _readPreference;
68+
5769
/// <summary>
5870
/// Gets the write concern.
5971
/// </summary>
@@ -67,14 +79,19 @@ public TransactionOptions(
6779
/// Returns a new TransactionOptions with some values changed.
6880
/// </summary>
6981
/// <param name="readConcern">The new read concern.</param>
82+
/// <param name="readPreference">The read preference.</param>
7083
/// <param name="writeConcern">The new write concern.</param>
71-
/// <returns>The new TransactionOptions.</returns>
84+
/// <returns>
85+
/// The new TransactionOptions.
86+
/// </returns>
7287
public TransactionOptions With(
7388
Optional<ReadConcern> readConcern = default(Optional<ReadConcern>),
89+
Optional<ReadPreference> readPreference = default(Optional<ReadPreference>),
7490
Optional<WriteConcern> writeConcern = default(Optional<WriteConcern>))
7591
{
7692
return new TransactionOptions(
7793
readConcern: readConcern.WithDefault(_readConcern),
94+
readPreference: readPreference.WithDefault(_readPreference),
7895
writeConcern: writeConcern.WithDefault(_writeConcern));
7996
}
8097
}

src/MongoDB.Driver/ClientSessionHandle.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,19 @@ public IClientSessionHandle Fork()
130130
/// <inheritdoc />
131131
public void StartTransaction(TransactionOptions transactionOptions = null)
132132
{
133-
_coreSession.StartTransaction(transactionOptions);
133+
var effectiveTransactionOptions = GetEffectiveTransactionOptions(transactionOptions);
134+
_coreSession.StartTransaction(effectiveTransactionOptions);
135+
}
136+
137+
// private methods
138+
private TransactionOptions GetEffectiveTransactionOptions(TransactionOptions transactionOptions)
139+
{
140+
var defaultTransactionOptions = _options?.DefaultTransactionOptions;
141+
var readConcern = transactionOptions?.ReadConcern ?? defaultTransactionOptions?.ReadConcern ?? _client.Settings?.ReadConcern ?? ReadConcern.Default;
142+
var readPreference = transactionOptions?.ReadPreference ?? defaultTransactionOptions?.ReadPreference ?? _client.Settings?.ReadPreference ?? ReadPreference.Primary;
143+
var writeConcern = transactionOptions?.WriteConcern ?? defaultTransactionOptions?.WriteConcern ?? _client.Settings?.WriteConcern ?? new WriteConcern();
144+
145+
return new TransactionOptions(readConcern, readPreference, writeConcern);
134146
}
135147
}
136148
}

src/MongoDB.Driver/MongoClient.cs

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -454,22 +454,6 @@ private IReadWriteBindingHandle CreateReadWriteBinding(IClientSessionHandle sess
454454
}
455455
}
456456

457-
private ClientSessionOptions GetEffectiveClientSessionOptions(ClientSessionOptions options)
458-
{
459-
var autoStartTransaction = options?.AutoStartTransaction ?? false;
460-
var causalConsistency = options?.CausalConsistency;
461-
var readConcern = options?.DefaultTransactionOptions?.ReadConcern ?? _settings.ReadConcern;
462-
var writeConcern = options?.DefaultTransactionOptions?.WriteConcern ?? _settings.WriteConcern;
463-
var defaultTransactionOptions = new TransactionOptions(readConcern, writeConcern);
464-
465-
return new ClientSessionOptions
466-
{
467-
AutoStartTransaction = autoStartTransaction,
468-
CausalConsistency = causalConsistency,
469-
DefaultTransactionOptions = defaultTransactionOptions
470-
};
471-
}
472-
473457
private MessageEncoderSettings GetMessageEncoderSettings()
474458
{
475459
return new MessageEncoderSettings
@@ -502,18 +486,14 @@ private IClientSessionHandle StartImplicitSession(bool areSessionsSupported)
502486

503487
private IClientSessionHandle StartSession(ClientSessionOptions options, bool areSessionsSupported)
504488
{
505-
options = GetEffectiveClientSessionOptions(options);
506-
507-
ICoreSessionHandle coreSession;
508-
if (areSessionsSupported)
509-
{
510-
coreSession = _cluster.StartSession(options.ToCore());
511-
}
512-
else
489+
if (!areSessionsSupported)
513490
{
514491
throw new NotSupportedException("Sessions are not supported by this version of the server.");
515492
}
516493

494+
options = options ?? new ClientSessionOptions();
495+
var coreSession = _cluster.StartSession(options.ToCore());
496+
517497
return new ClientSessionHandle(this, options, coreSession);
518498
}
519499

src/MongoDB.Driver/MongoCollectionImpl.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,8 @@ private IBsonSerializer<TField> GetValueSerializerForDistinct<TField>(RenderedFi
977977

978978
private TResult ExecuteReadOperation<TResult>(IClientSessionHandle session, IReadOperation<TResult> operation, CancellationToken cancellationToken = default(CancellationToken))
979979
{
980-
return ExecuteReadOperation(session, operation, _settings.ReadPreference, cancellationToken);
980+
var readPreference = GetReadPreference(session);
981+
return ExecuteReadOperation(session, operation, readPreference, cancellationToken);
981982
}
982983

983984
private TResult ExecuteReadOperation<TResult>(IClientSessionHandle session, IReadOperation<TResult> operation, ReadPreference readPreference, CancellationToken cancellationToken = default(CancellationToken))
@@ -990,7 +991,8 @@ private IBsonSerializer<TField> GetValueSerializerForDistinct<TField>(RenderedFi
990991

991992
private Task<TResult> ExecuteReadOperationAsync<TResult>(IClientSessionHandle session, IReadOperation<TResult> operation, CancellationToken cancellationToken = default(CancellationToken))
992993
{
993-
return ExecuteReadOperationAsync(session, operation, _settings.ReadPreference, cancellationToken);
994+
var readPreference = GetReadPreference(session);
995+
return ExecuteReadOperationAsync(session, operation, readPreference, cancellationToken);
994996
}
995997

996998
private async Task<TResult> ExecuteReadOperationAsync<TResult>(IClientSessionHandle session, IReadOperation<TResult> operation, ReadPreference readPreference, CancellationToken cancellationToken = default(CancellationToken))
@@ -1017,6 +1019,22 @@ private IBsonSerializer<TField> GetValueSerializerForDistinct<TField>(RenderedFi
10171019
}
10181020
}
10191021

1022+
private ReadPreference GetReadPreference(IClientSession session)
1023+
{
1024+
var readPreference = _settings.ReadPreference;
1025+
1026+
if (session.IsInTransaction)
1027+
{
1028+
var transactionReadPreference = session.WrappedCoreSession.CurrentTransaction.TransactionOptions.ReadPreference;
1029+
if (transactionReadPreference != null)
1030+
{
1031+
readPreference = transactionReadPreference;
1032+
}
1033+
}
1034+
1035+
return readPreference;
1036+
}
1037+
10201038
private IEnumerable<BsonDocument> RenderArrayFilters(IEnumerable<ArrayFilterDefinition> arrayFilters)
10211039
{
10221040
if (arrayFilters == null)

tests/MongoDB.Driver.Core.TestHelpers/JsonDrivenTests/CommandStartedEventAsserter.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ private void AssertCommandAspect(BsonDocument actualCommand, string name, BsonVa
9595
case "autocommit":
9696
case "readConcern":
9797
case "startTransaction":
98-
case "stmtId":
9998
case "txnNumber":
10099
case "writeConcern":
101100
if (actualCommand.Contains(name))

tests/MongoDB.Driver.Core.Tests/TransactionOptionsTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public void WriteConcern_should_return_expected_result(
100100
public void With_with_readConcern_should_return_expected_result(
101101
[Values(false, true)] bool nullReadConcern)
102102
{
103-
var subject = new TransactionOptions(new ReadConcern(), new WriteConcern());
103+
var subject = new TransactionOptions(new ReadConcern(), new ReadPreference(ReadPreferenceMode.Primary), new WriteConcern());
104104
var readConcern = nullReadConcern ? null : new ReadConcern();
105105

106106
var result = subject.With(readConcern: readConcern);
@@ -113,7 +113,7 @@ public void With_with_readConcern_should_return_expected_result(
113113
public void With_with_writeConcern_should_return_expected_result(
114114
[Values(false, true)] bool nullWriteConcern)
115115
{
116-
var subject = new TransactionOptions(new ReadConcern(), new WriteConcern());
116+
var subject = new TransactionOptions(new ReadConcern(), new ReadPreference(ReadPreferenceMode.Primary), new WriteConcern());
117117
var writeConcern = nullWriteConcern ? null : new WriteConcern();
118118

119119
var result = subject.With(writeConcern: writeConcern);
@@ -127,7 +127,7 @@ public void With_with_all_arguments_should_return_expected_result(
127127
[Values(false, true)] bool nullReadConcern,
128128
[Values(false, true)] bool nullWriteConcern)
129129
{
130-
var subject = new TransactionOptions(new ReadConcern(), new WriteConcern());
130+
var subject = new TransactionOptions(new ReadConcern(), new ReadPreference(ReadPreferenceMode.Primary), new WriteConcern());
131131
var readConcern = nullReadConcern ? null : new ReadConcern();
132132
var writeConcern = nullWriteConcern ? null : new WriteConcern();
133133

tests/MongoDB.Driver.Tests/ClientSessionHandleTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ public void StartTransaction_should_call_coreSession()
255255

256256
subject.StartTransaction(transactionOptions);
257257

258-
Mock.Get(subject.WrappedCoreSession).Verify(m => m.StartTransaction(transactionOptions), Times.Once);
258+
Mock.Get(subject.WrappedCoreSession).Verify(m => m.StartTransaction(It.IsAny<TransactionOptions>()), Times.Once);
259259
}
260260

261261
// private methods

tests/MongoDB.Driver.Tests/JsonDrivenTests/JsonDrivenStartTransactionTest.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace MongoDB.Driver.Tests.JsonDrivenTests
2323
public sealed class JsonDrivenStartTransactionTest : JsonDrivenClientTest
2424
{
2525
// private fields
26-
private TransactionOptions _options = new TransactionOptions();
26+
private TransactionOptions _options = null;
2727

2828
// public constructors
2929
public JsonDrivenStartTransactionTest(IMongoClient client, Dictionary<string, IClientSessionHandle> sessionMap)
@@ -59,17 +59,25 @@ protected override void SetArgument(string name, BsonValue value)
5959
// private methods
6060
private void SetOptions(BsonDocument document)
6161
{
62-
JsonDrivenHelper.EnsureAllFieldsAreValid(document, "readConcern", "writeConcern");
62+
JsonDrivenHelper.EnsureAllFieldsAreValid(document, "readConcern", "readPreference", "writeConcern");
6363

64+
var options = new TransactionOptions();
6465
if (document.Contains("readConcern"))
6566
{
66-
_options = _options.With(readConcern: ReadConcern.FromBsonDocument(document["readConcern"].AsBsonDocument));
67+
options = options.With(readConcern: ReadConcern.FromBsonDocument(document["readConcern"].AsBsonDocument));
68+
}
69+
70+
if (document.Contains("readPreference"))
71+
{
72+
options = options.With(readPreference: ReadPreference.FromBsonDocument(document["readPreference"].AsBsonDocument));
6773
}
6874

6975
if (document.Contains("writeConcern"))
7076
{
71-
_options = _options.With(writeConcern: WriteConcern.FromBsonDocument(document["writeConcern"].AsBsonDocument));
77+
options = options.With(writeConcern: WriteConcern.FromBsonDocument(document["writeConcern"].AsBsonDocument));
7278
}
79+
80+
_options = options;
7381
}
7482
}
7583
}

0 commit comments

Comments
 (0)