private bool ShouldInvalidateServer( IConnection connection, Exception exception, ServerDescription description, out TopologyVersion invalidatingResponseTopologyVersion) { if (exception is MongoConnectionException mongoConnectionException && mongoConnectionException.ContainsTimeoutException) { invalidatingResponseTopologyVersion = null; return(false); } if (__invalidatingExceptions.Contains(exception.GetType())) { invalidatingResponseTopologyVersion = null; return(true); } var exceptionsToCheck = new[] { exception as MongoCommandException, (exception as MongoWriteConcernException)?.MappedWriteConcernResultException } .OfType <MongoCommandException>(); foreach (MongoCommandException commandException in exceptionsToCheck) { if (IsStateChangeException(commandException)) { return(!IsStaleStateChangeError(commandException.Result, out invalidatingResponseTopologyVersion)); } } invalidatingResponseTopologyVersion = null; return(false); bool IsStaleStateChangeError(BsonDocument response, out TopologyVersion nonStaleResponseTopologyVersion) { if (ConnectionPool.Generation > connection.Generation) { // stale generation number nonStaleResponseTopologyVersion = null; return(true); } var responseTopologyVersion = TopologyVersion.FromMongoCommandResponse(response); // We use FresherThanOrEqualTo instead of FresherThan because a state change should come with a new // topology version. // We cannot use StalerThan(responseTopologyVersion, description.TopologyVersion) because due to how // TopologyVersions comparisons are defined, FresherThanOrEqualTo(x, y) does not imply StalerThan(y, x) bool isStale = TopologyVersion.IsFresherThanOrEqualTo(description.TopologyVersion, responseTopologyVersion); nonStaleResponseTopologyVersion = isStale ? null : responseTopologyVersion; return(isStale); } }
private bool ShouldInvalidateServer( IConnection connection, Exception exception, ServerDescription description, out TopologyVersion invalidatingResponseTopologyVersion) { if (exception is MongoConnectionException mongoConnectionException && mongoConnectionException.ContainsSocketTimeoutException) { invalidatingResponseTopologyVersion = null; return(false); } if (__invalidatingExceptions.Contains(exception.GetType())) { invalidatingResponseTopologyVersion = null; return(true); } var commandException = exception as MongoCommandException; if (commandException != null) { var code = (ServerErrorCode)commandException.Code; var message = commandException.ErrorMessage; if (IsStateChangeError(code, message)) { return(!IsStaleStateChangeError(commandException.Result, out invalidatingResponseTopologyVersion)); } if (commandException.GetType() == typeof(MongoWriteConcernException)) { var writeConcernException = (MongoWriteConcernException)commandException; var writeConcernResult = writeConcernException.WriteConcernResult; var response = writeConcernResult.Response; var writeConcernError = response["writeConcernError"].AsBsonDocument; if (writeConcernError != null) { code = (ServerErrorCode)writeConcernError.GetValue("code", -1).ToInt32(); message = writeConcernError.GetValue("errmsg", null)?.AsString; if (IsStateChangeError(code, message)) { return(!IsStaleStateChangeError(commandException.Result, out invalidatingResponseTopologyVersion)); } } } } invalidatingResponseTopologyVersion = null; return(false); bool IsStaleStateChangeError(BsonDocument response, out TopologyVersion nonStaleResponseTopologyVersion) { if (_connectionPool.Generation > connection.Generation) { // stale generation number nonStaleResponseTopologyVersion = null; return(true); } var responseTopologyVersion = TopologyVersion.FromMongoCommandResponse(response); // We use FresherThanOrEqualTo instead of FresherThan because a state change should come with a new // topology version. // We cannot use StalerThan(responseTopologyVersion, description.TopologyVersion) because due to how // TopologyVersions comparisons are defined, FresherThanOrEqualTo(x, y) does not imply StalerThan(y, x) bool isStale = TopologyVersion.IsFresherThanOrEqualTo(description.TopologyVersion, responseTopologyVersion); nonStaleResponseTopologyVersion = isStale ? null : responseTopologyVersion; return(isStale); } }