Skip to content

Commit 636e485

Browse files
CSHARP-2628: Fix issue with creating a not required connection in RetryableReads.
1 parent ed138b0 commit 636e485

File tree

3 files changed

+50
-9
lines changed

3 files changed

+50
-9
lines changed

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

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

16-
using System;
1716
using System.Threading;
1817
using System.Threading.Tasks;
1918
using MongoDB.Bson;
2019
using MongoDB.Bson.IO;
2120
using MongoDB.Bson.Serialization;
2221
using MongoDB.Driver.Core.Bindings;
2322
using MongoDB.Driver.Core.Misc;
24-
using MongoDB.Driver.Core.Servers;
2523
using MongoDB.Driver.Core.WireProtocol;
2624
using MongoDB.Driver.Core.WireProtocol.Messages.Encoders;
2725

@@ -144,7 +142,17 @@ public IBsonSerializer<TCommandResult> ResultSerializer
144142
}
145143

146144
// methods
147-
private TCommandResult ExecuteProtocol(IChannelHandle channel, ICoreSessionHandle session, ReadPreference readPreference, CancellationToken cancellationToken)
145+
/// <summary>
146+
/// Executes the protocol.
147+
/// </summary>
148+
/// <param name="channel">The channel.</param>
149+
/// <param name="session">The session.</param>
150+
/// <param name="readPreference">The read preference.</param>
151+
/// <param name="cancellationToken">The cancellation token.</param>
152+
/// <returns>
153+
/// A Task whose result is the command result.
154+
/// </returns>
155+
protected TCommandResult ExecuteProtocol(IChannelHandle channel, ICoreSessionHandle session, ReadPreference readPreference, CancellationToken cancellationToken)
148156
{
149157
var additionalOptions = GetEffectiveAdditionalOptions();
150158

@@ -185,7 +193,17 @@ protected TCommandResult ExecuteProtocol(
185193
}
186194
}
187195

188-
private Task<TCommandResult> ExecuteProtocolAsync(IChannelHandle channel, ICoreSessionHandle session, ReadPreference readPreference, CancellationToken cancellationToken)
196+
/// <summary>
197+
/// Executes the protocol.
198+
/// </summary>
199+
/// <param name="channel">The channel.</param>
200+
/// <param name="session">The session.</param>
201+
/// <param name="readPreference">The read preference.</param>
202+
/// <param name="cancellationToken">The cancellation token.</param>
203+
/// <returns>
204+
/// A Task whose result is the command result.
205+
/// </returns>
206+
protected Task<TCommandResult> ExecuteProtocolAsync(IChannelHandle channel, ICoreSessionHandle session, ReadPreference readPreference, CancellationToken cancellationToken)
189207
{
190208
var additionalOptions = GetEffectiveAdditionalOptions();
191209

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

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

16-
using System;
1716
using System.Threading;
1817
using System.Threading.Tasks;
1918
using MongoDB.Bson;
@@ -51,7 +50,7 @@ public ReadCommandOperation(
5150
{
5251
}
5352

54-
// public properties
53+
// public properties
5554
/// <summary>
5655
/// Gets or sets a value indicating whether to retry.
5756
/// </summary>
@@ -62,7 +61,7 @@ public bool RetryRequested
6261
set => _retryRequested = value;
6362
}
6463

65-
// public methods
64+
// public methods
6665
/// <inheritdoc/>
6766
public TCommandResult Execute(IReadBinding binding, CancellationToken cancellationToken)
6867
{
@@ -110,13 +109,13 @@ public async Task<TCommandResult> ExecuteAsync(RetryableReadContext context, Can
110109
/// <inheritdoc/>
111110
public TCommandResult ExecuteAttempt(RetryableReadContext context, int attempt, long? transactionNumber, CancellationToken cancellationToken)
112111
{
113-
return ExecuteProtocol(context.ChannelSource, context.Binding.Session, context.Binding.ReadPreference, cancellationToken);
112+
return ExecuteProtocol(context.Channel, context.Binding.Session, context.Binding.ReadPreference, cancellationToken);
114113
}
115114

116115
/// <inheritdoc/>
117116
public Task<TCommandResult> ExecuteAttemptAsync(RetryableReadContext context, int attempt, long? transactionNumber, CancellationToken cancellationToken)
118117
{
119-
return ExecuteProtocolAsync(context.ChannelSource, context.Binding.Session, context.Binding.ReadPreference, cancellationToken);
118+
return ExecuteProtocolAsync(context.Channel, context.Binding.Session, context.Binding.ReadPreference, cancellationToken);
120119
}
121120
}
122121
}

tests/MongoDB.Driver.Core.Tests/Core/Operations/ReadCommandOperationTests.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,30 @@ public void Execute_should_call_channel_Command_with_wrapped_command_when_readPr
312312
}
313313
}
314314

315+
[Theory]
316+
[ParameterAttributeData]
317+
public void Execute_should_call_GetChannel_only_once([Values(false, true)] bool async)
318+
{
319+
var subject = CreateSubject<BsonDocument>();
320+
var readPreference = ReadPreference.Primary;
321+
var serverDescription = CreateServerDescription(ServerType.Standalone);
322+
var mockChannel = CreateMockChannel();
323+
var mockChannelSource = CreateMockChannelSource(serverDescription, mockChannel.Object);
324+
var binding = CreateMockReadBinding(readPreference, mockChannelSource.Object).Object;
325+
var cancellationToken = new CancellationTokenSource().Token;
326+
327+
if (async)
328+
{
329+
subject.ExecuteAsync(binding, cancellationToken).GetAwaiter().GetResult();
330+
mockChannelSource.Verify(c => c.GetChannelAsync(cancellationToken), Times.Once);
331+
}
332+
else
333+
{
334+
subject.Execute(binding, cancellationToken);
335+
mockChannelSource.Verify(c => c.GetChannel(cancellationToken), Times.Once);
336+
}
337+
}
338+
315339
// private methods
316340
private Mock<IReadBinding> CreateMockReadBinding(ReadPreference readPreference, IChannelSourceHandle channelSource)
317341
{

0 commit comments

Comments
 (0)