internal static void PerformWithRetries <T>(Action <T> worker, T context, RetriableOperationExceptionHandler exceptionHandler, int maxRetryCount) { var initialRetryIntervalMs = BackupRestoreManager.InitialRetryInterval.Milliseconds; var maxRetryIntervalMs = BackupRestoreManager.MaxRetryInterval.Milliseconds; PerformWithRetries(worker, context, exceptionHandler, initialRetryIntervalMs, maxRetryCount, maxRetryIntervalMs); }
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; } } } }
internal static Task PerformActionWithRetriesAsync <T1, T2>(Func <T1, T2, CancellationToken, Task> worker, T1 param1, T2 param2, CancellationToken cancellationToken, RetriableOperationExceptionHandler exceptionHandler, int initialRetryIntervalMs, int maxRetryCount, int maxRetryIntervalMs) { var retryCount = 0; var retryIntervalMs = initialRetryIntervalMs; for (;;) { try { cancellationToken.ThrowIfCancellationRequested(); // Perform the operation return(worker(param1, param2, cancellationToken)); } 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 Task.Delay(retryIntervalMs, cancellationToken).Wait(); // 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; } } } }
internal static Task PerformActionWithRetriesAsync <T1, T2>(Func <T1, T2, CancellationToken, Task> worker, T1 param1, T2 param2, CancellationToken cancellationToken, RetriableOperationExceptionHandler exceptionHandler) { var initialRetryIntervalMs = BackupRestoreManager.InitialRetryInterval.Milliseconds; var maxRetryCount = BackupRestoreManager.MaxRetryCount; var maxRetryIntervalMs = BackupRestoreManager.MaxRetryInterval.Milliseconds; return(PerformActionWithRetriesAsync <T1, T2>(worker, param1, param2, cancellationToken, exceptionHandler, initialRetryIntervalMs, maxRetryCount, maxRetryIntervalMs)); }
internal static TResult PerformWithRetries <T, TResult>(Func <T, TResult> worker, T context, RetriableOperationExceptionHandler exceptionHandler, int maxRetryCount) { var initialRetryIntervalMs = BackupRestoreManager.InitialRetryInterval.Milliseconds; var maxRetryIntervalMs = BackupRestoreManager.MaxRetryInterval.Milliseconds; return(PerformWithRetries <T, TResult>(worker, context, exceptionHandler, initialRetryIntervalMs, maxRetryCount, maxRetryIntervalMs)); }