Exemple #1
0
 private void RetryLogicPoolAdd(SqlRetryLogicBase retryLogic)
 {
     if (retryLogic != null)
     {
         _retryLogicPool.Add(retryLogic);
     }
 }
Exemple #2
0
 /// <summary>Creates an instance of this type.</summary>
 public SqlRetryLogicProvider(SqlRetryLogicBase retryLogic)
 {
     Debug.Assert(retryLogic != null, $"The '{nameof(retryLogic)}' cannot be null.");
     AppContext.TryGetSwitch(EnableRetryLogicSwitch, out enableRetryLogic);
     SqlClientEventSource.Log.TryTraceEvent(@"<sc.{0}.SqlRetryLogicProvider|INFO> AppContext switch ""{1}""={2}.",
                                            TypeName, EnableRetryLogicSwitch, enableRetryLogic);
     RetryLogic = retryLogic;
 }
Exemple #3
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);
        }
Exemple #4
0
        private SqlRetryLogicBase GetRetryLogic()
        {
            SqlRetryLogicBase retryLogic = null;

            if (!_retryLogicPool.TryTake(out retryLogic))
            {
                retryLogic = RetryLogic.Clone() as SqlRetryLogicBase;
            }
            else
            {
                retryLogic?.Reset();
            }
            return(retryLogic);
        }
Exemple #5
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;
                }
            }
        }
Exemple #6
0
        /// <summary>Executes a function and applies retry logic, if enabled.</summary>
        public override TResult Execute <TResult>(object sender, Func <TResult> function)
        {
            if (function == null)
            {
                throw new ArgumentNullException(nameof(function));
            }

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

retry:
            try
            {
                TResult result = function.Invoke();
                RetryLogicPoolAdd(retryLogic);
                return(result);
            }
            catch (Exception e)
            {
                if (enableRetryLogic && RetryLogic.RetryCondition(sender) && RetryLogic.TransientPredicate(e))
                {
                    retryLogic = retryLogic ?? GetRetryLogic();
                    SqlClientEventSource.Log.TryTraceEvent("<sc.{0}.Execute<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);

                        Thread.Sleep(intervalTime);
                        goto retry;
                    }
                    else
                    {
                        throw CreateException(exceptions, retryLogic);
                    }
                }
                else
                {
                    RetryLogicPoolAdd(retryLogic);
                    throw;
                }
            }
        }
Exemple #7
0
        private void ApplyRetryingEvent(object sender, SqlRetryLogicBase retryLogic, TimeSpan intervalTime, List <Exception> exceptions, Exception lastException)
        {
            string methodName = MethodBase.GetCurrentMethod().Name;

            if (Retrying != null)
            {
                var retryEventArgs = new SqlRetryingEventArgs(retryLogic.Current, intervalTime, exceptions);
                SqlClientEventSource.Log.TryTraceEvent("<sc.{0}.{1}|INFO> Running the retrying event.", TypeName, methodName);
                Retrying?.Invoke(sender, retryEventArgs);
                if (retryEventArgs.Cancel)
                {
                    SqlClientEventSource.Log.TryTraceEvent("<sc.{0}.{1}|INFO> Retry attempt cancelled (current retry number = {2}).",
                                                           TypeName, methodName, retryLogic.Current);
                    throw CreateException(exceptions, retryLogic, true);
                }
            }
            SqlClientEventSource.Log.TryTraceEvent("<sc.{0}.{1}|INFO> Wait '{2}' and run the action for retry number {3}.",
                                                   TypeName, methodName, intervalTime, retryLogic.Current);
        }
Exemple #8
0
 /// <summary>Creates an instance of this type.</summary>
 public SqlRetryLogicProvider(SqlRetryLogicBase retryLogic)
 {
     Debug.Assert(retryLogic != null, $"The '{nameof(retryLogic)}' cannot be null.");
     RetryLogic = retryLogic;
 }
Exemple #9
0
 internal static AggregateException ConfigurableRetryFail(IList <Exception> exceptions, SqlRetryLogicBase retryLogic, bool canceled)
 => canceled ? new AggregateException(StringsHelper.GetString(Strings.SqlRetryLogic_RetryCanceled, retryLogic.Current), exceptions)
         : new AggregateException(StringsHelper.GetString(Strings.SqlRetryLogic_RetryExceeded, retryLogic.NumberOfTries), exceptions);