Resolves checkstyle errors for patterns starting with letter r (#1072)
* Reduces checkstyle errors in reactor * Reduces checkstyle errors in reader-writer-lock * Reduces checkstyle errors in repository * Reduces checkstyle errors in resource-acquisition-is-initialization * Reduces checkstyle errors in retry
This commit is contained in:
		
				
					committed by
					
						
						Ilkka Seppälä
					
				
			
			
				
	
			
			
			
						parent
						
							4dae1fae57
						
					
				
				
					commit
					9c8ad4485b
				
			@@ -27,34 +27,35 @@ import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The <em>Retry</em> pattern enables applications to handle potentially recoverable failures from 
 | 
			
		||||
 * the environment if the business requirements and nature of the failures allow it. By retrying 
 | 
			
		||||
 * The <em>Retry</em> pattern enables applications to handle potentially recoverable failures from
 | 
			
		||||
 * the environment if the business requirements and nature of the failures allow it. By retrying
 | 
			
		||||
 * failed operations on external dependencies, the application may maintain stability and minimize
 | 
			
		||||
 * negative impact on the user experience.
 | 
			
		||||
 * <p>
 | 
			
		||||
 * In our example, we have the {@link BusinessOperation} interface as an abstraction over
 | 
			
		||||
 * all operations that our application performs involving remote systems. The calling code should
 | 
			
		||||
 * remain decoupled from implementations. 
 | 
			
		||||
 * <p>
 | 
			
		||||
 * {@link FindCustomer} is a business operation that looks up a customer's record and returns 
 | 
			
		||||
 * its ID. Imagine its job is performed by looking up the customer in our local database and 
 | 
			
		||||
 * returning its ID. We can pass {@link CustomerNotFoundException} as one of its 
 | 
			
		||||
 * {@link FindCustomer#FindCustomer(java.lang.String, com.iluwatar.retry.BusinessException...) 
 | 
			
		||||
 * constructor parameters} in order to simulate not finding the customer.
 | 
			
		||||
 * <p>
 | 
			
		||||
 * Imagine that, lately, this operation has experienced intermittent failures due to some weird 
 | 
			
		||||
 * corruption and/or locking in the data. After retrying a few times the customer is found. The 
 | 
			
		||||
 * database is still, however, expected to always be available.  While a definitive solution is 
 | 
			
		||||
 * found to the problem, our engineers advise us to retry the operation a set number
 | 
			
		||||
 * of times with a set delay between retries, although not too many retries otherwise the end user
 | 
			
		||||
 * will be left waiting for a long time, while delays that are too short will not allow the database
 | 
			
		||||
 * to recover from the load. 
 | 
			
		||||
 * <p>
 | 
			
		||||
 * To keep the calling code as decoupled as possible from this workaround, we have implemented the
 | 
			
		||||
 * retry mechanism as a {@link BusinessOperation} named {@link Retry}.
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * <p>In our example, we have the {@link BusinessOperation} interface as an abstraction over all
 | 
			
		||||
 * operations that our application performs involving remote systems. The calling code should remain
 | 
			
		||||
 * decoupled from implementations.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>{@link FindCustomer} is a business operation that looks up a customer's record and returns
 | 
			
		||||
 * its ID. Imagine its job is performed by looking up the customer in our local database and
 | 
			
		||||
 * returning its ID. We can pass {@link CustomerNotFoundException} as one of its {@link
 | 
			
		||||
 * FindCustomer#FindCustomer(java.lang.String, com.iluwatar.retry.BusinessException...) constructor
 | 
			
		||||
 * parameters} in order to simulate not finding the customer.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>Imagine that, lately, this operation has experienced intermittent failures due to some weird
 | 
			
		||||
 * corruption and/or locking in the data. After retrying a few times the customer is found. The
 | 
			
		||||
 * database is still, however, expected to always be available.  While a definitive solution is
 | 
			
		||||
 * found to the problem, our engineers advise us to retry the operation a set number of times with a
 | 
			
		||||
 * set delay between retries, although not too many retries otherwise the end user will be left
 | 
			
		||||
 * waiting for a long time, while delays that are too short will not allow the database to recover
 | 
			
		||||
 * from the load.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>To keep the calling code as decoupled as possible from this workaround, we have implemented
 | 
			
		||||
 * the retry mechanism as a {@link BusinessOperation} named {@link Retry}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author George Aristy (george.aristy@gmail.com)
 | 
			
		||||
 * @see <a href="https://docs.microsoft.com/en-us/azure/architecture/patterns/retry">Retry pattern (Microsoft Azure Docs)</a>
 | 
			
		||||
 * @see <a href="https://docs.microsoft.com/en-us/azure/architecture/patterns/retry">Retry pattern
 | 
			
		||||
 *     (Microsoft Azure Docs)</a>
 | 
			
		||||
 */
 | 
			
		||||
public final class App {
 | 
			
		||||
  private static final Logger LOG = LoggerFactory.getLogger(App.class);
 | 
			
		||||
@@ -62,7 +63,7 @@ public final class App {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Entry point.
 | 
			
		||||
   * 
 | 
			
		||||
   *
 | 
			
		||||
   * @param args not used
 | 
			
		||||
   * @throws Exception not expected
 | 
			
		||||
   */
 | 
			
		||||
@@ -99,22 +100,22 @@ public final class App {
 | 
			
		||||
    final String customerId = op.perform();
 | 
			
		||||
    LOG.info(String.format(
 | 
			
		||||
        "However, retrying the operation while ignoring a recoverable error will eventually yield "
 | 
			
		||||
        + "the result %s after a number of attempts %s", customerId, retry.attempts()
 | 
			
		||||
            + "the result %s after a number of attempts %s", customerId, retry.attempts()
 | 
			
		||||
    ));
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  private static void errorWithRetryExponentialBackoff() throws Exception {
 | 
			
		||||
    final RetryExponentialBackoff<String> retry = new RetryExponentialBackoff<>(
 | 
			
		||||
        new FindCustomer("123", new CustomerNotFoundException("not found")),
 | 
			
		||||
        6,  //6 attempts
 | 
			
		||||
        30000, //30 s max delay between attempts
 | 
			
		||||
        e -> CustomerNotFoundException.class.isAssignableFrom(e.getClass())
 | 
			
		||||
        );
 | 
			
		||||
    );
 | 
			
		||||
    op = retry;
 | 
			
		||||
    final String customerId = op.perform();
 | 
			
		||||
    LOG.info(String.format(
 | 
			
		||||
                "However, retrying the operation while ignoring a recoverable error will eventually yield "
 | 
			
		||||
                        + "the result %s after a number of attempts %s", customerId, retry.attempts()
 | 
			
		||||
        ));
 | 
			
		||||
        "However, retrying the operation while ignoring a recoverable error will eventually yield "
 | 
			
		||||
            + "the result %s after a number of attempts %s", customerId, retry.attempts()
 | 
			
		||||
    ));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,10 +24,10 @@
 | 
			
		||||
package com.iluwatar.retry;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The top-most type in our exception hierarchy that signifies that an unexpected error 
 | 
			
		||||
 * condition occurred. Its use is reserved as a "catch-all" for cases where no other subtype 
 | 
			
		||||
 * captures the specificity of the error condition in question. Calling code is not expected to 
 | 
			
		||||
 * be able to handle this error and should be reported to the maintainers immediately.
 | 
			
		||||
 * The top-most type in our exception hierarchy that signifies that an unexpected error condition
 | 
			
		||||
 * occurred. Its use is reserved as a "catch-all" for cases where no other subtype captures the
 | 
			
		||||
 * specificity of the error condition in question. Calling code is not expected to be able to handle
 | 
			
		||||
 * this error and should be reported to the maintainers immediately.
 | 
			
		||||
 *
 | 
			
		||||
 * @author George Aristy (george.aristy@gmail.com)
 | 
			
		||||
 */
 | 
			
		||||
@@ -35,8 +35,8 @@ public class BusinessException extends Exception {
 | 
			
		||||
  private static final long serialVersionUID = 6235833142062144336L;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Ctor
 | 
			
		||||
   * 
 | 
			
		||||
   * Ctor.
 | 
			
		||||
   *
 | 
			
		||||
   * @param message the error message
 | 
			
		||||
   */
 | 
			
		||||
  public BusinessException(String message) {
 | 
			
		||||
 
 | 
			
		||||
@@ -26,18 +26,18 @@ package com.iluwatar.retry;
 | 
			
		||||
/**
 | 
			
		||||
 * Performs some business operation.
 | 
			
		||||
 *
 | 
			
		||||
 * @author George Aristy (george.aristy@gmail.com)
 | 
			
		||||
 * @param <T> the return type
 | 
			
		||||
 * @author George Aristy (george.aristy@gmail.com)
 | 
			
		||||
 */
 | 
			
		||||
@FunctionalInterface
 | 
			
		||||
public interface BusinessOperation<T> {
 | 
			
		||||
  /**
 | 
			
		||||
   * Performs some business operation, returning a value {@code T} if successful, otherwise throwing
 | 
			
		||||
   * an exception if an error occurs.
 | 
			
		||||
   * 
 | 
			
		||||
   *
 | 
			
		||||
   * @return the return value
 | 
			
		||||
   * @throws BusinessException if the operation fails. Implementations are allowed to throw more
 | 
			
		||||
   *     specific subtypes depending on the error conditions
 | 
			
		||||
   *                           specific subtypes depending on the error conditions
 | 
			
		||||
   */
 | 
			
		||||
  T perform() throws BusinessException;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,10 +24,11 @@
 | 
			
		||||
package com.iluwatar.retry;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Indicates that the customer was not found. 
 | 
			
		||||
 * <p>
 | 
			
		||||
 * The severity of this error is bounded by its context: was the search for the customer triggered
 | 
			
		||||
 * by an input from some end user, or were the search parameters pulled from your database?
 | 
			
		||||
 * Indicates that the customer was not found.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>The severity of this error is bounded by its context: was the search for the customer
 | 
			
		||||
 * triggered by an input from some end user, or were the search parameters pulled from your
 | 
			
		||||
 * database?
 | 
			
		||||
 *
 | 
			
		||||
 * @author George Aristy (george.aristy@gmail.com)
 | 
			
		||||
 */
 | 
			
		||||
@@ -36,7 +37,7 @@ public final class CustomerNotFoundException extends BusinessException {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Ctor.
 | 
			
		||||
   * 
 | 
			
		||||
   *
 | 
			
		||||
   * @param message the error message
 | 
			
		||||
   */
 | 
			
		||||
  public CustomerNotFoundException(String message) {
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,7 @@ public final class DatabaseNotAvailableException extends BusinessException {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Ctor.
 | 
			
		||||
   * 
 | 
			
		||||
   *
 | 
			
		||||
   * @param message the error message
 | 
			
		||||
   */
 | 
			
		||||
  public DatabaseNotAvailableException(String message) {
 | 
			
		||||
 
 | 
			
		||||
@@ -29,9 +29,9 @@ import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Finds a customer, returning its ID from our records.
 | 
			
		||||
 * <p>
 | 
			
		||||
 * This is an imaginary operation that, for some imagined input, returns the ID for a customer. 
 | 
			
		||||
 * However, this is a "flaky" operation that is supposed to fail intermittently, but for the 
 | 
			
		||||
 *
 | 
			
		||||
 * <p>This is an imaginary operation that, for some imagined input, returns the ID for a customer.
 | 
			
		||||
 * However, this is a "flaky" operation that is supposed to fail intermittently, but for the
 | 
			
		||||
 * purposes of this example it fails in a programmed way depending on the constructor parameters.
 | 
			
		||||
 *
 | 
			
		||||
 * @author George Aristy (george.aristy@gmail.com)
 | 
			
		||||
@@ -42,15 +42,15 @@ public final class FindCustomer implements BusinessOperation<String> {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Ctor.
 | 
			
		||||
   * 
 | 
			
		||||
   *
 | 
			
		||||
   * @param customerId the final result of the remote operation
 | 
			
		||||
   * @param errors the errors to throw before returning {@code customerId}
 | 
			
		||||
   * @param errors     the errors to throw before returning {@code customerId}
 | 
			
		||||
   */
 | 
			
		||||
  public FindCustomer(String customerId, BusinessException... errors) {
 | 
			
		||||
    this.customerId = customerId;
 | 
			
		||||
    this.errors = new ArrayDeque<>(List.of(errors));
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public String perform() throws BusinessException {
 | 
			
		||||
    if (!this.errors.isEmpty()) {
 | 
			
		||||
 
 | 
			
		||||
@@ -33,8 +33,8 @@ import java.util.function.Predicate;
 | 
			
		||||
/**
 | 
			
		||||
 * Decorates {@link BusinessOperation business operation} with "retry" capabilities.
 | 
			
		||||
 *
 | 
			
		||||
 * @author George Aristy (george.aristy@gmail.com)
 | 
			
		||||
 * @param <T> the remote op's return type
 | 
			
		||||
 * @author George Aristy (george.aristy@gmail.com)
 | 
			
		||||
 */
 | 
			
		||||
public final class Retry<T> implements BusinessOperation<T> {
 | 
			
		||||
  private final BusinessOperation<T> op;
 | 
			
		||||
@@ -46,18 +46,18 @@ public final class Retry<T> implements BusinessOperation<T> {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Ctor.
 | 
			
		||||
   * 
 | 
			
		||||
   * @param op the {@link BusinessOperation} to retry
 | 
			
		||||
   *
 | 
			
		||||
   * @param op          the {@link BusinessOperation} to retry
 | 
			
		||||
   * @param maxAttempts number of times to retry
 | 
			
		||||
   * @param delay delay (in milliseconds) between attempts
 | 
			
		||||
   * @param delay       delay (in milliseconds) between attempts
 | 
			
		||||
   * @param ignoreTests tests to check whether the remote exception can be ignored. No exceptions
 | 
			
		||||
   *     will be ignored if no tests are given
 | 
			
		||||
   *                    will be ignored if no tests are given
 | 
			
		||||
   */
 | 
			
		||||
  @SafeVarargs
 | 
			
		||||
  public Retry(
 | 
			
		||||
      BusinessOperation<T> op, 
 | 
			
		||||
      int maxAttempts, 
 | 
			
		||||
      long delay, 
 | 
			
		||||
      BusinessOperation<T> op,
 | 
			
		||||
      int maxAttempts,
 | 
			
		||||
      long delay,
 | 
			
		||||
      Predicate<Exception>... ignoreTests
 | 
			
		||||
  ) {
 | 
			
		||||
    this.op = op;
 | 
			
		||||
@@ -70,7 +70,7 @@ public final class Retry<T> implements BusinessOperation<T> {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The errors encountered while retrying, in the encounter order.
 | 
			
		||||
   * 
 | 
			
		||||
   *
 | 
			
		||||
   * @return the errors encountered while retrying
 | 
			
		||||
   */
 | 
			
		||||
  public List<Exception> errors() {
 | 
			
		||||
@@ -79,7 +79,7 @@ public final class Retry<T> implements BusinessOperation<T> {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The number of retries performed.
 | 
			
		||||
   * 
 | 
			
		||||
   *
 | 
			
		||||
   * @return the number of retries performed
 | 
			
		||||
   */
 | 
			
		||||
  public int attempts() {
 | 
			
		||||
@@ -93,7 +93,7 @@ public final class Retry<T> implements BusinessOperation<T> {
 | 
			
		||||
        return this.op.perform();
 | 
			
		||||
      } catch (BusinessException e) {
 | 
			
		||||
        this.errors.add(e);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        if (this.attempts.incrementAndGet() >= this.maxAttempts || !this.test.test(e)) {
 | 
			
		||||
          throw e;
 | 
			
		||||
        }
 | 
			
		||||
@@ -104,7 +104,6 @@ public final class Retry<T> implements BusinessOperation<T> {
 | 
			
		||||
          //ignore
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    while (true);
 | 
			
		||||
    } while (true);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -34,8 +34,8 @@ import java.util.function.Predicate;
 | 
			
		||||
/**
 | 
			
		||||
 * Decorates {@link BusinessOperation business operation} with "retry" capabilities.
 | 
			
		||||
 *
 | 
			
		||||
 * @author George Aristy (george.aristy@gmail.com)
 | 
			
		||||
 * @param <T> the remote op's return type
 | 
			
		||||
 * @author George Aristy (george.aristy@gmail.com)
 | 
			
		||||
 */
 | 
			
		||||
public final class RetryExponentialBackoff<T> implements BusinessOperation<T> {
 | 
			
		||||
  private static final Random RANDOM = new Random();
 | 
			
		||||
@@ -46,20 +46,20 @@ public final class RetryExponentialBackoff<T> implements BusinessOperation<T> {
 | 
			
		||||
  private final Predicate<Exception> test;
 | 
			
		||||
  private final List<Exception> errors;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Ctor.
 | 
			
		||||
     *
 | 
			
		||||
     * @param op the {@link BusinessOperation} to retry
 | 
			
		||||
     * @param maxAttempts number of times to retry
 | 
			
		||||
     * @param ignoreTests tests to check whether the remote exception can be ignored. No exceptions
 | 
			
		||||
     *     will be ignored if no tests are given
 | 
			
		||||
     */
 | 
			
		||||
  /**
 | 
			
		||||
   * Ctor.
 | 
			
		||||
   *
 | 
			
		||||
   * @param op          the {@link BusinessOperation} to retry
 | 
			
		||||
   * @param maxAttempts number of times to retry
 | 
			
		||||
   * @param ignoreTests tests to check whether the remote exception can be ignored. No exceptions
 | 
			
		||||
   *                    will be ignored if no tests are given
 | 
			
		||||
   */
 | 
			
		||||
  @SafeVarargs
 | 
			
		||||
  public RetryExponentialBackoff(
 | 
			
		||||
            BusinessOperation<T> op,
 | 
			
		||||
            int maxAttempts,
 | 
			
		||||
            long maxDelay,
 | 
			
		||||
            Predicate<Exception>... ignoreTests
 | 
			
		||||
      BusinessOperation<T> op,
 | 
			
		||||
      int maxAttempts,
 | 
			
		||||
      long maxDelay,
 | 
			
		||||
      Predicate<Exception>... ignoreTests
 | 
			
		||||
  ) {
 | 
			
		||||
    this.op = op;
 | 
			
		||||
    this.maxAttempts = maxAttempts;
 | 
			
		||||
@@ -69,20 +69,20 @@ public final class RetryExponentialBackoff<T> implements BusinessOperation<T> {
 | 
			
		||||
    this.errors = new ArrayList<>();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The errors encountered while retrying, in the encounter order.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the errors encountered while retrying
 | 
			
		||||
     */
 | 
			
		||||
  /**
 | 
			
		||||
   * The errors encountered while retrying, in the encounter order.
 | 
			
		||||
   *
 | 
			
		||||
   * @return the errors encountered while retrying
 | 
			
		||||
   */
 | 
			
		||||
  public List<Exception> errors() {
 | 
			
		||||
    return Collections.unmodifiableList(this.errors);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The number of retries performed.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the number of retries performed
 | 
			
		||||
     */
 | 
			
		||||
  /**
 | 
			
		||||
   * The number of retries performed.
 | 
			
		||||
   *
 | 
			
		||||
   * @return the number of retries performed
 | 
			
		||||
   */
 | 
			
		||||
  public int attempts() {
 | 
			
		||||
    return this.attempts.intValue();
 | 
			
		||||
  }
 | 
			
		||||
@@ -107,8 +107,7 @@ public final class RetryExponentialBackoff<T> implements BusinessOperation<T> {
 | 
			
		||||
          //ignore
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    while (true);
 | 
			
		||||
    } while (true);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user