/// <summary>
        /// Specify a fallback value if all the tries fail.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="result"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static RetryResult <T> WithFallBackValue <T>(this RetryResult <T> result, T defaultValue)
        {
            if (defaultValue == null)
            {
                throw new ArgumentNullException(nameof(defaultValue));
            }

            if (!result.Successful)
            {
                try
                {
                    result.ExecutedFallBack = true;
                    result.Result           = defaultValue;
                }
                catch (Exception ex)
                {
                    result.FallBackException = ex;
                }
            }

            return(result);
        }
        /// <summary>
        /// Configure a fallback function
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="result"></param>
        /// <param name="fallback"></param>
        /// <returns></returns>
        public static RetryResult <T> WithFallBack <T>(this RetryResult <T> result, Func <T> fallback)
        {
            if (fallback == null)
            {
                throw new ArgumentNullException(nameof(fallback));
            }

            if (!result.Successful)
            {
                try
                {
                    result.ExecutedFallBack = true;
                    result.Result           = fallback();
                }
                catch (Exception ex)
                {
                    result.FallBackException = ex;
                }
            }

            return(result);
        }
예제 #3
0
        /// <summary>
        /// Retry a function n times or until successful asynchronously.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="function"></param>
        /// <param name="config"></param>
        /// <returns></returns>
        static async Task <RetryResult <T> > RetryFuncAsync <T>(Func <Task <T> > function, RetryConfig config)
        {
            var retryInfo = new RetryInfo();
            var result    = new RetryResult <T>(default(T), retryInfo);

            var  isOk             = false;
            var  retriesRemaining = config.MaxRetries;
            var  timeoutAt        = DateTime.Now.Add(config.TotalTimeout);
            bool hasTimeout       = config.HasTimeout;

            while (!isOk && (retriesRemaining >= 0 || config.RetryForever) &&
                   (!hasTimeout || (config.HasTimeout && DateTime.Now < timeoutAt)))
            {
                result.RetryInfo.Executions++;

                try
                {
                    result.Result = await function();

                    isOk = true;
                }
                catch (Exception ex)
                {
                    result.RetryInfo.Exceptions.Add(ex);

                    // Wait before retrying.
                    if (config.WaitBetweenRetries > TimeSpan.Zero)
                    {
                        Thread.Sleep(config.WaitBetweenRetries);
                    }
                }

                retriesRemaining--;
            }

            return(result);
        }