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);
            }
        }
Beispiel #2
0
        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);
            }
        }