Esempio n. 1
0
        public static void DelayCanBeCancelled()
        {
            var cts = new CancellationTokenSource();

            var task = new Delay().For(2000, cts.Token);
            cts.Cancel();
            Assert.True(task.IsCanceled);
        }
Esempio n. 2
0
        /// <inheritdoc/>
        public async Task <TOperation> ExecuteAsync <TOperation>(
            Func <CancellationToken, Task <TOperation> > operationFunc,
            Func <TOperation, Exception, bool> shouldRetryFunc,
            Action <TOperation, Dictionary <string, object> > appendLogInfoFunc = null,
            CancellationToken cancellationToken = new CancellationToken())
        {
            var retryDelay = InitialRetryMilliseconds;
            var attempt    = 0;
            var stopwatch  = Stopwatch.StartNew();

            while (true)
            {
                Exception operationException = null;
                var       operationResult    = default(TOperation);
                try
                {
                    operationResult = await operationFunc(cancellationToken).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    operationException = ex;
                }

                if (!shouldRetryFunc(operationResult, operationException))
                {
                    if (operationException != null)
                    {
                        ExceptionDispatchInfo.Capture(operationException).Throw();
                    }

                    return(operationResult);
                }

                // Something failed. Attempt to retry the operation.
                var loggerInfo = new Dictionary <string, object>
                {
                    { "category", "retry" },
                    { "elapsedMilliseconds", stopwatch.ElapsedMilliseconds },
                    { "operationRetryDelayMS", retryDelay },
                    { "operationAttempt", ++attempt },
                    { "operationName", "ElasticLINQ" }
                };

                if (appendLogInfoFunc != null)
                {
                    appendLogInfoFunc(operationResult, loggerInfo);
                }

                if (attempt >= MaxAttempts)
                {
                    Log.Warn(operationException, loggerInfo, "The operation failed {0} times, which is the maximum allowed.", MaxAttempts);
                    throw new RetryFailedException(MaxAttempts);
                }

                Log.Info(operationException, loggerInfo, "The operation failed (attempt #{0}) and will be retried.", attempt);

                await Delay.For(retryDelay, cancellationToken).ConfigureAwait(false);

                retryDelay = retryDelay * 2;
            }
        }
Esempio n. 3
0
        public static async void DelayDoesDelay()
        {
            const int timingFudge = 50; // Task.Delay sometimes returns too soon...
            var delayTime = TimeSpan.FromSeconds(2);
            var delay = new Delay();
            var stopwatch = new Stopwatch();

            stopwatch.Start();
            await delay.For((int)delayTime.TotalMilliseconds, CancellationToken.None);
            stopwatch.Stop();

            Assert.True(stopwatch.ElapsedMilliseconds + timingFudge >= delayTime.TotalMilliseconds, string.Format("Requested {0}ms delay but only took {1}ms", delayTime.TotalMilliseconds, stopwatch.ElapsedMilliseconds));
        }
Esempio n. 4
0
 /// <summary>
 /// Retries an operation if the operation is retryable.
 /// </summary>
 /// <param name="log">Used for logging debug and warning information.</param>
 /// <param name="initialRetryMilliseconds">The initial wait time for a retry. Subsequent retries grow exponentially. Defaults to 100ms.</param>
 /// <param name="maxAttempts">The maximum number of attempts to perform. Defaults to 10 attempts.</param>
 /// <param name="delay">The object which implements an async delay. Replaceable for testing purposes.</param>
 public RetryPolicy(ILog log, int initialRetryMilliseconds = 100, int maxAttempts = 10, Delay delay = null)
 {
     Log = log;
     InitialRetryMilliseconds = initialRetryMilliseconds;
     MaxAttempts = maxAttempts;
     Delay       = delay ?? Delay.Instance;
 }