コード例 #1
0
        private Exception CreateException(IList <Exception> exceptions, SqlRetryLogicBase retryLogic, bool manualCancellation = false)
        {
            AggregateException result = SqlReliabilityUtil.ConfigurableRetryFail(exceptions, retryLogic, manualCancellation);

            if (!manualCancellation)
            {
                SqlClientEventSource.Log.TryTraceEvent("<sc.{0}.{1}|ERR|THROW> Exiting retry scope (exceeded the max allowed attempts = {2}).",
                                                       TypeName, MethodBase.GetCurrentMethod().Name, retryLogic.NumberOfTries);
            }
            _retryLogicPool.Add(retryLogic);
            return(result);
        }
コード例 #2
0
        private static SqlRetryLogicBaseProvider CreateRetryLogicProvider(string sectionName, ISqlConfigurableRetryConnectionSection configSection)
        {
            string methodName = MethodBase.GetCurrentMethod().Name;

            SqlClientEventSource.Log.TryTraceEvent("<sc.{0}.{1}|INFO> Entry point.", TypeName, methodName);

            try
            {
                if (configSection == null)
                {
                    throw SqlReliabilityUtil.ArgumentNull(nameof(configSection));
                }

                // Create a SqlRetryLogicOption object from the discovered retry logic values
                var retryOption = new SqlRetryLogicOption()
                {
                    NumberOfTries   = configSection.NumberOfTries,
                    DeltaTime       = configSection.DeltaTime,
                    MinTimeInterval = configSection.MinTimeInterval,
                    MaxTimeInterval = configSection.MaxTimeInterval
                };

                // Prepare the transient error lists
                if (!string.IsNullOrEmpty(configSection.TransientErrors))
                {
                    retryOption.TransientErrors = configSection.TransientErrors.Split(',').Select(x => Convert.ToInt32(x)).ToList();
                }

                // Prepare the authorized SQL statement just for SqlCommands
                if (configSection is ISqlConfigurableRetryCommandSection cmdSection && !string.IsNullOrEmpty(cmdSection.AuthorizedSqlCondition))
                {
                    retryOption.AuthorizedSqlCondition = (x) => Regex.IsMatch(x, cmdSection.AuthorizedSqlCondition);
                }
                SqlClientEventSource.Log.TryTraceEvent("<sc.{0}.{1}|INFO> Successfully created a {2} object to use on creating a retry logic provider from the section '{3}'.",
                                                       TypeName, methodName, nameof(SqlRetryLogicOption), sectionName);

                // Extract the SqlRetryLogicBaseProvider object from the given information
                var provider = ResolveRetryLogicProvider(configSection.RetryLogicType, configSection.RetryMethod, retryOption);
                SqlClientEventSource.Log.TryTraceEvent("<sc.{0}.{1}|INFO> Successfully created a {2} object from the section '{3}'.",
                                                       TypeName, methodName, nameof(SqlRetryLogicBaseProvider), sectionName);
                return(provider);
            }
            catch (Exception e)
            {
                SqlClientEventSource.Log.TryTraceEvent("<sc.{0}.{1}|INFO> {2}",
                                                       TypeName, methodName, e);
            }
            SqlClientEventSource.Log.TryTraceEvent("<sc.{0}.{1}|INFO> Due to an exception, the default non-retriable logic will be applied.",
                                                   TypeName, methodName);
            // Return default provider if an exception occured.
            return(SqlConfigurableRetryFactory.CreateNoneRetryProvider());
        }
コード例 #3
0
        /// <summary>Executes a function and applies retry logic, if enabled.</summary>
        public override async Task <TResult> ExecuteAsync <TResult>(object sender, Func <Task <TResult> > function, CancellationToken cancellationToken = default)
        {
            if (function == null)
            {
                throw SqlReliabilityUtil.ArgumentNull(nameof(function));
            }

            SqlRetryLogicBase retryLogic = null;
            var exceptions = new List <Exception>();

retry:
            try
            {
                TResult result = await function.Invoke();

                RetryLogicPoolAdd(retryLogic);
                return(result);
            }
            catch (Exception e)
            {
                if (RetryLogic.RetryCondition(sender) && RetryLogic.TransientPredicate(e))
                {
                    retryLogic = retryLogic ?? GetRetryLogic();
                    SqlClientEventSource.Log.TryTraceEvent("<sc.{0}.ExecuteAsync<TResult>|INFO> Found an action eligible for the retry policy (retried attempts = {1}).",
                                                           TypeName, retryLogic.Current);
                    exceptions.Add(e);
                    if (retryLogic.TryNextInterval(out TimeSpan intervalTime))
                    {
                        // The retrying event raises on each retry.
                        ApplyRetryingEvent(sender, retryLogic, intervalTime, exceptions, e);

                        await Task.Delay(intervalTime, cancellationToken);

                        goto retry;
                    }
                    else
                    {
                        throw CreateException(exceptions, retryLogic);
                    }
                }
                else
                {
                    RetryLogicPoolAdd(retryLogic);
                    throw;
                }
            }
        }
コード例 #4
0
        public SqlRetryLogic(int numberOfTries,
                             SqlRetryIntervalBaseEnumerator enumerator,
                             Predicate <Exception> transientPredicate,
                             Predicate <string> preCondition)
        {
            Debug.Assert(enumerator != null, $"The '{nameof(enumerator)}' mustn't be null.");
            Debug.Assert(transientPredicate != null, $"The '{nameof(transientPredicate)}' mustn't be null.");

            if (!(numberOfTries > counterDefaultValue && numberOfTries <= maxAttempts))
            {
                // The 'numberOfTries' should be between 1 and 60.
                throw SqlReliabilityUtil.ArgumentOutOfRange(nameof(numberOfTries), numberOfTries, counterDefaultValue + 1, maxAttempts);
            }

            NumberOfTries           = numberOfTries;
            RetryIntervalEnumerator = enumerator;
            TransientPredicate      = transientPredicate;
            PreCondition            = preCondition;
            Current = counterDefaultValue;
        }
コード例 #5
0
        /// <include file='../../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlRetryIntervalBaseEnumerator.xml' path='docs/members[@name="SqlRetryIntervalBaseEnumerator"]/Validate/*' />
        protected virtual void Validate(TimeSpan timeInterval, TimeSpan maxTimeInterval, TimeSpan minTimeInterval)
        {
            if (minTimeInterval < _minValue || minTimeInterval > _maxValue)
            {
                throw SqlReliabilityUtil.ArgumentOutOfRange(nameof(minTimeInterval), minTimeInterval, _minValue, _maxValue);
            }

            if (maxTimeInterval < _minValue || maxTimeInterval > _maxValue)
            {
                throw SqlReliabilityUtil.ArgumentOutOfRange(nameof(maxTimeInterval), maxTimeInterval, _minValue, _maxValue);
            }

            if (timeInterval < _minValue || timeInterval > _maxValue)
            {
                throw SqlReliabilityUtil.ArgumentOutOfRange(nameof(timeInterval), timeInterval, _minValue, _maxValue);
            }

            if (maxTimeInterval < minTimeInterval)
            {
                throw SqlReliabilityUtil.InvalidMinAndMaxPair(nameof(minTimeInterval), minTimeInterval, nameof(maxTimeInterval), maxTimeInterval);
            }
        }