Skip to content

Commit

Permalink
CSHARP-4827: Don't add RetryableWriteError label on pre 4.4 mongos.
Browse files Browse the repository at this point in the history
  • Loading branch information
rstam committed Feb 20, 2024
1 parent 211d76d commit 830b83a
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 31 deletions.
56 changes: 33 additions & 23 deletions src/MongoDB.Driver.Core/Core/Operations/RetryabilityHelper.cs
Expand Up @@ -16,7 +16,9 @@
using System;
using System.Collections.Generic;
using MongoDB.Bson;
using MongoDB.Driver.Core.Connections;
using MongoDB.Driver.Core.Misc;
using MongoDB.Driver.Core.Servers;

namespace MongoDB.Driver.Core.Operations
{
Expand Down Expand Up @@ -90,9 +92,9 @@ static RetryabilityHelper()
}

// public static methods
public static void AddRetryableWriteErrorLabelIfRequired(MongoException exception, int maxWireVersion)
public static void AddRetryableWriteErrorLabelIfRequired(MongoException exception, ConnectionDescription connectionDescription)
{
if (ShouldRetryableWriteExceptionLabelBeAdded(exception, maxWireVersion))
if (ShouldRetryableWriteExceptionLabelBeAdded(exception, connectionDescription))
{
exception.AddErrorLabel(RetryableWriteErrorLabel);
}
Expand Down Expand Up @@ -172,18 +174,22 @@ private static bool IsNetworkException(Exception exception)
return exception is MongoConnectionException mongoConnectionException && mongoConnectionException.IsNetworkException;
}

private static bool ShouldRetryableWriteExceptionLabelBeAdded(Exception exception, int maxWireVersion)
private static bool ShouldRetryableWriteExceptionLabelBeAdded(Exception exception, ConnectionDescription connectionDescription)
{
if (IsNetworkException(exception))
{
return true;
}

var maxWireVersion = connectionDescription.MaxWireVersion;
if (Feature.ServerReturnsRetryableWriteErrorLabel.IsSupported(maxWireVersion))
{
return false;
}

// on all servers from 4.4 on we would have returned false in the previous if statement
// so from this point on we know we are connected to a pre 4.4 server

if (__retryableWriteExceptions.Contains(exception.GetType()))
{
return true;
Expand All @@ -199,29 +205,33 @@ private static bool ShouldRetryableWriteExceptionLabelBeAdded(Exception exceptio
}
}

var writeConcernException = exception as MongoWriteConcernException;
if (writeConcernException != null)
var serverType = connectionDescription.HelloResult.ServerType;
if (serverType != ServerType.ShardRouter)
{
var writeConcernError = writeConcernException.WriteConcernResult.Response.GetValue("writeConcernError", null)?.AsBsonDocument;
if (writeConcernError != null)
var writeConcernException = exception as MongoWriteConcernException;
if (writeConcernException != null)
{
var code = (ServerErrorCode)writeConcernError.GetValue("code", -1).AsInt32;
switch (code)
var writeConcernError = writeConcernException.WriteConcernResult.Response.GetValue("writeConcernError", null)?.AsBsonDocument;
if (writeConcernError != null)
{
case ServerErrorCode.InterruptedAtShutdown:
case ServerErrorCode.InterruptedDueToReplStateChange:
case ServerErrorCode.LegacyNotPrimary:
case ServerErrorCode.NotWritablePrimary:
case ServerErrorCode.NotPrimaryNoSecondaryOk:
case ServerErrorCode.NotPrimaryOrSecondary:
case ServerErrorCode.PrimarySteppedDown:
case ServerErrorCode.ShutdownInProgress:
case ServerErrorCode.HostNotFound:
case ServerErrorCode.HostUnreachable:
case ServerErrorCode.NetworkTimeout:
case ServerErrorCode.SocketException:
case ServerErrorCode.ExceededTimeLimit:
return true;
var code = (ServerErrorCode)writeConcernError.GetValue("code", -1).AsInt32;
switch (code)
{
case ServerErrorCode.InterruptedAtShutdown:
case ServerErrorCode.InterruptedDueToReplStateChange:
case ServerErrorCode.LegacyNotPrimary:
case ServerErrorCode.NotWritablePrimary:
case ServerErrorCode.NotPrimaryNoSecondaryOk:
case ServerErrorCode.NotPrimaryOrSecondary:
case ServerErrorCode.PrimarySteppedDown:
case ServerErrorCode.ShutdownInProgress:
case ServerErrorCode.HostNotFound:
case ServerErrorCode.HostUnreachable:
case ServerErrorCode.NetworkTimeout:
case ServerErrorCode.SocketException:
case ServerErrorCode.ExceededTimeLimit:
return true;
}
}
}
}
Expand Down
Expand Up @@ -147,7 +147,7 @@ public TCommandResult Execute(IConnection connection, CancellationToken cancella
}
catch (Exception exception)
{
AddErrorLabelIfRequired(exception, connection.Description?.MaxWireVersion);
AddErrorLabelIfRequired(exception, connection.Description);

TransactionHelper.UnpinServerIfNeededOnCommandException(_session, exception);
throw;
Expand Down Expand Up @@ -201,15 +201,15 @@ public async Task<TCommandResult> ExecuteAsync(IConnection connection, Cancellat
}
catch (Exception exception)
{
AddErrorLabelIfRequired(exception, connection.Description?.MaxWireVersion);
AddErrorLabelIfRequired(exception, connection.Description);

TransactionHelper.UnpinServerIfNeededOnCommandException(_session, exception);
throw;
}
}

// private methods
private void AddErrorLabelIfRequired(Exception exception, int? maxWireVersion)
private void AddErrorLabelIfRequired(Exception exception, ConnectionDescription connectionDescription)
{
if (exception is MongoException mongoException)
{
Expand All @@ -218,9 +218,9 @@ private void AddErrorLabelIfRequired(Exception exception, int? maxWireVersion)
mongoException.AddErrorLabel("TransientTransactionError");
}

if (RetryabilityHelper.IsCommandRetryable(_command) && maxWireVersion.HasValue)
if (RetryabilityHelper.IsCommandRetryable(_command) && connectionDescription != null)
{
RetryabilityHelper.AddRetryableWriteErrorLabelIfRequired(mongoException, maxWireVersion.Value);
RetryabilityHelper.AddRetryableWriteErrorLabelIfRequired(mongoException, connectionDescription);
}
}
}
Expand Down
Expand Up @@ -21,6 +21,7 @@
using MongoDB.Driver.Core.Misc;
using MongoDB.Driver.Core.TestHelpers;
using Xunit;
using MongoDB.Driver.Core.Connections;

namespace MongoDB.Driver.Core.Operations
{
Expand All @@ -45,8 +46,10 @@ public class RetryabilityHelperTests
public void AddRetryableWriteErrorLabelIfRequired_should_add_RetryableWriteError_for_MongoWriteConcernException_when_required(int errorCode, bool shouldAddErrorLabel)
{
var exception = CoreExceptionHelper.CreateMongoWriteConcernException(BsonDocument.Parse($"{{ writeConcernError : {{ code : {errorCode} }} }}"));
var maxWireVersion = Feature.ServerReturnsRetryableWriteErrorLabel.LastNotSupportedWireVersion;
var connectionDescription = OperationTestHelper.CreateConnectionDescription(maxWireVersion);

RetryabilityHelper.AddRetryableWriteErrorLabelIfRequired(exception, Feature.ServerReturnsRetryableWriteErrorLabel.LastNotSupportedWireVersion);
RetryabilityHelper.AddRetryableWriteErrorLabelIfRequired(exception, connectionDescription);

var hasRetryableWriteErrorLabel = exception.HasErrorLabel("RetryableWriteError");
hasRetryableWriteErrorLabel.Should().Be(shouldAddErrorLabel);
Expand All @@ -59,8 +62,9 @@ public void AddRetryableWriteErrorLabelIfRequired_should_add_RetryableWriteError
var exception = (MongoException)CoreExceptionHelper.CreateException(typeof(MongoConnectionException));
var feature = Feature.ServerReturnsRetryableWriteErrorLabel;
var wireVersion = serverReturnsRetryableWriteErrorLabel ? feature.FirstSupportedWireVersion : feature.LastNotSupportedWireVersion;
var connectionDescription = OperationTestHelper.CreateConnectionDescription(wireVersion);

RetryabilityHelper.AddRetryableWriteErrorLabelIfRequired(exception, wireVersion);
RetryabilityHelper.AddRetryableWriteErrorLabelIfRequired(exception, connectionDescription);

var hasRetryableWriteErrorLabel = exception.HasErrorLabel("RetryableWriteError");
hasRetryableWriteErrorLabel.Should().BeTrue();
Expand Down Expand Up @@ -89,8 +93,10 @@ public void AddRetryableWriteErrorLabelIfRequired_should_add_RetryableWriteError
{
exception = CoreExceptionHelper.CreateMongoCommandException((int)exceptionDescription);
}
var maxWireVersion = Feature.ServerReturnsRetryableWriteErrorLabel.LastNotSupportedWireVersion;
var connectionDescription = OperationTestHelper.CreateConnectionDescription(maxWireVersion);

RetryabilityHelper.AddRetryableWriteErrorLabelIfRequired(exception, Feature.ServerReturnsRetryableWriteErrorLabel.LastNotSupportedWireVersion);
RetryabilityHelper.AddRetryableWriteErrorLabelIfRequired(exception, connectionDescription);

var hasRetryableWriteErrorLabel = exception.HasErrorLabel("RetryableWriteError");
hasRetryableWriteErrorLabel.Should().Be(shouldAddErrorLabel);
Expand Down

0 comments on commit 830b83a

Please sign in to comment.