Retry.java

  1. package com.github.dakusui.actionunit.actions;

  2. import com.github.dakusui.actionunit.core.Action;

  3. import java.util.Formatter;
  4. import java.util.concurrent.TimeUnit;

  5. import static com.github.dakusui.actionunit.utils.Checks.requireArgument;
  6. import static com.github.dakusui.actionunit.utils.InternalUtils.formatDuration;
  7. import static com.github.dakusui.actionunit.utils.InternalUtils.formatNumberOfTimes;
  8. import static java.util.Objects.requireNonNull;
  9. import static java.util.concurrent.TimeUnit.SECONDS;

  10. public interface Retry extends Action {

  11.   Action perform();

  12.   int times();

  13.   Class<? extends Throwable> targetExceptionClass();

  14.   long intervalInNanoseconds();

  15.   default void accept(Visitor visitor) {
  16.     visitor.visit(this);
  17.   }

  18.   @Override
  19.   default void formatTo(Formatter formatter, int flags, int width, int precision) {
  20.     formatter.format("retry %s in %s on %s",
  21.         formatNumberOfTimes(times()),
  22.         formatDuration(intervalInNanoseconds()),
  23.         targetExceptionClass().getSimpleName()
  24.     );
  25.   }

  26.   class Builder extends Action.Builder<Retry> {

  27.     private final Action                     perform;
  28.     private       int                        times                = 2;
  29.     private       Class<? extends Throwable> targetExceptionClass = Exception.class;
  30.     private       long                       interval             = 10;
  31.     private       TimeUnit                   timeUnit             = SECONDS;

  32.     public Builder(Action perform) {
  33.       this.perform = requireNonNull(perform);
  34.     }

  35.     public Builder times(int times) {
  36.       requireArgument(v -> v >= 0, times);
  37.       this.times = times;
  38.       return this;
  39.     }

  40.     public Builder on(Class<? extends Throwable> targetExceptionClass) {
  41.       this.targetExceptionClass = requireNonNull(targetExceptionClass);
  42.       return this;
  43.     }

  44.     public Builder withIntervalOf(long interval, TimeUnit timeUnit) {
  45.       this.interval = requireArgument(v -> v > 0, interval);
  46.       this.timeUnit = requireNonNull(timeUnit);
  47.       return this;
  48.     }

  49.     @Override
  50.     public Retry build() {
  51.       return new Retry() {
  52.         @Override
  53.         public Action perform() {
  54.           return Builder.this.perform;
  55.         }

  56.         @Override
  57.         public int times() {
  58.           return Builder.this.times;
  59.         }

  60.         @Override
  61.         public Class<? extends Throwable> targetExceptionClass() {
  62.           return Builder.this.targetExceptionClass;
  63.         }

  64.         @Override
  65.         public long intervalInNanoseconds() {
  66.           return timeUnit.toNanos(Builder.this.interval);
  67.         }

  68.         @Override
  69.         public String toString() {
  70.           return String.format("retry(%sx%dtimes)",
  71.               formatDuration(intervalInNanoseconds()),
  72.               times
  73.           );
  74.         }
  75.       };
  76.     }
  77.   }
  78. }