package com.sequenceiq.cloudbreak.cloud.retry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RetryUtil implements Runnable { private static final Logger LOGGER = LoggerFactory.getLogger(RetryUtil.class); private static final int DEFAULT_NUMBER_OF_RETRIES = 3; private int retryCount; private RetryTask task; private ErrorTask errorHandler; private ExceptionCheckTask exceptionCheck; private CheckTask check; private RetryUtil(int count) { this.retryCount = count; } public static RetryUtil withDefaultRetries() { return new RetryUtil(DEFAULT_NUMBER_OF_RETRIES); } public static RetryUtil withRetries(int count) { return new RetryUtil(count); } public RetryUtil retry(RetryTask task) { this.task = task; return this; } public RetryUtil retryIfFalse(CheckTask check) { this.check = check; return this; } public RetryUtil checkIfRecoverable(ExceptionCheckTask check) { this.exceptionCheck = check; return this; } public RetryUtil ifNotRecoverable(ErrorTask errorHandler) { this.errorHandler = errorHandler; return this; } @Override public void run() { try { retryCount--; task.run(); runChecker(); } catch (Exception e) { runExceptionChecker(e); } } private void runRetry() { if (retryCount > 0) { run(); } else { runErrorHandler(new RetryException("too many retries")); } } private void runChecker() { if (check != null && !check.check()) { runRetry(); } } private void runExceptionChecker(Exception e) { if (exceptionCheck == null || exceptionCheck.check(e)) { runRetry(); } else { runErrorHandler(e); } } private void runErrorHandler(Exception e) { try { if (errorHandler != null) { errorHandler.run(e); } } catch (Exception ex) { LOGGER.warn("ErrorHandler failed during retries.", ex); } } }