예제 #1
0
        internal static async Task PerformWithRetriesAsync <T>(Func <T, CancellationToken, Task> worker, T context, CancellationToken cancellationToken, RetriableOperationExceptionHandler exceptionHandler, int initialRetryIntervalMs, int maxRetryCount, int maxRetryIntervalMs)
        {
            var retryCount      = 0;
            var retryIntervalMs = initialRetryIntervalMs;

            for (;;)
            {
                try
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    // Perform the operation
                    await worker(context, cancellationToken);

                    return;
                }
                catch (Exception e)
                {
                    // Invoke the exception handler if present
                    var response = exceptionHandler.Handler(e);

                    if (RetriableOperationExceptionHandler.Response.Abort == response)
                    {
                        // The nature of the failure is such that we should not retry
                        throw;
                    }

                    // Should retry the operation
                    if (retryCount < maxRetryCount)
                    {
                        // We should retry the operation after an interval
                        await Task.Delay(retryIntervalMs, cancellationToken);

                        // Update the retry count
                        retryCount++;

                        // Update the interval to wait between retries. We are using a backoff mechanism here.
                        // The caller is responsible for ensuring that this doesn't overflow by providing a
                        // reasonable combination of initialRetryIntervalMS and maxRetryCount.
                        int nextRetryIntervalMs;
                        checked
                        {
                            nextRetryIntervalMs = retryIntervalMs * 2;
                        }

                        if (nextRetryIntervalMs <= maxRetryIntervalMs)
                        {
                            retryIntervalMs = nextRetryIntervalMs;
                        }
                    }
                    else
                    {
                        // The operation failed even after the maximum number of retries
                        throw;
                    }
                }
            }
        }
예제 #2
0
        internal static void PerformWithRetries <T>(Action <T> worker, T context, RetriableOperationExceptionHandler exceptionHandler, int initialRetryIntervalMs, int maxRetryCount, int maxRetryIntervalMs)
        {
            var retryCount      = 0;
            var retryIntervalMs = initialRetryIntervalMs;

            for (;;)
            {
                try
                {
                    // Perform the operation
                    worker(context);
                    break;
                }
                catch (Exception e)
                {
                    // Invoke the exception handler if present
                    var response = exceptionHandler.Handler(e);

                    if (RetriableOperationExceptionHandler.Response.Abort == response)
                    {
                        // The nature of the failure is such that we should not retry
                        throw;
                    }

                    // Should retry the operation
                    if (retryCount < maxRetryCount)
                    {
                        // We should retry the operation after an interval
                        Thread.Sleep(retryIntervalMs);

                        // Update the retry count
                        retryCount++;

                        // Update the interval to wait between retries. We are using a backoff mechanism here.
                        // The caller is responsible for ensuring that this doesn't overflow by providing a
                        // reasonable combination of initialRetryIntervalMS and maxRetryCount.
                        int nextRetryIntervalMs;
                        checked
                        {
                            nextRetryIntervalMs = retryIntervalMs * 2;
                        }

                        if (nextRetryIntervalMs <= maxRetryIntervalMs)
                        {
                            retryIntervalMs = nextRetryIntervalMs;
                        }
                    }
                    else
                    {
                        // The operation failed even after the maximum number of retries
                        throw;
                    }
                }
            }
        }