From 34183fde236497c65b4230be7889580013857193 Mon Sep 17 00:00:00 2001 From: Brian Reischl Date: Fri, 25 Oct 2019 11:21:10 -0600 Subject: [PATCH 1/4] Update to R4j 1.1.0, and implement Retries --- CHANGELOG.md | 3 +- README.md | 39 +++-- pom.xml | 22 ++- .../resilience4j/Resilience4jBundle.java | 61 ++++++- .../CircuitBreakerConfiguration.java | 164 +++++++++++++----- .../Resilience4jConfiguration.java | 26 +++ .../ConstantIntervalFunctionFactory.java | 30 ++++ .../ExponentialBackoffFunctionFactory.java | 48 +++++ ...ponentialRandomBackoffFunctionFactory.java | 63 +++++++ .../retry/IntervalFunctionFactory.java | 33 ++++ .../RandomizedIntervalFunctionFactory.java | 48 +++++ .../retry/RetryConfiguration.java | 98 +++++++++++ .../resilience4j/Resilience4jBundleTest.java | 106 +++++++++-- src/test/resources/config.yaml | 51 +++++- 14 files changed, 710 insertions(+), 82 deletions(-) create mode 100644 src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/ConstantIntervalFunctionFactory.java create mode 100644 src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/ExponentialBackoffFunctionFactory.java create mode 100644 src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/ExponentialRandomBackoffFunctionFactory.java create mode 100644 src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/IntervalFunctionFactory.java create mode 100644 src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/RandomizedIntervalFunctionFactory.java create mode 100644 src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/RetryConfiguration.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c2d851..b09c955 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). ## [Unreleased] ### Changed -- nothing yet +- Added support for R4j `Retry` +- Updated to R4j 1.1.0. This is a major version bump that has a lot of breaking changes that will be user-visible. See R4j documentation for details. ##[0.0.1] - 2019-03-11 diff --git a/README.md b/README.md index 280ce06..3f1002b 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,9 @@ dropwizard-resilience4j-bundle [![Build Status][build-icon]][build-link] Lightweight integration of Resilience4J into Dropwizard configuration and metrics. Does not provide any other services - actually _using_ -all the Resilience4j stuff is up to you. - -Currently this only supports Circuit Breakers, but supporting [more R4j features is welcome](http://resilience4j.github.io/resilience4j/#_usage_guide). +all the Resilience4j stuff is up to you. The [R4J documentation](https://resilience4j.readme.io/docs) is pretty good. +Currently this only supports Circuit Breakers and Retries, but supporting [more R4j features is welcome](http://resilience4j.github.io/resilience4j/#_usage_guide). User Guide ============================== @@ -29,10 +28,21 @@ resilience4j: circuitBreakers: - name: myFancyCircuitBreaker waitDurationInOpenState: 30s - ringBufferSizeInClosedState: 30 + failureRateThreshold: 10 ## Add as many as you want ## All parameters are optional except `name`, defaults are documented in CircuitBreakerConfiguration.java ##- name: anotherCircuitBreaker + retryConfigurations: + - name: exponentialRandomizedBackoffRetry + maxAttempts: 4 + intervalFunction: + type: exponentialRandomBackoff + initialInterval: 10ms + multiplier: 2.5 + randomizationFactor: 0.5 + ## Add as many as you want + ## most parameters are optional, but `intervalFunction` is required. Several are available, see `IntervalFunctionFactory` for full list, + ## but currently: constant, randomized, exponentialBackoff, exponentialRandomBackoff ``` Add to your application's Config class: @@ -41,21 +51,28 @@ Add to your application's Config class: private Resilience4jConfiguration resilience4j; ``` -The circuit breakers are automatically wired into Dropwizard Metrics, and also [into HK2 using the name from the YAML](src/main/java/com/homeaway/dropwizard/bundle/resilience4j/Resilience4jBundle.java#L93). +Configured R4J objects are automatically wired into Dropwizard Metrics, and also [into HK2 using the name from the YAML](src/main/java/com/homeaway/dropwizard/bundle/resilience4j/Resilience4jBundle.java#L93). You can also retrieve them from the configuration class... ```java val breaker = myAppConfig.getResilience4j().getCircuitBreakerRegistry().circuitBreaker("myFancyCircuitBreaker"); +val retry = myAppConfig.getResilience4j().getRetryRegistry().retry("myFancyRetry"); ``` -If you want to configure the CircuitBreakers in code before they are created, you can pass a handler into the bundle when it's constructed. +If you want to configure the objects in code before they are created, you can pass a handler into the bundle when it's constructed. ```java @Override public void initialize(Bootstrap bootstrap) { - bootstrap.addBundle(new Resilience4jBundle<>(RatesEngineConfiguration::getResilience4j, (breakerName, breakerBuilder) -> { - //breakerName is what was configured in YAML - //breakerBuilder can be modified as desired - breakerBuilder.ignoreExceptions(IOException.class); - })); + bootstrap.addBundle(new Resilience4jBundle<>(TestConfiguration::getResilience4j, + (breakerName, breakerBuilder) -> { + //breakerName is what was configured in YAML + //breakerBuilder can be modified as desired + breakerBuilder.ignoreExceptions(IOException.class); + }, + (retryName, retryBuilder) -> { + //retryName is what was configured in YAML + //retryBuilder can be modified as desired + retryBuilder.retryOnResult(myRetryPredicate); + })); } ``` diff --git a/pom.xml b/pom.xml index 670cca6..7fbbbf1 100644 --- a/pom.xml +++ b/pom.xml @@ -45,9 +45,10 @@ 2.5.0-b32 4.12 2.0.1 - 0.13.1 + 1.1.0 + 1.7.25 1.1.0.Final - 0.9.2 + 0.10.0 @@ -64,6 +65,10 @@ + + com.fasterxml.jackson.core + jackson-annotations + com.google.code.findbugs jsr305 @@ -72,6 +77,10 @@ io.dropwizard dropwizard-core + + io.dropwizard + dropwizard-jackson + io.dropwizard dropwizard-jersey @@ -94,6 +103,11 @@ resilience4j-metrics ${resilience4j.version} + + io.github.resilience4j + resilience4j-retry + ${resilience4j.version} + io.vavr vavr @@ -109,6 +123,10 @@ hk2-api ${hk2-api.version} + + org.hibernate + hibernate-validator + diff --git a/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/Resilience4jBundle.java b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/Resilience4jBundle.java index 5b74a09..8e6d517 100644 --- a/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/Resilience4jBundle.java +++ b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/Resilience4jBundle.java @@ -19,11 +19,12 @@ import java.util.List; import java.util.function.BiConsumer; import java.util.function.Function; -import javax.annotation.Nonnull; import org.glassfish.hk2.utilities.binding.AbstractBinder; + import com.homeaway.dropwizard.bundle.resilience4j.configuration.CircuitBreakerConfiguration; import com.homeaway.dropwizard.bundle.resilience4j.configuration.Resilience4jConfiguration; +import com.homeaway.dropwizard.bundle.resilience4j.configuration.retry.RetryConfiguration; import io.dropwizard.ConfiguredBundle; import io.dropwizard.setup.Bootstrap; @@ -32,7 +33,13 @@ import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig; import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry; import io.github.resilience4j.circuitbreaker.internal.InMemoryCircuitBreakerRegistry; +import io.github.resilience4j.core.lang.NonNull; import io.github.resilience4j.metrics.CircuitBreakerMetrics; +import io.github.resilience4j.metrics.RetryMetrics; +import io.github.resilience4j.retry.Retry; +import io.github.resilience4j.retry.RetryConfig; +import io.github.resilience4j.retry.RetryRegistry; +import io.github.resilience4j.retry.internal.InMemoryRetryRegistry; public class Resilience4jBundle implements ConfiguredBundle { @@ -40,14 +47,15 @@ public class Resilience4jBundle implements ConfiguredBundle { private final BiConsumer circuitBreakerConfigurator; - private static final BiConsumer NOOP_CONFIGURATOR = (a, b) -> { - }; + private final BiConsumer retryConfigurator; /** * Create a new bundle */ - public Resilience4jBundle(@Nonnull Function resilienceConfiguratorFunction) { - this(resilienceConfiguratorFunction, NOOP_CONFIGURATOR); + public Resilience4jBundle(@NonNull Function resilienceConfiguratorFunction) { + this(resilienceConfiguratorFunction, + noOpConfigurator(), + noOpConfigurator()); } /** @@ -55,10 +63,12 @@ public Resilience4jBundle(@Nonnull Function resili * * @param circuitBreakerConfigurator A function that will be passed the name and builder for each circuit breaker before it is created */ - public Resilience4jBundle(@Nonnull Function resilienceConfiguratorFunction, - @Nonnull BiConsumer circuitBreakerConfigurator) { + public Resilience4jBundle(@NonNull Function resilienceConfiguratorFunction, + @NonNull BiConsumer circuitBreakerConfigurator, + @NonNull BiConsumer retryConfigurator) { this.resiliencyConfiguratorFunction = resilienceConfiguratorFunction; this.circuitBreakerConfigurator = circuitBreakerConfigurator; + this.retryConfigurator = retryConfigurator; } @Override @@ -100,5 +110,42 @@ protected void configure() { } }); } + + final List retryConfigs = config.getRetryConfigurations(); + if (retryConfigs != null & !retryConfigs.isEmpty()) { + final InMemoryRetryRegistry retryRegistry = new InMemoryRetryRegistry(); + for (final RetryConfiguration cfg : retryConfigs) { + final RetryConfig.Builder r4jConfigBuilder = cfg.toResilience4jConfigBuilder(); + retryConfigurator.accept(cfg.getName(), r4jConfigBuilder); + retryRegistry.retry(cfg.getName(), r4jConfigBuilder.build()); + } + + config.setRetryRegistry(retryRegistry); + + //Register retry metrics with Dropwizard metrics + environment.metrics().registerAll(RetryMetrics.ofRetryRegistry(retryRegistry)); + + //Register retryers with Jersey for injection, if anybody wants to use it + environment.jersey().register(new AbstractBinder() { + + @Override + protected void configure() { + //Bind the registry + bind(retryRegistry).to(RetryRegistry.class); + + //Bind each of the retryers + for (final Retry retryer : retryRegistry.getAllRetries()) { + bind(retryer).to(Retry.class).named(retryer.getName()); + } + } + }); + } + } + + private static final BiConsumer NOOP_CONFIGURATOR = (a, b) -> { + }; + + private static BiConsumer noOpConfigurator() { + return (BiConsumer) NOOP_CONFIGURATOR; } } diff --git a/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/CircuitBreakerConfiguration.java b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/CircuitBreakerConfiguration.java index e9de838..c96adf8 100644 --- a/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/CircuitBreakerConfiguration.java +++ b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/CircuitBreakerConfiguration.java @@ -16,6 +16,8 @@ package com.homeaway.dropwizard.bundle.resilience4j.configuration; +import com.fasterxml.jackson.annotation.JsonProperty; + import io.dropwizard.util.Duration; import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig; @@ -27,6 +29,7 @@ public class CircuitBreakerConfiguration { /** * Name for this circuit breaker for use in the registry */ + @JsonProperty private String name; /** @@ -35,35 +38,16 @@ public class CircuitBreakerConfiguration { *
* See also {@link io.github.resilience4j.circuitbreaker.CircuitBreakerConfig.Builder#failureRateThreshold}. */ + @JsonProperty private float failureRateThreshold = 50; - /** - * Configures the size of the ring buffer when the CircuitBreaker is half open. The CircuitBreaker stores the success/failure - * success / failure status of the latest calls in a ring buffer. For example, if {@code ringBufferSizeInClosedState} is 10, then - * at least 10 calls must be evaluated, before the failure rate can be calculated. If only 9 calls have been evaluated the - * CircuitBreaker will not trip back to closed or open even if all 9 calls have failed. The size must be greater than 10. Default - * size is 10. - *
- * See also {@link io.github.resilience4j.circuitbreaker.CircuitBreakerConfig.Builder#ringBufferSizeInHalfOpenState}. - */ - private int ringBufferSizeInHalfOpenState = 10; - - /** - * Configures the size of the ring buffer when the CircuitBreaker is closed. The CircuitBreaker stores the success/failure - * success / failure status of the latest calls in a ring buffer. For example, if {@code ringBufferSizeInClosedState} is 100, - * then at least 100 calls must be evaluated, before the failure rate can be calculated. If only 99 calls have been evaluated the - * CircuitBreaker will not trip open even if all 99 calls have failed. The size must be greater than 0. Default size is 100. - *
- * See also {@link io.github.resilience4j.circuitbreaker.CircuitBreakerConfig.Builder#ringBufferSizeInClosedState}. - */ - private int ringBufferSizeInClosedState = 100; - /** * Configures the wait duration which specifies how long the CircuitBreaker should stay open, before it switches to half open. * Default value is 60000 milliseconds. *
* See also {@link io.github.resilience4j.circuitbreaker.CircuitBreakerConfig.Builder#waitDurationInOpenState}. */ + @JsonProperty private Duration waitDurationInOpenState = Duration.seconds(60); /** @@ -71,20 +55,50 @@ public class CircuitBreakerConfiguration { * Default value is {c}true{/c} * See also {@link io.github.resilience4j.circuitbreaker.CircuitBreakerConfig.Builder#enableAutomaticTransitionFromOpenToHalfOpen}. */ + @JsonProperty private Boolean enableAutomaticTransitionFromOpenToHalfOpen = true; - public CircuitBreakerConfig.Builder toResilience4jConfigBuilder() { - CircuitBreakerConfig.Builder builder = CircuitBreakerConfig.custom() - .waitDurationInOpenState(java.time.Duration.ofNanos(this.waitDurationInOpenState.toNanoseconds())) - .ringBufferSizeInClosedState(this.ringBufferSizeInClosedState) - .ringBufferSizeInHalfOpenState(this.ringBufferSizeInHalfOpenState) - .failureRateThreshold(this.failureRateThreshold); + @JsonProperty + private int minimumNumberOfCalls = CircuitBreakerConfig.DEFAULT_MINIMUM_NUMBER_OF_CALLS; + + @JsonProperty + private int permittedNumberOfCallsInHalfOpenState = CircuitBreakerConfig.DEFAULT_PERMITTED_CALLS_IN_HALF_OPEN_STATE; + + @JsonProperty + private int slidingWindowSize = CircuitBreakerConfig.DEFAULT_SLIDING_WINDOW_SIZE; + + @JsonProperty + private CircuitBreakerConfig.SlidingWindowType slidingWindowType = CircuitBreakerConfig.DEFAULT_SLIDING_WINDOW_TYPE; + + @JsonProperty + private Duration slowCallDurationThreshold = Duration.seconds(CircuitBreakerConfig.DEFAULT_SLOW_CALL_DURATION_THRESHOLD); + + @JsonProperty + private float slowCallRateThreshold = CircuitBreakerConfig.DEFAULT_SLOW_CALL_RATE_THRESHOLD; + + @JsonProperty + private boolean writableStackTraceEnabled = CircuitBreakerConfig.DEFAULT_WRITABLE_STACK_TRACE_ENABLED; - if (enableAutomaticTransitionFromOpenToHalfOpen) { - builder.enableAutomaticTransitionFromOpenToHalfOpen(); - } + @JsonProperty + private Class[] ignoreExceptions = new Class[0]; - return builder; + @JsonProperty + private Class[] recordExceptions = new Class[0]; + + public CircuitBreakerConfig.Builder toResilience4jConfigBuilder() { + return CircuitBreakerConfig.custom() + .waitDurationInOpenState(java.time.Duration.ofNanos(this.waitDurationInOpenState.toNanoseconds())) + .automaticTransitionFromOpenToHalfOpenEnabled(enableAutomaticTransitionFromOpenToHalfOpen) + .failureRateThreshold(this.failureRateThreshold) + .minimumNumberOfCalls(minimumNumberOfCalls) + .permittedNumberOfCallsInHalfOpenState(permittedNumberOfCallsInHalfOpenState) + .slidingWindowSize(slidingWindowSize) + .slidingWindowType(slidingWindowType) + .slowCallDurationThreshold(java.time.Duration.ofNanos(slowCallDurationThreshold.toNanoseconds())) + .slowCallRateThreshold(slowCallRateThreshold) + .writableStackTraceEnabled(writableStackTraceEnabled) + .ignoreExceptions(ignoreExceptions) + .recordExceptions(recordExceptions); } public String getName() { @@ -103,22 +117,6 @@ public float getFailureRateThreshold() { return failureRateThreshold; } - public void setRingBufferSizeInHalfOpenState(int ringBufferSizeInHalfOpenState) { - this.ringBufferSizeInHalfOpenState = ringBufferSizeInHalfOpenState; - } - - public int getRingBufferSizeInHalfOpenState() { - return ringBufferSizeInHalfOpenState; - } - - public int getRingBufferSizeInClosedState() { - return ringBufferSizeInClosedState; - } - - public void setRingBufferSizeInClosedState(int ringBufferSizeInClosedState) { - this.ringBufferSizeInClosedState = ringBufferSizeInClosedState; - } - public Duration getWaitDurationInOpenState() { return waitDurationInOpenState; } @@ -134,4 +132,76 @@ public Boolean getEnableAutomaticTransitionFromOpenToHalfOpen() { public void setEnableAutomaticTransitionFromOpenToHalfOpen(Boolean enableAutomaticTransitionFromOpenToHalfOpen) { this.enableAutomaticTransitionFromOpenToHalfOpen = enableAutomaticTransitionFromOpenToHalfOpen; } + + public int getMinimumNumberOfCalls() { + return minimumNumberOfCalls; + } + + public void setMinimumNumberOfCalls(int minimumNumberOfCalls) { + this.minimumNumberOfCalls = minimumNumberOfCalls; + } + + public int getPermittedNumberOfCallsInHalfOpenState() { + return permittedNumberOfCallsInHalfOpenState; + } + + public void setPermittedNumberOfCallsInHalfOpenState(int permittedNumberOfCallsInHalfOpenState) { + this.permittedNumberOfCallsInHalfOpenState = permittedNumberOfCallsInHalfOpenState; + } + + public int getSlidingWindowSize() { + return slidingWindowSize; + } + + public void setSlidingWindowSize(int slidingWindowSize) { + this.slidingWindowSize = slidingWindowSize; + } + + public CircuitBreakerConfig.SlidingWindowType getSlidingWindowType() { + return slidingWindowType; + } + + public void setSlidingWindowType(CircuitBreakerConfig.SlidingWindowType slidingWindowType) { + this.slidingWindowType = slidingWindowType; + } + + public Duration getSlowCallDurationThreshold() { + return slowCallDurationThreshold; + } + + public void setSlowCallDurationThreshold(Duration slowCallDurationThreshold) { + this.slowCallDurationThreshold = slowCallDurationThreshold; + } + + public float getSlowCallRateThreshold() { + return slowCallRateThreshold; + } + + public void setSlowCallRateThreshold(float slowCallRateThreshold) { + this.slowCallRateThreshold = slowCallRateThreshold; + } + + public boolean isWritableStackTraceEnabled() { + return writableStackTraceEnabled; + } + + public void setWritableStackTraceEnabled(boolean writableStackTraceEnabled) { + this.writableStackTraceEnabled = writableStackTraceEnabled; + } + + public Class[] getIgnoreExceptions() { + return ignoreExceptions; + } + + public void setIgnoreExceptions(Class[] ignoreExceptions) { + this.ignoreExceptions = ignoreExceptions; + } + + public Class[] getRecordExceptions() { + return recordExceptions; + } + + public void setRecordExceptions(Class[] recordExceptions) { + this.recordExceptions = recordExceptions; + } } diff --git a/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/Resilience4jConfiguration.java b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/Resilience4jConfiguration.java index 6d5754b..dd78081 100644 --- a/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/Resilience4jConfiguration.java +++ b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/Resilience4jConfiguration.java @@ -21,7 +21,10 @@ import javax.annotation.Nullable; import javax.validation.Valid; +import com.homeaway.dropwizard.bundle.resilience4j.configuration.retry.RetryConfiguration; + import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry; +import io.github.resilience4j.retry.RetryRegistry; /** * Resilience4j configuration @@ -35,8 +38,14 @@ public class Resilience4jConfiguration { @Valid private List circuitBreakers; + @Nullable + @Valid + private List retryConfigurations; + public CircuitBreakerRegistry circuitBreakerRegistry; + public RetryRegistry retryRegistry; + @Nullable public List getCircuitBreakers() { return circuitBreakers; @@ -53,4 +62,21 @@ public CircuitBreakerRegistry getCircuitBreakerRegistry() { public void setCircuitBreakerRegistry(CircuitBreakerRegistry circuitBreakerRegistry) { this.circuitBreakerRegistry = circuitBreakerRegistry; } + + @Nullable + public List getRetryConfigurations() { + return retryConfigurations; + } + + public void setRetryConfigurations(@Nullable List retryConfigurations) { + this.retryConfigurations = retryConfigurations; + } + + public RetryRegistry getRetryRegistry() { + return retryRegistry; + } + + public void setRetryRegistry(RetryRegistry retryRegistry) { + this.retryRegistry = retryRegistry; + } } diff --git a/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/ConstantIntervalFunctionFactory.java b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/ConstantIntervalFunctionFactory.java new file mode 100644 index 0000000..ac7100e --- /dev/null +++ b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/ConstantIntervalFunctionFactory.java @@ -0,0 +1,30 @@ +package com.homeaway.dropwizard.bundle.resilience4j.configuration.retry; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeName; + +import io.dropwizard.util.Duration; +import io.github.resilience4j.retry.IntervalFunction; + +@JsonTypeName("constant") +public class ConstantIntervalFunctionFactory implements IntervalFunctionFactory { + + /** + * Wait interval. Minimum value is 10 milliseconds. Default is R4j default, currently 500ms. + */ + @JsonProperty + private Duration initialInterval = Duration.milliseconds(IntervalFunction.DEFAULT_INITIAL_INTERVAL); + + @Override + public IntervalFunction build() { + return IntervalFunction.of(initialInterval.toMilliseconds()); + } + + public Duration getInitialInterval() { + return initialInterval; + } + + public void setInitialInterval(Duration initialInterval) { + this.initialInterval = initialInterval; + } +} diff --git a/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/ExponentialBackoffFunctionFactory.java b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/ExponentialBackoffFunctionFactory.java new file mode 100644 index 0000000..7f17218 --- /dev/null +++ b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/ExponentialBackoffFunctionFactory.java @@ -0,0 +1,48 @@ +package com.homeaway.dropwizard.bundle.resilience4j.configuration.retry; + +import javax.validation.constraints.NotNull; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeName; + +import io.dropwizard.util.Duration; +import io.github.resilience4j.retry.IntervalFunction; + +@JsonTypeName("exponentialBackoff") +public class ExponentialBackoffFunctionFactory implements IntervalFunctionFactory { + + /** + * Amount to multiply by at each iteration. Must be greater than 1. Default value is 1.5. + */ + @JsonProperty + @NotNull + private double multiplier = IntervalFunction.DEFAULT_MULTIPLIER; + + /** + * Initial interval. Minimum value is 10 milliseconds. Default is R4j default, currently 500ms. + */ + @JsonProperty + @NotNull + private Duration initialInterval = Duration.milliseconds(IntervalFunction.DEFAULT_INITIAL_INTERVAL); + + @Override + public IntervalFunction build() { + return IntervalFunction.ofExponentialBackoff(initialInterval.toMilliseconds(), multiplier); + } + + public double getMultiplier() { + return multiplier; + } + + public void setMultiplier(double multiplier) { + this.multiplier = multiplier; + } + + public Duration getInitialInterval() { + return initialInterval; + } + + public void setInitialInterval(Duration initialInterval) { + this.initialInterval = initialInterval; + } +} diff --git a/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/ExponentialRandomBackoffFunctionFactory.java b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/ExponentialRandomBackoffFunctionFactory.java new file mode 100644 index 0000000..fabdfde --- /dev/null +++ b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/ExponentialRandomBackoffFunctionFactory.java @@ -0,0 +1,63 @@ +package com.homeaway.dropwizard.bundle.resilience4j.configuration.retry; + +import javax.validation.constraints.NotNull; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeName; + +import io.dropwizard.util.Duration; +import io.github.resilience4j.retry.IntervalFunction; + +@JsonTypeName("exponentialRandomBackoff") +public class ExponentialRandomBackoffFunctionFactory implements IntervalFunctionFactory { + + /** + * Amount to multiply by at each iteration. Must be greater than 1. Default value is 1.5. + */ + @JsonProperty + @NotNull + private double multiplier = IntervalFunction.DEFAULT_MULTIPLIER; + + /** + * Randomization multiplier. Must be in range [0.0d, 1.0d). Default value is 0.5. + */ + @JsonProperty + @NotNull + private double randomizationFactor = IntervalFunction.DEFAULT_RANDOMIZATION_FACTOR; + + /** + * Initial interval. Minimum value is 10 milliseconds. Default is R4j default, currently 500ms. + */ + @JsonProperty + @NotNull + private Duration initialInterval = Duration.milliseconds(IntervalFunction.DEFAULT_INITIAL_INTERVAL); + + @Override + public IntervalFunction build() { + return IntervalFunction.ofExponentialRandomBackoff(initialInterval.toMilliseconds(), multiplier, randomizationFactor); + } + + public double getMultiplier() { + return multiplier; + } + + public void setMultiplier(double multiplier) { + this.multiplier = multiplier; + } + + public double getRandomizationFactor() { + return randomizationFactor; + } + + public void setRandomizationFactor(double randomizationFactor) { + this.randomizationFactor = randomizationFactor; + } + + public Duration getInitialInterval() { + return initialInterval; + } + + public void setInitialInterval(Duration initialInterval) { + this.initialInterval = initialInterval; + } +} diff --git a/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/IntervalFunctionFactory.java b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/IntervalFunctionFactory.java new file mode 100644 index 0000000..5e2c7c8 --- /dev/null +++ b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/IntervalFunctionFactory.java @@ -0,0 +1,33 @@ +package com.homeaway.dropwizard.bundle.resilience4j.configuration.retry; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; + +import io.dropwizard.jackson.Discoverable; +import io.github.resilience4j.retry.IntervalFunction; + +/** + * A service provider interface for creating Resilience4j {@link IntervalFunction interval functions}. + * To create your own, just: + *
    + *
  1. Create a class which implements {@link IntervalFunctionFactory}.
  2. + *
  3. Annotate it with {@code @JsonTypeName} and give it a unique type name.
  4. + *
  5. Add it to the {@code @JsonSubTypes} annotation on this class
  6. + *
+ * + * @see ConstantIntervalFunctionFactory + * @see ExponentialBackoffFunctionFactory + * @see ExponentialRandomBackoffFunctionFactory + * @see RandomizedIntervalFunctionFactory + */ +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") +@JsonSubTypes({ + @JsonSubTypes.Type(value = ConstantIntervalFunctionFactory.class), + @JsonSubTypes.Type(value = ExponentialBackoffFunctionFactory.class), + @JsonSubTypes.Type(value = ExponentialRandomBackoffFunctionFactory.class), + @JsonSubTypes.Type(value = RandomizedIntervalFunctionFactory.class) +}) +public interface IntervalFunctionFactory extends Discoverable { + + IntervalFunction build(); +} diff --git a/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/RandomizedIntervalFunctionFactory.java b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/RandomizedIntervalFunctionFactory.java new file mode 100644 index 0000000..9891421 --- /dev/null +++ b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/RandomizedIntervalFunctionFactory.java @@ -0,0 +1,48 @@ +package com.homeaway.dropwizard.bundle.resilience4j.configuration.retry; + +import javax.validation.constraints.NotNull; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeName; + +import io.dropwizard.util.Duration; +import io.github.resilience4j.retry.IntervalFunction; + +@JsonTypeName("randomized") +public class RandomizedIntervalFunctionFactory implements IntervalFunctionFactory { + + /** + * Base interval before randomization is applied. Minimum value is 10 milliseconds. Default is R4j default, currently 500ms. + */ + @JsonProperty + @NotNull + private Duration initialInterval = Duration.milliseconds(IntervalFunction.DEFAULT_INITIAL_INTERVAL); + + /** + * Randomization multiplier. Must be in range [0.0d, 1.0d) + */ + @JsonProperty + @NotNull + private double randomizationFactor = IntervalFunction.DEFAULT_RANDOMIZATION_FACTOR; + + @Override + public IntervalFunction build() { + return IntervalFunction.ofRandomized(initialInterval.toMilliseconds(), randomizationFactor); + } + + public Duration getInitialInterval() { + return initialInterval; + } + + public void setInitialInterval(Duration initialInterval) { + this.initialInterval = initialInterval; + } + + public double getRandomizationFactor() { + return randomizationFactor; + } + + public void setRandomizationFactor(double randomizationFactor) { + this.randomizationFactor = randomizationFactor; + } +} diff --git a/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/RetryConfiguration.java b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/RetryConfiguration.java new file mode 100644 index 0000000..1e80139 --- /dev/null +++ b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/RetryConfiguration.java @@ -0,0 +1,98 @@ +package com.homeaway.dropwizard.bundle.resilience4j.configuration.retry; + +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.constraints.NotEmpty; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import io.github.resilience4j.retry.RetryConfig; + +public class RetryConfiguration { + + /** + * Name for this circuit breaker for use in the registry + */ + @JsonProperty + @NotEmpty + private String name; + + /** + * Names of exceptions to ignore + */ + @JsonProperty + private Class[] ignoreExceptions = null; + + /** + * Names of exceptions to always retry + */ + @JsonProperty + private Class[] retryExceptions = null; + + /** + * Maximum number of retries + */ + @JsonProperty + private int maxAttempts = 3; + + /** + * Interval function to define wait period between attempts + */ + @JsonProperty + @NotNull + private IntervalFunctionFactory intervalFunction; + + public RetryConfig.Builder toResilience4jConfigBuilder() { + final RetryConfig.Builder builder = new RetryConfig.Builder() + .maxAttempts(this.maxAttempts) + .intervalFunction(intervalFunction.build()) + .ignoreExceptions(ignoreExceptions) + .retryExceptions(retryExceptions); + + //We are intentionally not supporting the waitDuration() setting, because under the covers it just sets a constant-duration intervalFunction + //The bundle's approach to that is to use a ConstantIntervalFunctionFactory instead + //builder.waitDuration(foo); + + return builder; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Class[] getIgnoreExceptions() { + return ignoreExceptions; + } + + public void setIgnoreExceptions(Class[] ignoreExceptions) { + this.ignoreExceptions = ignoreExceptions; + } + + public Class[] getRetryExceptions() { + return retryExceptions; + } + + public void setRetryExceptions(Class[] retryExceptions) { + this.retryExceptions = retryExceptions; + } + + public int getMaxAttempts() { + return maxAttempts; + } + + public void setMaxAttempts(int maxAttempts) { + this.maxAttempts = maxAttempts; + } + + public IntervalFunctionFactory getIntervalFunction() { + return intervalFunction; + } + + public void setIntervalFunction(IntervalFunctionFactory intervalFunction) { + this.intervalFunction = intervalFunction; + } +} diff --git a/src/test/java/com/homeaway/dropwizard/bundle/resilience4j/Resilience4jBundleTest.java b/src/test/java/com/homeaway/dropwizard/bundle/resilience4j/Resilience4jBundleTest.java index ba32fca..7904a30 100644 --- a/src/test/java/com/homeaway/dropwizard/bundle/resilience4j/Resilience4jBundleTest.java +++ b/src/test/java/com/homeaway/dropwizard/bundle/resilience4j/Resilience4jBundleTest.java @@ -20,12 +20,18 @@ import java.util.List; import org.apache.commons.lang3.tuple.Pair; -import com.homeaway.dropwizard.bundle.resilience4j.configuration.CircuitBreakerConfiguration; -import com.homeaway.dropwizard.bundle.resilience4j.configuration.Resilience4jConfiguration; import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import com.homeaway.dropwizard.bundle.resilience4j.configuration.CircuitBreakerConfiguration; +import com.homeaway.dropwizard.bundle.resilience4j.configuration.Resilience4jConfiguration; +import com.homeaway.dropwizard.bundle.resilience4j.configuration.retry.ConstantIntervalFunctionFactory; +import com.homeaway.dropwizard.bundle.resilience4j.configuration.retry.ExponentialBackoffFunctionFactory; +import com.homeaway.dropwizard.bundle.resilience4j.configuration.retry.ExponentialRandomBackoffFunctionFactory; +import com.homeaway.dropwizard.bundle.resilience4j.configuration.retry.RandomizedIntervalFunctionFactory; +import com.homeaway.dropwizard.bundle.resilience4j.configuration.retry.RetryConfiguration; + import io.dropwizard.Application; import io.dropwizard.Configuration; import io.dropwizard.setup.Bootstrap; @@ -34,6 +40,7 @@ import io.dropwizard.testing.junit.DropwizardAppRule; import io.dropwizard.util.Duration; import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig; +import io.github.resilience4j.retry.RetryConfig; import static org.assertj.core.api.Assertions.assertThat; @@ -43,7 +50,6 @@ public class Resilience4jBundleTest { public DropwizardAppRule app = new DropwizardAppRule<>(TestApplication.class, ResourceHelpers.resourceFilePath("config.yaml")); - @Before public void setup() { } @@ -59,16 +65,45 @@ public void testConfiguration() { assertThat(breaker1).isNotNull(); assertThat(breaker1.getName()).isEqualTo("testBreaker1"); assertThat(breaker1.getEnableAutomaticTransitionFromOpenToHalfOpen()).isFalse(); - assertThat(breaker1.getFailureRateThreshold()).isEqualTo(10); - assertThat(breaker1.getRingBufferSizeInClosedState()).isEqualTo(50); - assertThat(breaker1.getRingBufferSizeInHalfOpenState()).isEqualTo(5); assertThat(breaker1.getWaitDurationInOpenState()).isEqualTo(Duration.seconds(30)); - - assertThat(r4jConfig.getCircuitBreakers().get(1).getName()).isEqualTo("testBreaker2"); - assertThat(r4jConfig.getCircuitBreakers().get(2).getName()).isEqualTo("testBreaker3"); + assertThat(breaker1.getFailureRateThreshold()).isEqualTo(10); + assertThat(breaker1.getMinimumNumberOfCalls()).isEqualTo(5); + assertThat(breaker1.getPermittedNumberOfCallsInHalfOpenState()).isEqualTo(2); + assertThat(breaker1.getSlidingWindowSize()).isEqualTo(4); + assertThat(breaker1.getSlidingWindowType()).isEqualTo(CircuitBreakerConfig.SlidingWindowType.TIME_BASED); + assertThat(breaker1.getSlowCallRateThreshold()).isEqualTo(1.5f); + assertThat(breaker1.getSlowCallDurationThreshold()).isEqualTo(Duration.milliseconds(10)); + assertThat(breaker1.isWritableStackTraceEnabled()).isEqualTo(true); + assertThat(breaker1.getIgnoreExceptions()).containsExactly(NullPointerException.class); + assertThat(breaker1.getRecordExceptions()).containsExactly(IllegalArgumentException.class); + + CircuitBreakerConfiguration breaker2 = r4jConfig.getCircuitBreakers().get(1); + assertThat(breaker2).isNotNull(); + assertThat(breaker2.getName()).isEqualTo("testBreaker2"); + assertThat(breaker2.getEnableAutomaticTransitionFromOpenToHalfOpen()).isTrue(); + assertThat(breaker2.getWaitDurationInOpenState()).isEqualTo(Duration.seconds(CircuitBreakerConfig.DEFAULT_WAIT_DURATION_IN_OPEN_STATE)); + assertThat(breaker2.getFailureRateThreshold()).isEqualTo(CircuitBreakerConfig.DEFAULT_FAILURE_RATE_THRESHOLD); + assertThat(breaker2.getMinimumNumberOfCalls()).isEqualTo(CircuitBreakerConfig.DEFAULT_MINIMUM_NUMBER_OF_CALLS); + assertThat(breaker2.getPermittedNumberOfCallsInHalfOpenState()).isEqualTo(CircuitBreakerConfig.DEFAULT_PERMITTED_CALLS_IN_HALF_OPEN_STATE); + assertThat(breaker2.getSlidingWindowSize()).isEqualTo(CircuitBreakerConfig.DEFAULT_SLIDING_WINDOW_SIZE); + assertThat(breaker2.getSlidingWindowType()).isEqualTo(CircuitBreakerConfig.DEFAULT_SLIDING_WINDOW_TYPE); + assertThat(breaker2.getSlowCallRateThreshold()).isEqualTo(CircuitBreakerConfig.DEFAULT_SLOW_CALL_RATE_THRESHOLD); + assertThat(breaker2.getSlowCallDurationThreshold()).isEqualTo(Duration.seconds(CircuitBreakerConfig.DEFAULT_SLOW_CALL_DURATION_THRESHOLD)); + assertThat(breaker2.isWritableStackTraceEnabled()).isEqualTo(true); + assertThat(breaker2.getIgnoreExceptions()).isNullOrEmpty(); + assertThat(breaker2.getRecordExceptions()).isNullOrEmpty(); + + CircuitBreakerConfiguration breaker3 = r4jConfig.getCircuitBreakers().get(2); + assertThat(breaker3).isNotNull(); + assertThat(breaker3.getName()).isEqualTo("testBreaker3"); + assertThat(breaker3.getSlidingWindowSize()).isEqualTo(10); + assertThat(breaker3.getSlidingWindowType()).isEqualTo(CircuitBreakerConfig.SlidingWindowType.COUNT_BASED); + assertThat(breaker2.getIgnoreExceptions()).isNullOrEmpty(); + assertThat(breaker2.getRecordExceptions()).isNullOrEmpty(); //Check that the configurator function was called for each breaker config - List> breakersSeenInConfiguration = ((TestApplication)app.getApplication()).getBreakersSeenInConfiguration(); + List> breakersSeenInConfiguration = + ((TestApplication) app.getApplication()).getBreakersSeenInConfiguration(); assertThat(breakersSeenInConfiguration.size()).isEqualTo(3); assertThat(breakersSeenInConfiguration.get(0).getKey()).isEqualTo("testBreaker1"); assertThat(breakersSeenInConfiguration.get(1).getKey()).isEqualTo("testBreaker2"); @@ -77,6 +112,42 @@ public void testConfiguration() { assertThat(r4jConfig.getCircuitBreakerRegistry().circuitBreaker("testBreaker1")).isNotNull(); assertThat(r4jConfig.getCircuitBreakerRegistry().circuitBreaker("testBreaker2")).isNotNull(); assertThat(r4jConfig.getCircuitBreakerRegistry().circuitBreaker("testBreaker3")).isNotNull(); + + //Check that retry was configured correctly + assertThat(r4jConfig.getRetryConfigurations()).isNotNull(); + assertThat(r4jConfig.getRetryConfigurations().size()).isEqualTo(4); + + RetryConfiguration retry1 = r4jConfig.getRetryConfigurations().get(0); + assertThat(retry1).isNotNull(); + assertThat(retry1.getName()).isEqualTo("constantRetry"); + assertThat(retry1.getMaxAttempts()).isEqualTo(1); + assertThat(retry1.getIgnoreExceptions()).containsExactly(RuntimeException.class); + assertThat(retry1.getRetryExceptions()).containsExactly(IllegalArgumentException.class); + assertThat(retry1.getIntervalFunction().getClass()).isEqualTo(ConstantIntervalFunctionFactory.class); + + RetryConfiguration retry2 = r4jConfig.getRetryConfigurations().get(1); + assertThat(retry2).isNotNull(); + assertThat(retry2.getName()).isEqualTo("randomizedRetry"); + assertThat(retry2.getMaxAttempts()).isEqualTo(2); + assertThat(retry2.getIgnoreExceptions()).isNullOrEmpty(); + assertThat(retry2.getRetryExceptions()).isNullOrEmpty(); + assertThat(retry2.getIntervalFunction().getClass()).isEqualTo(RandomizedIntervalFunctionFactory.class); + + RetryConfiguration retry3 = r4jConfig.getRetryConfigurations().get(2); + assertThat(retry3).isNotNull(); + assertThat(retry3.getName()).isEqualTo("exponentialBackoffRetry"); + assertThat(retry3.getMaxAttempts()).isEqualTo(3); + assertThat(retry3.getIgnoreExceptions()).isNullOrEmpty(); + assertThat(retry3.getRetryExceptions()).isNullOrEmpty(); + assertThat(retry3.getIntervalFunction().getClass()).isEqualTo(ExponentialBackoffFunctionFactory.class); + + RetryConfiguration retry4 = r4jConfig.getRetryConfigurations().get(3); + assertThat(retry4).isNotNull(); + assertThat(retry4.getName()).isEqualTo("exponentialRandomizedBackoffRetry"); + assertThat(retry4.getMaxAttempts()).isEqualTo(4); + assertThat(retry4.getIgnoreExceptions()).isNullOrEmpty(); + assertThat(retry4.getRetryExceptions()).isNullOrEmpty(); + assertThat(retry4.getIntervalFunction().getClass()).isEqualTo(ExponentialRandomBackoffFunctionFactory.class); } public static class TestConfiguration extends Configuration { @@ -92,9 +163,14 @@ public static class TestApplication extends Application { private List> breakersSeenInConfiguration = new ArrayList<>(); + private List> retryersSeenInConfiguration = new ArrayList<>(); + @Override public void initialize(Bootstrap bootstrap) { - Resilience4jBundle bundle = new Resilience4jBundle<>(TestConfiguration::getResilience4j, this::addBreakerConfigurationToTestList); + Resilience4jBundle bundle = + new Resilience4jBundle<>(TestConfiguration::getResilience4j, + this::addBreakerConfigurationToTestList, + this::addRetryConfigurationToTestList); bootstrap.addBundle(bundle); } @@ -107,8 +183,16 @@ private void addBreakerConfigurationToTestList(String key, CircuitBreakerConfig. breakersSeenInConfiguration.add(Pair.of(key, builder)); } + private void addRetryConfigurationToTestList(String key, RetryConfig.Builder builder) { + retryersSeenInConfiguration.add(Pair.of(key, builder)); + } + public List> getBreakersSeenInConfiguration() { return breakersSeenInConfiguration; } + + public List> getRetryersSeenInConfiguration() { + return retryersSeenInConfiguration; + } } } diff --git a/src/test/resources/config.yaml b/src/test/resources/config.yaml index 195938b..70c4936 100644 --- a/src/test/resources/config.yaml +++ b/src/test/resources/config.yaml @@ -9,10 +9,55 @@ server: resilience4j: circuitBreakers: - name: testBreaker1 - failureRateThreshold: 10 - ringBufferSizeInHalfOpenState: 5 - ringBufferSizeInClosedState: 50 waitDurationInOpenState: 30s enableAutomaticTransitionFromOpenToHalfOpen: false + failureRateThreshold: 10 + minimumNumberOfCalls: 5 + permittedNumberOfCallsInHalfOpenState: 2 + slidingWindowSize: 4 + slidingWindowType: TIME_BASED + slowCallDurationThreshold: 10ms + slowCallRateThreshold: 1.5 + writableStackTraceEnabled: true + ignoreExceptions: + - java.lang.NullPointerException + recordExceptions: + - java.lang.IllegalArgumentException - name: testBreaker2 - name: testBreaker3 + slidingWindowType: COUNT_BASED + slidingWindowSize: 10 + ignoreExceptions: + recordExceptions: + + retryConfigurations: + - name: constantRetry + maxAttempts: 1 + intervalFunction: + type: constant + initialInterval: 10ms + ignoreExceptions: + - java.lang.RuntimeException + retryExceptions: + - java.lang.IllegalArgumentException + - name: randomizedRetry + maxAttempts: 2 + intervalFunction: + type: randomized + initialInterval: 10ms + randomizationFactor: 0.5 + ignoreExceptions: + retryExceptions: + - name: exponentialBackoffRetry + maxAttempts: 3 + intervalFunction: + type: exponentialBackoff + initialInterval: 10ms + multiplier: 3.5 + - name: exponentialRandomizedBackoffRetry + maxAttempts: 4 + intervalFunction: + type: exponentialRandomBackoff + initialInterval: 10ms + multiplier: 2.5 + randomizationFactor: 0.5 \ No newline at end of file From 5803cdba0711538d2a6042d9d4b396a0c484038e Mon Sep 17 00:00:00 2001 From: Brian Reischl Date: Mon, 28 Oct 2019 08:13:20 -0600 Subject: [PATCH 2/4] Generify arrays --- .../configuration/CircuitBreakerConfiguration.java | 12 ++++++------ .../configuration/retry/RetryConfiguration.java | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/CircuitBreakerConfiguration.java b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/CircuitBreakerConfiguration.java index c96adf8..3b89067 100644 --- a/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/CircuitBreakerConfiguration.java +++ b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/CircuitBreakerConfiguration.java @@ -80,10 +80,10 @@ public class CircuitBreakerConfiguration { private boolean writableStackTraceEnabled = CircuitBreakerConfig.DEFAULT_WRITABLE_STACK_TRACE_ENABLED; @JsonProperty - private Class[] ignoreExceptions = new Class[0]; + private Class[] ignoreExceptions = new Class[0]; @JsonProperty - private Class[] recordExceptions = new Class[0]; + private Class[] recordExceptions = new Class[0]; public CircuitBreakerConfig.Builder toResilience4jConfigBuilder() { return CircuitBreakerConfig.custom() @@ -189,19 +189,19 @@ public void setWritableStackTraceEnabled(boolean writableStackTraceEnabled) { this.writableStackTraceEnabled = writableStackTraceEnabled; } - public Class[] getIgnoreExceptions() { + public Class[] getIgnoreExceptions() { return ignoreExceptions; } - public void setIgnoreExceptions(Class[] ignoreExceptions) { + public void setIgnoreExceptions(Class[] ignoreExceptions) { this.ignoreExceptions = ignoreExceptions; } - public Class[] getRecordExceptions() { + public Class[] getRecordExceptions() { return recordExceptions; } - public void setRecordExceptions(Class[] recordExceptions) { + public void setRecordExceptions(Class[] recordExceptions) { this.recordExceptions = recordExceptions; } } diff --git a/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/RetryConfiguration.java b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/RetryConfiguration.java index 1e80139..165959f 100644 --- a/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/RetryConfiguration.java +++ b/src/main/java/com/homeaway/dropwizard/bundle/resilience4j/configuration/retry/RetryConfiguration.java @@ -21,13 +21,13 @@ public class RetryConfiguration { * Names of exceptions to ignore */ @JsonProperty - private Class[] ignoreExceptions = null; + private Class[] ignoreExceptions = null; /** * Names of exceptions to always retry */ @JsonProperty - private Class[] retryExceptions = null; + private Class[] retryExceptions = null; /** * Maximum number of retries @@ -64,19 +64,19 @@ public void setName(String name) { this.name = name; } - public Class[] getIgnoreExceptions() { + public Class[] getIgnoreExceptions() { return ignoreExceptions; } - public void setIgnoreExceptions(Class[] ignoreExceptions) { + public void setIgnoreExceptions(Class[] ignoreExceptions) { this.ignoreExceptions = ignoreExceptions; } - public Class[] getRetryExceptions() { + public Class[] getRetryExceptions() { return retryExceptions; } - public void setRetryExceptions(Class[] retryExceptions) { + public void setRetryExceptions(Class[] retryExceptions) { this.retryExceptions = retryExceptions; } From 7061db87a177e3dd08e7ed8840cbcd56e6ffea21 Mon Sep 17 00:00:00 2001 From: Brian Reischl Date: Mon, 28 Oct 2019 08:14:14 -0600 Subject: [PATCH 3/4] changelog --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b09c955..cd7d1b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/). ## [Unreleased] -### Changed +### Added - Added support for R4j `Retry` -- Updated to R4j 1.1.0. This is a major version bump that has a lot of breaking changes that will be user-visible. See R4j documentation for details. +### Changed +- Updated to R4j 1.1.0. This is a major version bump that has a lot of breaking changes that will be user-visible. See R4j documentation for details. ##[0.0.1] - 2019-03-11 ###Initial Version From a35fca73ce07980c0653f64c5a1187480449be56 Mon Sep 17 00:00:00 2001 From: Brian Reischl Date: Mon, 28 Oct 2019 09:41:07 -0600 Subject: [PATCH 4/4] Bump version, ignore .versionBackup files --- .gitignore | 3 ++- pom.xml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 4f3d262..7e8e8d7 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ overlays *.ipr *.iml *.iws -.idea \ No newline at end of file +.idea +*.versionsBackup diff --git a/pom.xml b/pom.xml index 7fbbbf1..b242637 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.expediagroup.dropwizard.bundle dropwizard-resilience4j-bundle - 0.1.0-SNAPSHOT + 1.0.0-SNAPSHOT jar dropwizard-resilience4j-bundle