Skip to content

Commit 39b3572

Browse files
committed
CSHARP-2229: Changes to reflect latest spec changes.
1 parent d250d9f commit 39b3572

File tree

5 files changed

+120
-42
lines changed

5 files changed

+120
-42
lines changed

src/MongoDB.Driver.Core/Core/Misc/ExceptionMapper.cs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,17 +118,37 @@ public static Exception Map(ConnectionId connectionId, WriteConcernResult writeC
118118
/// <returns>The exception, or null if no exception necessary.</returns>
119119
public static Exception MapNotPrimaryOrNodeIsRecovering(ConnectionId connectionId, BsonDocument response, string errorMessageFieldName)
120120
{
121+
BsonValue codeBsonValue;
122+
if (response.TryGetValue("code", out codeBsonValue) && codeBsonValue.IsNumeric)
123+
{
124+
var code = (ServerErrorCode)codeBsonValue.ToInt32();
125+
switch (code)
126+
{
127+
case ServerErrorCode.NotMaster:
128+
case ServerErrorCode.NotMasterNoSlaveOk:
129+
return new MongoNotPrimaryException(connectionId, response);
130+
131+
case ServerErrorCode.InterruptedAtShutdown:
132+
case ServerErrorCode.InterruptedDueToReplStateChange:
133+
case ServerErrorCode.NotMasterOrSecondary:
134+
case ServerErrorCode.PrimarySteppedDown:
135+
case ServerErrorCode.ShutdownInProgress:
136+
return new MongoNodeIsRecoveringException(connectionId, response);
137+
}
138+
}
139+
121140
BsonValue errorMessageBsonValue;
122141
if (response.TryGetValue(errorMessageFieldName, out errorMessageBsonValue) && errorMessageBsonValue.IsString)
123142
{
124143
var errorMessage = errorMessageBsonValue.ToString();
125-
if (errorMessage.StartsWith("not master", StringComparison.OrdinalIgnoreCase))
144+
if (errorMessage.IndexOf("node is recovering", StringComparison.OrdinalIgnoreCase) != -1 ||
145+
errorMessage.IndexOf("not master or secondary", StringComparison.OrdinalIgnoreCase) != -1)
126146
{
127-
return new MongoNotPrimaryException(connectionId, response);
147+
return new MongoNodeIsRecoveringException(connectionId, response);
128148
}
129-
if (errorMessage.StartsWith("node is recovering", StringComparison.OrdinalIgnoreCase))
149+
else if (errorMessage.IndexOf("not master", StringComparison.OrdinalIgnoreCase) != -1)
130150
{
131-
return new MongoNodeIsRecoveringException(connectionId, response);
151+
return new MongoNotPrimaryException(connectionId, response);
132152
}
133153
}
134154

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

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ namespace MongoDB.Driver.Core.Operations
2121
internal static class RetryabilityHelper
2222
{
2323
// private static fields
24+
private static readonly HashSet<ServerErrorCode> __notResumableChangeStreamErrorCodes;
2425
private static readonly HashSet<Type> __resumableChangeStreamExceptions;
2526
private static readonly HashSet<ServerErrorCode> __resumableChangeStreamErrorCodes;
2627
private static readonly HashSet<Type> __retryableWriteExceptions;
@@ -32,7 +33,8 @@ static RetryabilityHelper()
3233
var resumableAndRetryableExceptions = new HashSet<Type>()
3334
{
3435
typeof(MongoConnectionException),
35-
typeof(MongoNotPrimaryException)
36+
typeof(MongoNotPrimaryException),
37+
typeof(MongoNodeIsRecoveringException)
3638
};
3739

3840
__resumableChangeStreamExceptions = new HashSet<Type>(resumableAndRetryableExceptions)
@@ -42,56 +44,62 @@ static RetryabilityHelper()
4244

4345
__retryableWriteExceptions = new HashSet<Type>(resumableAndRetryableExceptions)
4446
{
45-
typeof(MongoNodeIsRecoveringException)
4647
};
4748

4849
var resumableAndRetryableErrorCodes = new HashSet<ServerErrorCode>
4950
{
5051
ServerErrorCode.HostNotFound,
5152
ServerErrorCode.HostUnreachable,
52-
ServerErrorCode.InterruptedAtShutdown,
53-
ServerErrorCode.InterruptedDueToReplStateChange,
5453
ServerErrorCode.NetworkTimeout,
55-
ServerErrorCode.NotMaster,
56-
ServerErrorCode.NotMasterNoSlaveOk,
57-
ServerErrorCode.NotMasterOrSecondary,
58-
ServerErrorCode.PrimarySteppedDown,
59-
ServerErrorCode.ShutdownInProgress,
6054
ServerErrorCode.SocketException
6155
};
6256

6357
__resumableChangeStreamErrorCodes = new HashSet<ServerErrorCode>(resumableAndRetryableErrorCodes)
6458
{
59+
ServerErrorCode.ElectionInProgress,
60+
ServerErrorCode.ExceededTimeLimit,
61+
ServerErrorCode.RetryChangeStream,
6562
};
6663

6764
__retryableWriteErrorCodes = new HashSet<ServerErrorCode>(resumableAndRetryableErrorCodes)
6865
{
6966
ServerErrorCode.WriteConcernFailed
7067
};
68+
69+
__notResumableChangeStreamErrorCodes = new HashSet<ServerErrorCode>()
70+
{
71+
ServerErrorCode.CappedPositionLost,
72+
ServerErrorCode.CursorKilled,
73+
ServerErrorCode.Interrupted
74+
};
7175
}
7276

7377
// public static methods
7478
public static bool IsResumableChangeStreamException(Exception exception)
7579
{
76-
return IsMatch(exception, __resumableChangeStreamExceptions, __resumableChangeStreamErrorCodes);
80+
var commandException = exception as MongoCommandException;
81+
if (commandException != null)
82+
{
83+
var code = (ServerErrorCode)commandException.Code;
84+
return __resumableChangeStreamErrorCodes.Contains(code) || !__notResumableChangeStreamErrorCodes.Contains(code);
85+
}
86+
else
87+
{
88+
return __resumableChangeStreamExceptions.Contains(exception.GetType());
89+
}
7790
}
7891

7992
public static bool IsRetryableWriteException(Exception exception)
80-
{
81-
return IsMatch(exception, __retryableWriteExceptions, __retryableWriteErrorCodes);
82-
}
83-
84-
// private static methods
85-
private static bool IsMatch(Exception exception, HashSet<Type> matchingExceptions, HashSet<ServerErrorCode> matchingErrorCodes)
8693
{
8794
var commandException = exception as MongoCommandException;
8895
if (commandException != null)
8996
{
90-
return matchingErrorCodes.Contains((ServerErrorCode)commandException.Code);
97+
var code = (ServerErrorCode)commandException.Code;
98+
return __retryableWriteErrorCodes.Contains(code);
9199
}
92100
else
93101
{
94-
return matchingExceptions.Contains(exception.GetType());
102+
return __retryableWriteExceptions.Contains(exception.GetType());
95103
}
96104
}
97105
}

src/MongoDB.Driver.Core/ServerErrorCode.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,21 @@ namespace MongoDB.Driver
1818
internal enum ServerErrorCode
1919
{
2020
// this is not a complete list, more will be added as needed
21+
CappedPositionLost = 136,
22+
CursorKilled = 237,
23+
ElectionInProgress = 216,
24+
ExceededTimeLimit = 50,
2125
HostNotFound = 7,
2226
HostUnreachable = 6,
27+
Interrupted = 11601,
2328
InterruptedAtShutdown = 11600,
2429
InterruptedDueToReplStateChange = 11602,
2530
NetworkTimeout = 89,
2631
NotMaster = 10107,
2732
NotMasterNoSlaveOk = 13435,
2833
NotMasterOrSecondary = 13436,
2934
PrimarySteppedDown = 189,
35+
RetryChangeStream = 234,
3036
ShutdownInProgress = 91,
3137
SocketException = 9001,
3238
WriteConcernFailed = 64

tests/MongoDB.Driver.Core.Tests/Core/Misc/ExceptionMapperTests.cs

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

16+
using System;
1617
using System.Net;
18+
using FluentAssertions;
1719
using MongoDB.Bson;
1820
using MongoDB.Driver.Core.Clusters;
1921
using MongoDB.Driver.Core.Connections;
@@ -180,5 +182,54 @@ public void TestThrowsExecutionTimeoutExceptionWhenErrMsgIsSpecified(string errm
180182
Assert.NotNull(ex);
181183
Assert.IsType<MongoExecutionTimeoutException>(ex);
182184
}
185+
186+
187+
[Theory]
188+
[InlineData(ServerErrorCode.NotMaster, typeof(MongoNotPrimaryException))]
189+
[InlineData(ServerErrorCode.NotMasterNoSlaveOk, typeof(MongoNotPrimaryException))]
190+
[InlineData(ServerErrorCode.InterruptedAtShutdown, typeof(MongoNodeIsRecoveringException))]
191+
[InlineData(ServerErrorCode.InterruptedDueToReplStateChange, typeof(MongoNodeIsRecoveringException))]
192+
[InlineData(ServerErrorCode.NotMasterOrSecondary, typeof(MongoNodeIsRecoveringException))]
193+
[InlineData(ServerErrorCode.PrimarySteppedDown, typeof(MongoNodeIsRecoveringException))]
194+
[InlineData(ServerErrorCode.ShutdownInProgress, typeof(MongoNodeIsRecoveringException))]
195+
[InlineData(-1, null)]
196+
public void MapNotPrimaryOrNodeIsRecovering_should_return_expected_result_using_code(int code, Type expectedExceptionType)
197+
{
198+
var connectionId = CreateConnectionId();
199+
var response = BsonDocument.Parse("{ ok : 0, code : 0 }");
200+
response["code"] = code;
201+
202+
var result = ExceptionMapper.MapNotPrimaryOrNodeIsRecovering(connectionId, response, "errmsg");
203+
204+
result?.GetType().Should().Be(expectedExceptionType);
205+
}
206+
207+
[Theory]
208+
[InlineData("...not master...", typeof(MongoNotPrimaryException))]
209+
[InlineData("...NOT MASTER...", typeof(MongoNotPrimaryException))]
210+
[InlineData("...node is recovering...", typeof(MongoNodeIsRecoveringException))]
211+
[InlineData("...NODE IS RECOVERING...", typeof(MongoNodeIsRecoveringException))]
212+
[InlineData("...not master or secondary...", typeof(MongoNodeIsRecoveringException))]
213+
[InlineData("...NOT MASTER OR SECONDARY...", typeof(MongoNodeIsRecoveringException))]
214+
[InlineData("", null)]
215+
public void MapNotPrimaryOrNodeIsRecovering_should_return_expected_result_using_errmsg(string errmsg, Type expectedExceptionType)
216+
{
217+
var connectionId = CreateConnectionId();
218+
var response = BsonDocument.Parse("{ ok : 0, errmsg : '' }");
219+
response["errmsg"] = errmsg;
220+
221+
var result = ExceptionMapper.MapNotPrimaryOrNodeIsRecovering(connectionId, response, "errmsg");
222+
223+
result?.GetType().Should().Be(expectedExceptionType);
224+
}
225+
226+
// private methods
227+
private ConnectionId CreateConnectionId()
228+
{
229+
var clusterId = new ClusterId(1);
230+
var endPoint = new DnsEndPoint("localhost", 27017);
231+
var serverId = new ServerId(clusterId, endPoint);
232+
return new ConnectionId(serverId);
233+
}
183234
}
184235
}

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

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,19 @@ namespace MongoDB.Driver.Core.Operations
2424
public class RetryabilityHelperTests
2525
{
2626
[Theory]
27-
[InlineData(1, false)]
27+
[InlineData(1, true)]
2828
[InlineData(ServerErrorCode.HostNotFound, true)]
2929
[InlineData(ServerErrorCode.HostUnreachable, true)]
30-
[InlineData(ServerErrorCode.InterruptedAtShutdown, true)]
31-
[InlineData(ServerErrorCode.InterruptedDueToReplStateChange, true)]
3230
[InlineData(ServerErrorCode.NetworkTimeout, true)]
33-
[InlineData(ServerErrorCode.NotMaster, true)]
34-
[InlineData(ServerErrorCode.NotMasterNoSlaveOk, true)]
35-
[InlineData(ServerErrorCode.NotMasterOrSecondary, true)]
36-
[InlineData(ServerErrorCode.PrimarySteppedDown, true)]
37-
[InlineData(ServerErrorCode.ShutdownInProgress, true)]
3831
[InlineData(ServerErrorCode.SocketException, true)]
39-
[InlineData(ServerErrorCode.WriteConcernFailed, false)]
40-
public void IsResumableChangeStreamException_should_return_expected_result_for_MongoCommandExceptions(int code, bool expectedResult)
32+
[InlineData(ServerErrorCode.ElectionInProgress, true)]
33+
[InlineData(ServerErrorCode.ExceededTimeLimit, true)]
34+
[InlineData(ServerErrorCode.RetryChangeStream, true)]
35+
[InlineData(ServerErrorCode.WriteConcernFailed, true)]
36+
[InlineData(ServerErrorCode.CappedPositionLost, false)]
37+
[InlineData(ServerErrorCode.CursorKilled, false)]
38+
[InlineData(ServerErrorCode.Interrupted, false)]
39+
public void IsResumableChangeStreamException_should_return_expected_result_using_code(int code, bool expectedResult)
4140
{
4241
var exception = CoreExceptionHelper.CreateMongoCommandException(code);
4342

@@ -50,8 +49,9 @@ public void IsResumableChangeStreamException_should_return_expected_result_for_M
5049
[InlineData(typeof(IOException), false)]
5150
[InlineData(typeof(MongoConnectionException), true)]
5251
[InlineData(typeof(MongoCursorNotFoundException), true)]
52+
[InlineData(typeof(MongoNodeIsRecoveringException), true)]
5353
[InlineData(typeof(MongoNotPrimaryException), true)]
54-
public void IsResumableChangeStreamException_should_return_expected_result_for_other_exceptions(Type exceptionType, bool expectedResult)
54+
public void IsResumableChangeStreamException_should_return_expected_result_using_exception_type(Type exceptionType, bool expectedResult)
5555
{
5656
var exception = CoreExceptionHelper.CreateException(exceptionType);
5757

@@ -64,17 +64,10 @@ public void IsResumableChangeStreamException_should_return_expected_result_for_o
6464
[InlineData(1, false)]
6565
[InlineData(ServerErrorCode.HostNotFound, true)]
6666
[InlineData(ServerErrorCode.HostUnreachable, true)]
67-
[InlineData(ServerErrorCode.InterruptedAtShutdown, true)]
68-
[InlineData(ServerErrorCode.InterruptedDueToReplStateChange, true)]
6967
[InlineData(ServerErrorCode.NetworkTimeout, true)]
70-
[InlineData(ServerErrorCode.NotMaster, true)]
71-
[InlineData(ServerErrorCode.NotMasterNoSlaveOk, true)]
72-
[InlineData(ServerErrorCode.NotMasterOrSecondary, true)]
73-
[InlineData(ServerErrorCode.PrimarySteppedDown, true)]
74-
[InlineData(ServerErrorCode.ShutdownInProgress, true)]
7568
[InlineData(ServerErrorCode.SocketException, true)]
7669
[InlineData(ServerErrorCode.WriteConcernFailed, true)]
77-
public void IsRetryableException_should_return_false(int code, bool expectedResult)
70+
public void IsRetryableException_should_return_expected_result_using_code(int code, bool expectedResult)
7871
{
7972
var exception = CoreExceptionHelper.CreateMongoCommandException(code);
8073

@@ -89,7 +82,7 @@ public void IsRetryableException_should_return_false(int code, bool expectedResu
8982
[InlineData(typeof(MongoConnectionException), true)]
9083
[InlineData(typeof(MongoNodeIsRecoveringException), true)]
9184
[InlineData(typeof(MongoNotPrimaryException), true)]
92-
public void IsRetryableException_should_return_expected_result(Type exceptionType, bool expectedResult)
85+
public void IsRetryableException_should_return_expected_result_using_exception_type(Type exceptionType, bool expectedResult)
9386
{
9487
var exception = CoreExceptionHelper.CreateException(exceptionType);
9588

0 commit comments

Comments
 (0)