public void PropertiesAreSetByConstrutor()
        {
            var condition = new RetryCondition(true, TimeSpan.FromSeconds(1));
            Assert.Equal(true, condition.RetryAllowed);
            Assert.Equal(TimeSpan.FromSeconds(1), condition.DelayBeforeRetry);

            condition = new RetryCondition(false, TimeSpan.Zero);
            Assert.Equal(false, condition.RetryAllowed);
            Assert.Equal(TimeSpan.Zero, condition.DelayBeforeRetry);
        }
Example #2
0
        public virtual TResult ExecuteAction <TResult>(Func <TResult> func)
        {
            Guard.ArgumentNotNull(func, "func");

            int       retryCount = 0;
            TimeSpan  delay      = TimeSpan.Zero;
            Exception lastError;

            var shouldRetry = this.RetryStrategy.GetShouldRetryHandler();

            for (;;)
            {
                lastError = null;

                try
                {
                    return(func());
                }
                catch (Exception ex)
                {
                    lastError = ex;

                    if (!(this.ErrorDetectionStrategy.IsTransient(lastError)))
                    {
                        throw;
                    }

                    RetryCondition condition = shouldRetry(retryCount++, lastError);
                    if (!condition.RetryAllowed)
                    {
                        throw;
                    }
                    delay = condition.DelayBeforeRetry;
                }

                // Perform an extra check in the delay interval. Should prevent from accidentally ending up with the
                // value of -1 that will block a thread indefinitely. In addition, any other negative numbers will
                // cause an ArgumentOutOfRangeException fault that will be thrown by Thread.Sleep.
                if (delay.TotalMilliseconds < 0)
                {
                    delay = TimeSpan.Zero;
                }

                this.OnRetrying(retryCount, lastError, delay);

                if (retryCount > 1 || !this.RetryStrategy.FastFirstRetry)
                {
                    PlatformTask.Delay(delay).Wait();
                }
            }
        }
Example #3
0
        private Task <TResult> ExecuteAsyncContinueWith(Task <TResult> runningTask)
        {
            if (!runningTask.IsFaulted || this._cancellationToken.IsCancellationRequested)
            {
                return(runningTask);
            }

            TimeSpan delay = TimeSpan.Zero;

            Exception lastError = runningTask.Exception.InnerException;

            if (!(this._isTransient(lastError)))
            {
                // if not transient, return the faulted running task.
                return(runningTask);
            }

            RetryCondition condition = this._shouldRetryHandler(this._retryCount++, lastError);

            if (!condition.RetryAllowed)
            {
                return(runningTask);
            }
            delay = condition.DelayBeforeRetry;

            // Perform an extra check in the delay interval.
            if (delay < TimeSpan.Zero)
            {
                delay = TimeSpan.Zero;
            }

            this._onRetrying(this._retryCount, lastError, delay);

            this._previousTask = runningTask;
            if (delay > TimeSpan.Zero && (this._retryCount > 1 || !this._fastFirstRetry))
            {
                return(PlatformTask.Delay(delay)
                       .ContinueWith <Task <TResult> >(this.ExecuteAsyncImpl, CancellationToken.None,
                                                       TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default)
                       .Unwrap());
            }

            return(this.ExecuteAsyncImpl(null));
        }