private RetryStrategy applyContext(final RetryContext retryContext) { final Optional<RetryRule> matchingRetryRuleOption = findMatchingRetryRule(retryRules, retryContext); final RetryRule matchingRetryRule = matchingRetryRuleOption .orElseGet(() -> RetryRule.of(RetryPredicate.ofAlwaysTrue(), RetryAction.ofGiveUpAndSendLatestException())); return matchingRetryRule.apply(retryContext); }
@Test public void statusCodesPredicate() { final RetryPredicate predicate = RetryPredicate.ofMatchingStatusCodes(SERVICE_UNAVAILABLE_503, GATEWAY_TIMEOUT_504); assertThat(predicate.test(getRetryContext(new GatewayTimeoutException()))).isTrue(); assertThat(predicate.test(getRetryContext(new BadRequestException("")))).isFalse(); }
/** * Creates a predicate which matches specific status codes for {@link SphereServiceException}s. * * {@include.example io.sphere.sdk.client.retry.RetryBadGatewayExample} * * @param first the mandatory status code which might match * @param more varargs parameter for more status codes to match * @return predicate */ static RetryPredicate ofMatchingStatusCodes(final int first, final int ... more) { final Predicate<Integer> predicate = statusCode -> IntStream.concat(IntStream.of(first), IntStream.of(more)).anyMatch(i -> i == statusCode); return ofMatchingStatusCodes(predicate); }
public static SphereClient ofRetry(final SphereClient delegate) { final int maxAttempts = 5; final List<RetryRule> retryRules = singletonList(RetryRule.of( RetryPredicate.ofMatchingStatusCodes(BAD_GATEWAY_502, SERVICE_UNAVAILABLE_503, GATEWAY_TIMEOUT_504), RetryAction.ofScheduledRetry(maxAttempts, context -> Duration.ofSeconds(context.getAttempt() * 2))) ); return RetrySphereClientDecorator.of(delegate, retryRules); } }
private List<RetryRule> createRules() { final Predicate<RetryContext> isFatal = r -> { final Throwable latestError = r.getLatestError(); final boolean unknownHost = latestError instanceof HttpException && latestError != null && latestError instanceof UnknownHostException; final boolean unauthorized = latestError instanceof UnauthorizedException; return unknownHost || unauthorized; }; final RetryRule fatalRetryRule = RetryRule.of(isFatal, RetryAction.ofShutdownServiceAndSendLatestException()); final RetryRule retryScheduledRetryRule = RetryRule.of(RetryPredicate.ofAlwaysTrue(), RetryAction.ofScheduledRetry(2, retryContext -> Duration.ofMillis(retryContext.getAttempt() * retryContext.getAttempt() * 50))); return asList(fatalRetryRule, retryScheduledRetryRule); }
@Test public void statusCodesVarargs() { final RetryPredicate predicate = RetryPredicate.ofMatchingStatusCodes(SERVICE_UNAVAILABLE_503, GATEWAY_TIMEOUT_504); assertThat(predicate.test(getRetryContext(new GatewayTimeoutException()))).isTrue(); assertThat(predicate.test(getRetryContext(new BadRequestException("")))).isFalse(); }
private List<RetryRule> createRules() { final Predicate<RetryContext> isFatal = r -> { final Throwable latestError = r.getLatestError(); final boolean unknownHost = latestError instanceof HttpException && latestError != null && latestError instanceof UnknownHostException; final boolean unauthorized = latestError instanceof UnauthorizedException; return unknownHost || unauthorized; }; final RetryRule fatalRetryRule = RetryRule.of(isFatal, RetryAction.ofShutdownServiceAndSendLatestException()); final RetryRule retryScheduledRetryRule = RetryRule.of(RetryPredicate.ofAlwaysTrue(), RetryAction.ofScheduledRetry(2, retryContext -> Duration.ofMillis(retryContext.getAttempt() * retryContext.getAttempt() * 50))); return asList(fatalRetryRule, retryScheduledRetryRule); }
@Test public void immediateRetryRule() throws Exception { try (final Service service = new Failing2TimesServiceImpl()) { final List<RetryRule> retryRules = singletonList(RetryRule.of(RetryPredicate.ofAlwaysTrue(), RetryAction.ofImmediateRetries(3))); try(final AsyncRetrySupervisor supervisor = AsyncRetrySupervisor.of(retryRules)) { final CompletionStage<Integer> bar = supervisor.supervise(service, service::apply, "bar"); assertThat(waitAndGet(bar)).isEqualTo(3); assertThat(service.isClosed()).isFalse(); } } }
@Test public void giveUpAndSendFirstException() throws Exception { try (final Service service = new Failing2TimesServiceImpl()) { final List<RetryRule> retryRules = singletonList(RetryRule.of(RetryPredicate.ofAlwaysTrue(), RetryAction.ofGiveUpAndSendFirstException())); try(final AsyncRetrySupervisor supervisor = AsyncRetrySupervisor.of(retryRules)) { final CompletionStage<Integer> bar = supervisor.supervise(service, service::apply, "bar"); final Throwable throwable = catchThrowable(() -> waitAndGet(bar)); assertThat(throwable.getCause()).hasMessage(Failing2TimesServiceImpl.ERROR_MESSAGE); assertThat(service.isClosed()).isFalse(); } } }
@Test public void scheduledRetry() throws Exception { try (final Service service = new Failing2TimesServiceImpl()) { final RetryAction op = RetryAction.ofScheduledRetry(3, o -> Duration.ofMillis(o.getAttempt() * 100)); final List<RetryRule> retryRules = singletonList(RetryRule.of(RetryPredicate.ofAlwaysTrue(), op)); try(final AsyncRetrySupervisor supervisor = AsyncRetrySupervisor.of(retryRules)) { final CompletionStage<Integer> bar = supervisor.supervise(service, service::apply, "bar"); assertThat(waitAndGet(bar)).isEqualTo(3); assertThat(service.isClosed()).isFalse(); } } }
@Test public void shutdownServiceAndSendFirstException() throws Exception { try (final Service service = new Failing2TimesServiceImpl()) { final List<RetryRule> retryRules = singletonList(RetryRule.of(RetryPredicate.ofAlwaysTrue(), RetryAction.ofShutdownServiceAndSendFirstException())); try(final AsyncRetrySupervisor supervisor = AsyncRetrySupervisor.of(retryRules)) { final CompletionStage<Integer> bar = supervisor.supervise(service, service::apply, "bar"); final Throwable throwable = catchThrowable(() -> waitAndGet(bar)); assertThat(throwable.getCause()).hasMessage(Failing2TimesServiceImpl.ERROR_MESSAGE); Thread.sleep(200); assertThat(service.isClosed()).isTrue(); } } }
@Test public void immediateRetryRuleNonSufficient() throws Exception { try (final Service service = new Failing2TimesServiceImpl()) { final List<RetryRule> retryRules = singletonList(RetryRule.of(RetryPredicate.ofAlwaysTrue(), RetryAction.ofImmediateRetries(1))); try(final AsyncRetrySupervisor supervisor = AsyncRetrySupervisor.of(retryRules)) { final CompletionStage<Integer> bar = supervisor.supervise(service, service::apply, "bar"); final Throwable throwable = catchThrowable(() -> waitAndGet(bar)); assertThat(throwable.getCause()).hasMessage(Failing2TimesServiceImpl.ERROR_MESSAGE); assertThat(service.isClosed()).isFalse(); } } }