private RetryMetrics(String prefix, Iterable<Retry> retries){ requireNonNull(prefix); requireNonNull(retries); retries.forEach(retry -> { String name = retry.getName(); metricRegistry.register(name(prefix, name, SUCCESSFUL_CALLS_WITHOUT_RETRY), (Gauge<Long>) () -> retry.getMetrics().getNumberOfSuccessfulCallsWithoutRetryAttempt()); metricRegistry.register(name(prefix, name, SUCCESSFUL_CALLS_WITH_RETRY), (Gauge<Long>) () -> retry.getMetrics().getNumberOfSuccessfulCallsWithRetryAttempt()); metricRegistry.register(name(prefix, name, FAILED_CALLS_WITHOUT_RETRY), (Gauge<Long>) () -> retry.getMetrics().getNumberOfFailedCallsWithoutRetryAttempt()); metricRegistry.register(name(prefix, name, FAILED_CALLS_WITH_RETRY), (Gauge<Long>) () -> retry.getMetrics().getNumberOfFailedCallsWithRetryAttempt()); }); }
@Override public void bindTo(MeterRegistry registry) { for (Retry retry : retries) { final String name = retry.getName(); Gauge.builder(getName(prefix, name, SUCCESSFUL_CALLS_WITHOUT_RETRY), retry, (cb) -> cb.getMetrics().getNumberOfSuccessfulCallsWithoutRetryAttempt()) .register(registry); Gauge.builder(getName(prefix, name, SUCCESSFUL_CALLS_WITH_RETRY), retry, (cb) -> cb.getMetrics().getNumberOfSuccessfulCallsWithRetryAttempt()) .register(registry); Gauge.builder(getName(prefix, name, FAILED_CALLS_WITHOUT_RETRY), retry, (cb) -> cb.getMetrics().getNumberOfFailedCallsWithoutRetryAttempt()) .register(registry); Gauge.builder(getName(prefix, name, FAILED_CALLS_WITH_RETRY), retry, (cb) -> cb.getMetrics().getNumberOfFailedCallsWithRetryAttempt()) .register(registry); } } }
@Test public void testDecorateSupplierAndInvokeTwice() { // Given the HelloWorldService throws an exception BDDMockito.given(helloWorldService.returnHelloWorld()) .willThrow(new WebServiceException("BAM!")) .willReturn("Hello world") .willThrow(new WebServiceException("BAM!")) .willReturn("Hello world"); // Create a Retry with default configuration Retry retry = Retry.ofDefaults("id"); // Decorate the invocation of the HelloWorldService Supplier<String> supplier = Retry.decorateSupplier(retry, helloWorldService::returnHelloWorld); // When String result = supplier.get(); String result2 = supplier.get(); // Then the helloWorldService should be invoked 2 times BDDMockito.then(helloWorldService).should(Mockito.times(4)).returnHelloWorld(); assertThat(result).isEqualTo("Hello world"); assertThat(result2).isEqualTo("Hello world"); assertThat(sleptTime).isEqualTo(RetryConfig.DEFAULT_WAIT_DURATION * 2); assertThat(retry.getMetrics().getNumberOfSuccessfulCallsWithRetryAttempt()).isEqualTo(2); }
@Test public void shouldReturnAfterThreeAttemptsAndRecover() { // Given the HelloWorldService throws an exception BDDMockito.given(helloWorldService.returnHelloWorld()).willThrow(new WebServiceException("BAM!")); // Create a Retry with default configuration Retry retry = Retry.ofDefaults("id"); // Decorate the invocation of the HelloWorldService CheckedFunction0<String> retryableSupplier = Retry .decorateCheckedSupplier(retry, helloWorldService::returnHelloWorld); // When Try<String> result = Try.of(retryableSupplier).recover((throwable) -> "Hello world from recovery function"); assertThat(retry.getMetrics().getNumberOfFailedCallsWithRetryAttempt()).isEqualTo(1); // Then the helloWorldService should be invoked 3 times BDDMockito.then(helloWorldService).should(Mockito.times(3)).returnHelloWorld(); // and the returned exception should be of type RuntimeException assertThat(result.get()).isEqualTo("Hello world from recovery function"); assertThat(sleptTime).isEqualTo(RetryConfig.DEFAULT_WAIT_DURATION * 2); }
@Test public void shouldNotRetryFromPredicateUsingSingle() { //Given RetryConfig config = RetryConfig.custom() .retryOnException(t -> t instanceof IOException) .maxAttempts(3).build(); Retry retry = Retry.of("testName", config); given(helloWorldService.returnHelloWorld()) .willThrow(new WebServiceException("BAM!")); //When Single.fromCallable(helloWorldService::returnHelloWorld) .compose(RetryTransformer.of(retry)) .test() .assertError(WebServiceException.class) .assertNotComplete() .assertSubscribed(); //Then BDDMockito.then(helloWorldService).should(Mockito.times(1)).returnHelloWorld(); Retry.Metrics metrics = retry.getMetrics(); assertThat(metrics.getNumberOfFailedCallsWithoutRetryAttempt()).isEqualTo(1); assertThat(metrics.getNumberOfFailedCallsWithRetryAttempt()).isEqualTo(0); }
@Test public void shouldNotRetryFromPredicateUsingObservable() { //Given RetryConfig config = RetryConfig.custom() .retryOnException(t -> t instanceof IOException) .maxAttempts(3).build(); Retry retry = Retry.of("testName", config); given(helloWorldService.returnHelloWorld()) .willThrow(new WebServiceException("BAM!")); //When Observable.fromCallable(helloWorldService::returnHelloWorld) .compose(RetryTransformer.of(retry)) .test() .assertError(WebServiceException.class) .assertNotComplete() .assertSubscribed(); //Then BDDMockito.then(helloWorldService).should(Mockito.times(1)).returnHelloWorld(); Retry.Metrics metrics = retry.getMetrics(); assertThat(metrics.getNumberOfFailedCallsWithoutRetryAttempt()).isEqualTo(1); assertThat(metrics.getNumberOfFailedCallsWithRetryAttempt()).isEqualTo(0); }
@Test public void shouldNotRetryFromPredicateUsingFlowable() { //Given RetryConfig config = RetryConfig.custom() .retryOnException(t -> t instanceof IOException) .maxAttempts(3).build(); Retry retry = Retry.of("testName", config); given(helloWorldService.returnHelloWorld()) .willThrow(new WebServiceException("BAM!")); //When Flowable.fromCallable(helloWorldService::returnHelloWorld) .compose(RetryTransformer.of(retry)) .test() .assertError(WebServiceException.class) .assertNotComplete() .assertSubscribed(); //Then BDDMockito.then(helloWorldService).should(Mockito.times(1)).returnHelloWorld(); Retry.Metrics metrics = retry.getMetrics(); assertThat(metrics.getNumberOfFailedCallsWithoutRetryAttempt()).isEqualTo(1); assertThat(metrics.getNumberOfFailedCallsWithRetryAttempt()).isEqualTo(0); }
Retry.Metrics metrics = retry.getMetrics();
@Test public void shouldReturnOnErrorUsingFlowable() { //Given RetryConfig config = RetryConfig.ofDefaults(); Retry retry = Retry.of("testName", config); RetryTransformer<Object> retryTransformer = RetryTransformer.of(retry); given(helloWorldService.returnHelloWorld()) .willThrow(new WebServiceException("BAM!")); //When Flowable.fromCallable(helloWorldService::returnHelloWorld) .compose(retryTransformer) .test() .assertError(WebServiceException.class) .assertNotComplete() .assertSubscribed(); Flowable.fromCallable(helloWorldService::returnHelloWorld) .compose(retryTransformer) .test() .assertError(WebServiceException.class) .assertNotComplete() .assertSubscribed(); //Then BDDMockito.then(helloWorldService).should(Mockito.times(6)).returnHelloWorld(); Retry.Metrics metrics = retry.getMetrics(); assertThat(metrics.getNumberOfFailedCallsWithRetryAttempt()).isEqualTo(2); assertThat(metrics.getNumberOfFailedCallsWithoutRetryAttempt()).isEqualTo(0); }
@Test public void shouldReturnOnErrorUsingObservable() { //Given RetryConfig config = RetryConfig.ofDefaults(); Retry retry = Retry.of("testName", config); RetryTransformer<Object> retryTransformer = RetryTransformer.of(retry); given(helloWorldService.returnHelloWorld()) .willThrow(new WebServiceException("BAM!")); //When Observable.fromCallable(helloWorldService::returnHelloWorld) .compose(retryTransformer) .test() .assertError(WebServiceException.class) .assertNotComplete() .assertSubscribed(); Observable.fromCallable(helloWorldService::returnHelloWorld) .compose(retryTransformer) .test() .assertError(WebServiceException.class) .assertNotComplete() .assertSubscribed(); //Then BDDMockito.then(helloWorldService).should(Mockito.times(6)).returnHelloWorld(); Retry.Metrics metrics = retry.getMetrics(); assertThat(metrics.getNumberOfFailedCallsWithRetryAttempt()).isEqualTo(2); assertThat(metrics.getNumberOfFailedCallsWithoutRetryAttempt()).isEqualTo(0); }
@Test public void shouldReturnOnErrorUsingSingle() { //Given RetryConfig config = RetryConfig.ofDefaults(); Retry retry = Retry.of("testName", config); RetryTransformer<Object> retryTransformer = RetryTransformer.of(retry); given(helloWorldService.returnHelloWorld()) .willThrow(new WebServiceException("BAM!")); //When Single.fromCallable(helloWorldService::returnHelloWorld) .compose(retryTransformer) .test() .assertError(WebServiceException.class) .assertNotComplete() .assertSubscribed(); Single.fromCallable(helloWorldService::returnHelloWorld) .compose(retryTransformer) .test() .assertError(WebServiceException.class) .assertNotComplete() .assertSubscribed(); //Then BDDMockito.then(helloWorldService).should(Mockito.times(6)).returnHelloWorld(); Retry.Metrics metrics = retry.getMetrics(); assertThat(metrics.getNumberOfFailedCallsWithRetryAttempt()).isEqualTo(2); assertThat(metrics.getNumberOfFailedCallsWithoutRetryAttempt()).isEqualTo(0); }
@Test public void shouldReturnOnCompleteUsingObservable() { //Given RetryConfig config = RetryConfig.ofDefaults(); Retry retry = Retry.of("testName", config); RetryTransformer<Object> retryTransformer = RetryTransformer.of(retry); given(helloWorldService.returnHelloWorld()) .willThrow(new WebServiceException("BAM!")); //When Observable.fromCallable(helloWorldService::returnHelloWorld) .compose(retryTransformer) .test() .assertError(WebServiceException.class) .assertNotComplete() .assertSubscribed(); Observable.fromCallable(helloWorldService::returnHelloWorld) .compose(retryTransformer) .test() .assertError(WebServiceException.class) .assertNotComplete() .assertSubscribed(); //Then BDDMockito.then(helloWorldService).should(Mockito.times(6)).returnHelloWorld(); Retry.Metrics metrics = retry.getMetrics(); assertThat(metrics.getNumberOfFailedCallsWithRetryAttempt()).isEqualTo(2); assertThat(metrics.getNumberOfFailedCallsWithoutRetryAttempt()).isEqualTo(0); }
@Test public void shouldReturnOnCompleteUsingFlowable() { //Given RetryConfig config = RetryConfig.ofDefaults(); Retry retry = Retry.of("testName", config); RetryTransformer<Object> retryTransformer = RetryTransformer.of(retry); given(helloWorldService.returnHelloWorld()) .willThrow(new WebServiceException("BAM!")); //When Flowable.fromCallable(helloWorldService::returnHelloWorld) .compose(retryTransformer) .test() .assertError(WebServiceException.class) .assertNotComplete() .assertSubscribed(); Flowable.fromCallable(helloWorldService::returnHelloWorld) .compose(retryTransformer) .test() .assertError(WebServiceException.class) .assertNotComplete() .assertSubscribed(); //Then BDDMockito.then(helloWorldService).should(Mockito.times(6)).returnHelloWorld(); Retry.Metrics metrics = retry.getMetrics(); assertThat(metrics.getNumberOfFailedCallsWithRetryAttempt()).isEqualTo(2); assertThat(metrics.getNumberOfFailedCallsWithoutRetryAttempt()).isEqualTo(0); }
private RetryMetrics(String prefix, Iterable<Retry> retries){ requireNonNull(prefix); requireNonNull(retries); retries.forEach(retry -> { String name = retry.getName(); metricRegistry.register(name(prefix, name, SUCCESSFUL_CALLS_WITHOUT_RETRY), (Gauge<Long>) () -> retry.getMetrics().getNumberOfSuccessfulCallsWithoutRetryAttempt()); metricRegistry.register(name(prefix, name, SUCCESSFUL_CALLS_WITH_RETRY), (Gauge<Long>) () -> retry.getMetrics().getNumberOfSuccessfulCallsWithRetryAttempt()); metricRegistry.register(name(prefix, name, FAILED_CALLS_WITHOUT_RETRY), (Gauge<Long>) () -> retry.getMetrics().getNumberOfFailedCallsWithoutRetryAttempt()); metricRegistry.register(name(prefix, name, FAILED_CALLS_WITH_RETRY), (Gauge<Long>) () -> retry.getMetrics().getNumberOfFailedCallsWithRetryAttempt()); }); }