RetryPolicy implements SyncRetryExecutor<T, C> { @CheckReturnValue public static <T, C extends Callable<? extends T>> Builder<T, C> newBuilder() { return new Builder<>(); } RetryPolicy(final TimedSupplier<RetryPredicate<T, C>> retryPredicate,
          final int maxExceptionChain); static RetryPolicy<T, C> noRetryPolicy(); static RetryPolicy<T, C> defaultPolicy(); @Override final R call(
          final W pwhat, final Class<EX> exceptionClass, final long startNanos, final long deadlineNanos); final AsyncRetryExecutor<T, C> async(final FailSafeExecutor exec); final AsyncRetryExecutor<T, C> async(final HedgePolicy hedgePolicy, final FailSafeExecutor exec); final AsyncRetryExecutor async(); final RetryPredicate<T, C> getRetryPredicate(final long startTimeNanos, final long deadlineNanos); @Override String toString(); @CheckReturnValue static Builder<T, C> newBuilder(); @CheckReturnValue static Builder<T, C> newBuilder(final Builder<T, C> builder);  }
@Test public void testDefaulPolicyAsync() throws IOException, InterruptedException, TimeoutException { try (LogAssert expect = TestLoggers.sys().expect(PREDICATE_CLASS, Level.DEBUG, 2, LogMatchers.hasMatchingMessage( Matchers.startsWith("Result java.lang.RuntimeException, retrying org.spf4j.failsafe.RetryPolicyTest")))) { try { RetryPolicy.newBuilder() .withDefaultThrowableRetryPredicate() .withRetryOnException(Exception.class, 2) .buildAsync().submit(() -> { throw new RuntimeException(); }).get(); Assert.fail(); } catch (ExecutionException ex) { Assert.assertEquals(RuntimeException.class, ex.getCause().getClass()); expect.assertObservation(); } } }
@Test public void testDefaulPolicyInterruption() throws IOException, InterruptedException, TimeoutException { try { Thread t = Thread.currentThread(); DefaultScheduler.INSTANCE.schedule(() -> t.interrupt(), 1, TimeUnit.SECONDS); RetryPolicy.newBuilder() .withRetryOnException(Exception.class, Integer.MAX_VALUE) .build().run(() -> { throw new IOException(); }, IOException.class); Assert.fail(); } catch (InterruptedException ex) { } }
@Test public void testDefaulPolicyInterruptionAsync() throws IOException, InterruptedException, TimeoutException, ExecutionException { Future<Object> res = RetryPolicy.newBuilder() .withRetryOnException(Exception.class, Integer.MAX_VALUE) .buildAsync().submit(() -> { throw new IOException(); }); try { res.get(100, TimeUnit.MILLISECONDS); Assert.fail(); } catch (TimeoutException tex) { } res.cancel(true); Assert.assertTrue(res.isDone()); try { res.get(100, TimeUnit.MILLISECONDS); Assert.fail(); } catch (CancellationException ex) { LOG.debug("exception detail ", ex); Assert.assertThat(ex.getSuppressed(), Matchers.arrayWithSize(1)); } }
@Test public void testSpecificExceptionRetryPolicy() throws TimeoutException, InterruptedException { LogAssert expect = TestLoggers.sys().expect(LOG.getName(), Level.DEBUG, LogMatchers.hasFormat("encountered")); RetryPolicy<Object, Callable<Object>> policy = RetryPolicy.newBuilder().withExceptionPartialPredicate(IllegalStateException.class, (ex, call) -> { LOG.debug("encountered", ex); return RetryDecision.abort(); }).build(); try { policy.run(() -> { throw new IllegalStateException(); }, RuntimeException.class); Assert.fail(); } catch (IllegalStateException ex) { expect.assertObservation(); } }