From 3617fd707656e54fbd372722404b848ae7e5ef86 Mon Sep 17 00:00:00 2001 From: Andrii Bohutskyi Date: Thu, 8 Apr 2021 12:21:17 +0300 Subject: [PATCH 1/5] Support bulkhead group --- .../Resilience4JCircuitBreaker.java | 31 +++++++++++++---- .../Resilience4JCircuitBreakerFactory.java | 26 ++++++++++---- .../Resilience4jBulkheadProvider.java | 13 ++++--- ...lience4JCircuitBreakerIntegrationTest.java | 4 +++ .../Resilience4JCircuitBreakerTest.java | 34 +++++++++++++++++++ 5 files changed, 89 insertions(+), 19 deletions(-) diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java index cbcffe7..a16518d 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java @@ -38,8 +38,12 @@ import org.springframework.cloud.client.circuitbreaker.Customizer; */ public class Resilience4JCircuitBreaker implements CircuitBreaker { + static final String CIRCUIT_BREAKER_GROUP_TAG = "group"; + private final String id; + private final String groupName; + private Resilience4jBulkheadProvider bulkheadProvider; private final io.github.resilience4j.circuitbreaker.CircuitBreakerConfig circuitBreakerConfig; @@ -62,6 +66,7 @@ public class Resilience4JCircuitBreaker implements CircuitBreaker { ExecutorService executorService, Optional> circuitBreakerCustomizer) { this.id = id; + this.groupName = id; this.circuitBreakerConfig = circuitBreakerConfig; this.registry = circuitBreakerRegistry; this.timeLimiterRegistry = TimeLimiterRegistry.ofDefaults(); @@ -70,6 +75,7 @@ public class Resilience4JCircuitBreaker implements CircuitBreaker { this.circuitBreakerCustomizer = circuitBreakerCustomizer; } + @Deprecated public Resilience4JCircuitBreaker(String id, io.github.resilience4j.circuitbreaker.CircuitBreakerConfig circuitBreakerConfig, TimeLimiterConfig timeLimiterConfig, @@ -77,7 +83,20 @@ public class Resilience4JCircuitBreaker implements CircuitBreaker { TimeLimiterRegistry timeLimiterRegistry, ExecutorService executorService, Optional> circuitBreakerCustomizer, Resilience4jBulkheadProvider bulkheadProvider) { + this(id, id, circuitBreakerConfig, timeLimiterConfig, circuitBreakerRegistry, timeLimiterRegistry, executorService, + circuitBreakerCustomizer, bulkheadProvider); + } + + public Resilience4JCircuitBreaker(String id, + String groupName, + io.github.resilience4j.circuitbreaker.CircuitBreakerConfig circuitBreakerConfig, + TimeLimiterConfig timeLimiterConfig, + CircuitBreakerRegistry circuitBreakerRegistry, + TimeLimiterRegistry timeLimiterRegistry, ExecutorService executorService, + Optional> circuitBreakerCustomizer, + Resilience4jBulkheadProvider bulkheadProvider) { this.id = id; + this.groupName = groupName; this.circuitBreakerConfig = circuitBreakerConfig; this.registry = circuitBreakerRegistry; this.timeLimiterRegistry = timeLimiterRegistry; @@ -89,20 +108,20 @@ public class Resilience4JCircuitBreaker implements CircuitBreaker { @Override public T run(Supplier toRun, Function fallback) { - TimeLimiter timeLimiter = timeLimiterRegistry.timeLimiter(id, timeLimiterConfig); + final io.vavr.collection.Map tags = io.vavr.collection.HashMap.of(CIRCUIT_BREAKER_GROUP_TAG, this.groupName); + TimeLimiter timeLimiter = timeLimiterRegistry.timeLimiter(id, timeLimiterConfig, tags); Supplier> futureSupplier = () -> executorService.submit(toRun::get); Callable restrictedCall = TimeLimiter.decorateFutureSupplier(timeLimiter, futureSupplier); io.github.resilience4j.circuitbreaker.CircuitBreaker defaultCircuitBreaker = registry - .circuitBreaker(id, circuitBreakerConfig); + .circuitBreaker(this.id, this.circuitBreakerConfig, tags); circuitBreakerCustomizer .ifPresent(customizer -> customizer.customize(defaultCircuitBreaker)); if (bulkheadProvider != null) { - return bulkheadProvider.run(id, toRun, fallback, defaultCircuitBreaker, - timeLimiter); - } - else { + return bulkheadProvider.run(this.groupName, toRun, fallback, defaultCircuitBreaker, + timeLimiter, tags); + } else { Callable callable = io.github.resilience4j.circuitbreaker.CircuitBreaker .decorateCallable(defaultCircuitBreaker, restrictedCall); return Try.of(callable::call).recover(fallback).get(); diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java index 6da4ef3..7de0e2a 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java @@ -19,6 +19,7 @@ package org.springframework.cloud.circuitbreaker.resilience4j; import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.function.Function; @@ -51,6 +52,8 @@ public class Resilience4JCircuitBreakerFactory extends private ExecutorService executorService = Executors.newCachedThreadPool(); + private ConcurrentHashMap executorServices = new ConcurrentHashMap<>(); + private Map> circuitBreakerCustomizers = new HashMap<>(); @Deprecated @@ -106,12 +109,15 @@ public class Resilience4JCircuitBreakerFactory extends @Override public Resilience4JCircuitBreaker create(String id) { Assert.hasText(id, "A CircuitBreaker must have an id."); - Resilience4JConfigBuilder.Resilience4JCircuitBreakerConfiguration config = getConfigurations() - .computeIfAbsent(id, defaultConfiguration); - return new Resilience4JCircuitBreaker(id, config.getCircuitBreakerConfig(), - config.getTimeLimiterConfig(), circuitBreakerRegistry, - timeLimiterRegistry, executorService, - Optional.ofNullable(circuitBreakerCustomizers.get(id)), bulkheadProvider); + return create(id, id, this.executorService); + } + + @Override + public Resilience4JCircuitBreaker create(String id, String groupName) { + Assert.hasText(id, "A CircuitBreaker must have an id."); + Assert.hasText(groupName, "A CircuitBreaker must have a group name."); + final ExecutorService groupExecutorService = executorServices.computeIfAbsent(groupName, group -> Executors.newCachedThreadPool()); + return create(id, groupName, groupExecutorService); } public void addCircuitBreakerCustomizer(Customizer customizer, @@ -121,4 +127,12 @@ public class Resilience4JCircuitBreakerFactory extends } } + private Resilience4JCircuitBreaker create(String id, String groupName, ExecutorService circuitBreakerExecutorService) { + Resilience4JConfigBuilder.Resilience4JCircuitBreakerConfiguration config = getConfigurations() + .computeIfAbsent(id, defaultConfiguration); + return new Resilience4JCircuitBreaker(id, groupName, config.getCircuitBreakerConfig(), + config.getTimeLimiterConfig(), circuitBreakerRegistry, + timeLimiterRegistry, circuitBreakerExecutorService, + Optional.ofNullable(circuitBreakerCustomizers.get(id)), bulkheadProvider); + } } diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4jBulkheadProvider.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4jBulkheadProvider.java index f3532e3..ea8037d 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4jBulkheadProvider.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4jBulkheadProvider.java @@ -105,9 +105,9 @@ public class Resilience4jBulkheadProvider { return threadPoolBulkheadRegistry; } - public T run(String id, Supplier toRun, Function fallback, - CircuitBreaker circuitBreaker, TimeLimiter timeLimiter) { - Supplier> bulkheadCall = decorateBulkhead(id, toRun); + public T run(String groupName, Supplier toRun, Function fallback, + CircuitBreaker circuitBreaker, TimeLimiter timeLimiter, io.vavr.collection.Map tags) { + Supplier> bulkheadCall = decorateBulkhead(groupName, tags, toRun); final Callable timeLimiterCall = decorateTimeLimiter(bulkheadCall, timeLimiter); final Callable circuitBreakerCall = circuitBreaker @@ -115,21 +115,20 @@ public class Resilience4jBulkheadProvider { return Try.of(circuitBreakerCall::call).recover(fallback).get(); } - private Supplier> decorateBulkhead(final String id, + private Supplier> decorateBulkhead(final String id, final io.vavr.collection.Map tags, final Supplier supplier) { Resilience4jBulkheadConfigurationBuilder.BulkheadConfiguration configuration = configurations .computeIfAbsent(id, defaultConfiguration); if (bulkheadRegistry.find(id).isPresent() && !threadPoolBulkheadRegistry.find(id).isPresent()) { - Bulkhead bulkhead = bulkheadRegistry.bulkhead(id, - configuration.getBulkheadConfig()); + Bulkhead bulkhead = bulkheadRegistry.bulkhead(id, configuration.getBulkheadConfig(), tags); CompletableFuture asyncCall = CompletableFuture.supplyAsync(supplier); return Bulkhead.decorateCompletionStage(bulkhead, () -> asyncCall); } else { ThreadPoolBulkhead threadPoolBulkhead = threadPoolBulkheadRegistry - .bulkhead(id, configuration.getThreadPoolBulkheadConfig()); + .bulkhead(id, configuration.getThreadPoolBulkheadConfig(), tags); return threadPoolBulkhead.decorateSupplier(supplier); } } diff --git a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java index 29430f2..710558c 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java @@ -108,6 +108,10 @@ public class Resilience4JCircuitBreakerIntegrationTest { assertThat(service.normal()).isEqualTo("normal"); assertThat(((List) rest.getForObject("/actuator/metrics", Map.class).get("names")) .contains("resilience4j.circuitbreaker.calls")).isTrue(); + + //CircuitBreaker and TimeLimiter should have 3 metrics: name, kind, group + assertThat(((List) rest.getForObject("/actuator/metrics/resilience4j.circuitbreaker.calls", Map.class).get("availableTags"))).hasSize(3); + assertThat(((List) rest.getForObject("/actuator/metrics/resilience4j.timelimiter.calls", Map.class).get("availableTags"))).hasSize(3); } @Configuration(proxyBeanMethods = false) diff --git a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java index 14c6bad..a21e2ff 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java @@ -40,6 +40,14 @@ public class Resilience4JCircuitBreakerTest { assertThat(cb.run(() -> "foobar")).isEqualTo("foobar"); } + @Test + public void runWithGroupName() { + CircuitBreaker cb = new Resilience4JCircuitBreakerFactory(CircuitBreakerRegistry.ofDefaults(), + TimeLimiterRegistry.ofDefaults(), null).create("foo", "groupFoo"); + assertThat(cb.run(() -> "foobar")).isEqualTo("foobar"); + + } + @Test public void runWithFallback() { CircuitBreaker cb = new Resilience4JCircuitBreakerFactory( @@ -50,6 +58,15 @@ public class Resilience4JCircuitBreakerTest { }, t -> "fallback")).isEqualTo("fallback"); } + @Test + public void runWithFallbackAndGroupName() { + CircuitBreaker cb = new Resilience4JCircuitBreakerFactory(CircuitBreakerRegistry.ofDefaults(), + TimeLimiterRegistry.ofDefaults(), null).create("foo", "groupFoo"); + assertThat((String) cb.run(() -> { + throw new RuntimeException("boom"); + }, t -> "fallback")).isEqualTo("fallback"); + } + @Test public void runWithBulkheadProvider() { CircuitBreaker cb = new Resilience4JCircuitBreakerFactory( @@ -59,6 +76,14 @@ public class Resilience4JCircuitBreakerTest { assertThat(cb.run(() -> "foobar")).isEqualTo("foobar"); } + @Test + public void runWithBulkheadProviderAndGroupName() { + CircuitBreaker cb = new Resilience4JCircuitBreakerFactory(CircuitBreakerRegistry.ofDefaults(), + TimeLimiterRegistry.ofDefaults(), new Resilience4jBulkheadProvider( + ThreadPoolBulkheadRegistry.ofDefaults(), BulkheadRegistry.ofDefaults())).create("foo", "groupFoo"); + assertThat(cb.run(() -> "foobar")).isEqualTo("foobar"); + } + @Test public void runWithFallbackBulkheadProvider() { CircuitBreaker cb = new Resilience4JCircuitBreakerFactory( @@ -70,4 +95,13 @@ public class Resilience4JCircuitBreakerTest { }, t -> "fallback")).isEqualTo("fallback"); } + @Test + public void runWithFallbackBulkheadProviderAndGroupName() { + CircuitBreaker cb = new Resilience4JCircuitBreakerFactory(CircuitBreakerRegistry.ofDefaults(), + TimeLimiterRegistry.ofDefaults(), new Resilience4jBulkheadProvider( + ThreadPoolBulkheadRegistry.ofDefaults(), BulkheadRegistry.ofDefaults())).create("foo", "groupFoo"); + assertThat((String) cb.run(() -> { + throw new RuntimeException("boom"); + }, t -> "fallback")).isEqualTo("fallback"); + } } From c1259691dd7d9101451cbe5637d063de0e38b4f6 Mon Sep 17 00:00:00 2001 From: buildmaster Date: Wed, 21 Apr 2021 17:17:31 +0000 Subject: [PATCH 2/5] Update SNAPSHOT to 1.0.5.RELEASE --- README.adoc | 102 ++++++++++++++---- docs/pom.xml | 2 +- pom.xml | 6 +- .../pom.xml | 4 +- .../pom.xml | 2 +- .../Resilience4JCircuitBreaker.java | 33 +++--- .../Resilience4JCircuitBreakerFactory.java | 18 ++-- .../Resilience4jBulkheadProvider.java | 12 ++- ...lience4JCircuitBreakerIntegrationTest.java | 12 ++- .../Resilience4JCircuitBreakerTest.java | 25 +++-- .../pom.xml | 2 +- spring-cloud-starter-circuitbreaker/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- 15 files changed, 157 insertions(+), 69 deletions(-) diff --git a/README.adoc b/README.adoc index 1315b63..f0d352d 100644 --- a/README.adoc +++ b/README.adoc @@ -138,34 +138,100 @@ public Customizer slowCusomtizer() { ---- ==== +==== Bulkhead pattern supporting +If `resilience4j-bulkhead` is on the classpath, Spring Cloud CircuitBreaker will wrap all methods with a Resilience4j Bulkhead. +You can disable the Resilience4j Bulkhead by setting `spring.cloud.circuitbreaker.bulkhead.resilience4j.enabled` to `false`. -==== Properties Configuration +Spring Cloud CircuitBreaker Resilience4j provides two implementation of bulkhead pattern: -You can configure CircuitBreaker and TimeLimiter instances in your application's configuration properties file. Property configuration has higher priority than Java `Customizer` configuration. +* a `SemaphoreBulkhead` which uses Semaphores +* a `FixedThreadPoolBulkhead` which uses a bounded queue and a fixed thread pool. + +By default, Spring Cloud CircuitBreaker Resilience4j uses `FixedThreadPoolBulkhead`. For more information on implementation +of Bulkhead patterns see the https://resilience4j.readme.io/docs/bulkhead[Resilience4j Bulkhead]. + +The `Customizer` can be used to provide a default `Bulkhead` and `ThreadPoolBulkhead` configuration. + +==== +[source,java] +---- +@Bean +public Customizer defaultBulkheadCustomizer() { + return provider -> provider.configureDefault(id -> new Resilience4jBulkheadConfigurationBuilder() + .bulkheadConfig(BulkheadConfig.custom().maxConcurrentCalls(4).build()) + .threadPoolBulkheadConfig(ThreadPoolBulkheadConfig.custom().coreThreadPoolSize(1).maxThreadPoolSize(1).build()) + .build() +); +} +---- +==== + +==== Specific Bulkhead Configuration + +Similarly to proving a default 'Bulkhead' or 'ThreadPoolBulkhead' configuration, you can create a `Customize` bean this +is passed a `Resilience4jBulkheadProvider`. + +==== +[source,java] +---- +@Bean +public Customizer slowBulkheadProviderCustomizer() { + return provider -> provider.configure(builder -> builder + .bulkheadConfig(BulkheadConfig.custom().maxConcurrentCalls(1).build()) + .threadPoolBulkheadConfig(ThreadPoolBulkheadConfig.ofDefaults()), "slowBulkhead"); +} +---- +==== + +In addition to configuring the Bulkhead that is created you can also customize the bulkhead and thread pool bulkhead after they +have been created but before they are returned to caller. To do this you can use the `addBulkheadCustomizer` and `addThreadPoolBulkheadCustomizer` +methods. + +===== Bulkhead Example + +==== +[source,java] +---- +@Bean +public Customizer customizer() { + return provider -> provider.addBulkheadCustomizer(bulkhead -> bulkhead.getEventPublisher() + .onCallRejected(slowRejectedConsumer) + .onCallFinished(slowFinishedConsumer), "slowBulkhead"); +} +---- +==== + +===== Thread Pool Bulkhead Example + +==== +[source,java] +---- +@Bean +public Customizer slowThreadPoolBulkheadCustomizer() { + return provider -> provider.addThreadPoolBulkheadCustomizer(threadPoolBulkhead -> threadPoolBulkhead.getEventPublisher() + .onCallRejected(slowThreadPoolRejectedConsumer) + .onCallFinished(slowThreadPoolFinishedConsumer), "slowThreadPoolBulkhead"); +} +---- +==== + +==== Bulkhead Properties Configuration + +You can configure ThreadPoolBulkhead and SemaphoreBulkhead instances in your application's configuration properties file. +Property configuration has higher priority than Java `Customizer` configuration. ==== [source] ---- -resilience4j.circuitbreaker: +resilience4j.thread-pool-bulkhead: instances: backendA: - registerHealthIndicator: true - slidingWindowSize: 100 - backendB: - registerHealthIndicator: true - slidingWindowSize: 10 - permittedNumberOfCallsInHalfOpenState: 3 - slidingWindowType: TIME_BASED - recordFailurePredicate: io.github.robwin.exception.RecordFailurePredicate - -resilience4j.timelimiter: + maxThreadPoolSize: 1 + coreThreadPoolSize: 1 +resilience4j.bulkhead: instances: - backendA: - timeoutDuration: 2s - cancelRunningFuture: true backendB: - timeoutDuration: 1s - cancelRunningFuture: false + maxConcurrentCalls: 10 ---- ==== diff --git a/docs/pom.xml b/docs/pom.xml index 58f8b78..2cab78c 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -5,7 +5,7 @@ spring-cloud-circuitbreaker org.springframework.cloud - 1.0.5.BUILD-SNAPSHOT + 1.0.5.RELEASE 4.0.0 diff --git a/pom.xml b/pom.xml index 2a3869e..380d9a2 100644 --- a/pom.xml +++ b/pom.xml @@ -6,12 +6,12 @@ spring-cloud-circuitbreaker pom - 1.0.5.BUILD-SNAPSHOT + 1.0.5.RELEASE org.springframework.cloud spring-cloud-build - 2.3.2.BUILD-SNAPSHOT + 2.3.4.RELEASE @@ -21,7 +21,7 @@ reuseReports ${project.basedir}/../target/jacoco.exec java - 2.2.8.BUILD-SNAPSHOT + 2.2.8.RELEASE diff --git a/spring-cloud-circuitbreaker-dependencies/pom.xml b/spring-cloud-circuitbreaker-dependencies/pom.xml index b0a1cb8..6ed54d4 100644 --- a/spring-cloud-circuitbreaker-dependencies/pom.xml +++ b/spring-cloud-circuitbreaker-dependencies/pom.xml @@ -7,12 +7,12 @@ spring-cloud-dependencies-parent org.springframework.cloud - 2.3.2.BUILD-SNAPSHOT + 2.3.4.RELEASE spring-cloud-circuitbreaker-dependencies - 1.0.5.BUILD-SNAPSHOT + 1.0.5.RELEASE pom spring-cloud-circuitbreaker-dependencies Spring Cloud Circuit Breaker Dependencies diff --git a/spring-cloud-circuitbreaker-resilience4j/pom.xml b/spring-cloud-circuitbreaker-resilience4j/pom.xml index 8cb8c7a..73a09f4 100644 --- a/spring-cloud-circuitbreaker-resilience4j/pom.xml +++ b/spring-cloud-circuitbreaker-resilience4j/pom.xml @@ -5,7 +5,7 @@ spring-cloud-circuitbreaker org.springframework.cloud - 1.0.5.BUILD-SNAPSHOT + 1.0.5.RELEASE .. 4.0.0 diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java index a16518d..2fb9ec4 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java @@ -83,18 +83,18 @@ public class Resilience4JCircuitBreaker implements CircuitBreaker { TimeLimiterRegistry timeLimiterRegistry, ExecutorService executorService, Optional> circuitBreakerCustomizer, Resilience4jBulkheadProvider bulkheadProvider) { - this(id, id, circuitBreakerConfig, timeLimiterConfig, circuitBreakerRegistry, timeLimiterRegistry, executorService, - circuitBreakerCustomizer, bulkheadProvider); + this(id, id, circuitBreakerConfig, timeLimiterConfig, circuitBreakerRegistry, + timeLimiterRegistry, executorService, circuitBreakerCustomizer, + bulkheadProvider); } - public Resilience4JCircuitBreaker(String id, - String groupName, - io.github.resilience4j.circuitbreaker.CircuitBreakerConfig circuitBreakerConfig, - TimeLimiterConfig timeLimiterConfig, - CircuitBreakerRegistry circuitBreakerRegistry, - TimeLimiterRegistry timeLimiterRegistry, ExecutorService executorService, - Optional> circuitBreakerCustomizer, - Resilience4jBulkheadProvider bulkheadProvider) { + public Resilience4JCircuitBreaker(String id, String groupName, + io.github.resilience4j.circuitbreaker.CircuitBreakerConfig circuitBreakerConfig, + TimeLimiterConfig timeLimiterConfig, + CircuitBreakerRegistry circuitBreakerRegistry, + TimeLimiterRegistry timeLimiterRegistry, ExecutorService executorService, + Optional> circuitBreakerCustomizer, + Resilience4jBulkheadProvider bulkheadProvider) { this.id = id; this.groupName = groupName; this.circuitBreakerConfig = circuitBreakerConfig; @@ -108,8 +108,10 @@ public class Resilience4JCircuitBreaker implements CircuitBreaker { @Override public T run(Supplier toRun, Function fallback) { - final io.vavr.collection.Map tags = io.vavr.collection.HashMap.of(CIRCUIT_BREAKER_GROUP_TAG, this.groupName); - TimeLimiter timeLimiter = timeLimiterRegistry.timeLimiter(id, timeLimiterConfig, tags); + final io.vavr.collection.Map tags = io.vavr.collection.HashMap + .of(CIRCUIT_BREAKER_GROUP_TAG, this.groupName); + TimeLimiter timeLimiter = timeLimiterRegistry.timeLimiter(id, timeLimiterConfig, + tags); Supplier> futureSupplier = () -> executorService.submit(toRun::get); Callable restrictedCall = TimeLimiter.decorateFutureSupplier(timeLimiter, futureSupplier); @@ -119,9 +121,10 @@ public class Resilience4JCircuitBreaker implements CircuitBreaker { .ifPresent(customizer -> customizer.customize(defaultCircuitBreaker)); if (bulkheadProvider != null) { - return bulkheadProvider.run(this.groupName, toRun, fallback, defaultCircuitBreaker, - timeLimiter, tags); - } else { + return bulkheadProvider.run(this.groupName, toRun, fallback, + defaultCircuitBreaker, timeLimiter, tags); + } + else { Callable callable = io.github.resilience4j.circuitbreaker.CircuitBreaker .decorateCallable(defaultCircuitBreaker, restrictedCall); return Try.of(callable::call).recover(fallback).get(); diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java index 7de0e2a..0966274 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java @@ -116,7 +116,8 @@ public class Resilience4JCircuitBreakerFactory extends public Resilience4JCircuitBreaker create(String id, String groupName) { Assert.hasText(id, "A CircuitBreaker must have an id."); Assert.hasText(groupName, "A CircuitBreaker must have a group name."); - final ExecutorService groupExecutorService = executorServices.computeIfAbsent(groupName, group -> Executors.newCachedThreadPool()); + final ExecutorService groupExecutorService = executorServices + .computeIfAbsent(groupName, group -> Executors.newCachedThreadPool()); return create(id, groupName, groupExecutorService); } @@ -127,12 +128,15 @@ public class Resilience4JCircuitBreakerFactory extends } } - private Resilience4JCircuitBreaker create(String id, String groupName, ExecutorService circuitBreakerExecutorService) { + private Resilience4JCircuitBreaker create(String id, String groupName, + ExecutorService circuitBreakerExecutorService) { Resilience4JConfigBuilder.Resilience4JCircuitBreakerConfiguration config = getConfigurations() - .computeIfAbsent(id, defaultConfiguration); - return new Resilience4JCircuitBreaker(id, groupName, config.getCircuitBreakerConfig(), - config.getTimeLimiterConfig(), circuitBreakerRegistry, - timeLimiterRegistry, circuitBreakerExecutorService, - Optional.ofNullable(circuitBreakerCustomizers.get(id)), bulkheadProvider); + .computeIfAbsent(id, defaultConfiguration); + return new Resilience4JCircuitBreaker(id, groupName, + config.getCircuitBreakerConfig(), config.getTimeLimiterConfig(), + circuitBreakerRegistry, timeLimiterRegistry, + circuitBreakerExecutorService, + Optional.ofNullable(circuitBreakerCustomizers.get(id)), bulkheadProvider); } + } diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4jBulkheadProvider.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4jBulkheadProvider.java index ea8037d..fdd59ca 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4jBulkheadProvider.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4jBulkheadProvider.java @@ -106,8 +106,10 @@ public class Resilience4jBulkheadProvider { } public T run(String groupName, Supplier toRun, Function fallback, - CircuitBreaker circuitBreaker, TimeLimiter timeLimiter, io.vavr.collection.Map tags) { - Supplier> bulkheadCall = decorateBulkhead(groupName, tags, toRun); + CircuitBreaker circuitBreaker, TimeLimiter timeLimiter, + io.vavr.collection.Map tags) { + Supplier> bulkheadCall = decorateBulkhead(groupName, tags, + toRun); final Callable timeLimiterCall = decorateTimeLimiter(bulkheadCall, timeLimiter); final Callable circuitBreakerCall = circuitBreaker @@ -115,14 +117,16 @@ public class Resilience4jBulkheadProvider { return Try.of(circuitBreakerCall::call).recover(fallback).get(); } - private Supplier> decorateBulkhead(final String id, final io.vavr.collection.Map tags, + private Supplier> decorateBulkhead(final String id, + final io.vavr.collection.Map tags, final Supplier supplier) { Resilience4jBulkheadConfigurationBuilder.BulkheadConfiguration configuration = configurations .computeIfAbsent(id, defaultConfiguration); if (bulkheadRegistry.find(id).isPresent() && !threadPoolBulkheadRegistry.find(id).isPresent()) { - Bulkhead bulkhead = bulkheadRegistry.bulkhead(id, configuration.getBulkheadConfig(), tags); + Bulkhead bulkhead = bulkheadRegistry.bulkhead(id, + configuration.getBulkheadConfig(), tags); CompletableFuture asyncCall = CompletableFuture.supplyAsync(supplier); return Bulkhead.decorateCompletionStage(bulkhead, () -> asyncCall); } diff --git a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java index 710558c..2d23fb6 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java @@ -109,9 +109,15 @@ public class Resilience4JCircuitBreakerIntegrationTest { assertThat(((List) rest.getForObject("/actuator/metrics", Map.class).get("names")) .contains("resilience4j.circuitbreaker.calls")).isTrue(); - //CircuitBreaker and TimeLimiter should have 3 metrics: name, kind, group - assertThat(((List) rest.getForObject("/actuator/metrics/resilience4j.circuitbreaker.calls", Map.class).get("availableTags"))).hasSize(3); - assertThat(((List) rest.getForObject("/actuator/metrics/resilience4j.timelimiter.calls", Map.class).get("availableTags"))).hasSize(3); + // CircuitBreaker and TimeLimiter should have 3 metrics: name, kind, group + assertThat(((List) rest + .getForObject("/actuator/metrics/resilience4j.circuitbreaker.calls", + Map.class) + .get("availableTags"))).hasSize(3); + assertThat(((List) rest + .getForObject("/actuator/metrics/resilience4j.timelimiter.calls", + Map.class) + .get("availableTags"))).hasSize(3); } @Configuration(proxyBeanMethods = false) diff --git a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java index a21e2ff..6e3c843 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java @@ -42,8 +42,9 @@ public class Resilience4JCircuitBreakerTest { @Test public void runWithGroupName() { - CircuitBreaker cb = new Resilience4JCircuitBreakerFactory(CircuitBreakerRegistry.ofDefaults(), - TimeLimiterRegistry.ofDefaults(), null).create("foo", "groupFoo"); + CircuitBreaker cb = new Resilience4JCircuitBreakerFactory( + CircuitBreakerRegistry.ofDefaults(), TimeLimiterRegistry.ofDefaults(), + null).create("foo", "groupFoo"); assertThat(cb.run(() -> "foobar")).isEqualTo("foobar"); } @@ -60,8 +61,9 @@ public class Resilience4JCircuitBreakerTest { @Test public void runWithFallbackAndGroupName() { - CircuitBreaker cb = new Resilience4JCircuitBreakerFactory(CircuitBreakerRegistry.ofDefaults(), - TimeLimiterRegistry.ofDefaults(), null).create("foo", "groupFoo"); + CircuitBreaker cb = new Resilience4JCircuitBreakerFactory( + CircuitBreakerRegistry.ofDefaults(), TimeLimiterRegistry.ofDefaults(), + null).create("foo", "groupFoo"); assertThat((String) cb.run(() -> { throw new RuntimeException("boom"); }, t -> "fallback")).isEqualTo("fallback"); @@ -78,9 +80,10 @@ public class Resilience4JCircuitBreakerTest { @Test public void runWithBulkheadProviderAndGroupName() { - CircuitBreaker cb = new Resilience4JCircuitBreakerFactory(CircuitBreakerRegistry.ofDefaults(), - TimeLimiterRegistry.ofDefaults(), new Resilience4jBulkheadProvider( - ThreadPoolBulkheadRegistry.ofDefaults(), BulkheadRegistry.ofDefaults())).create("foo", "groupFoo"); + CircuitBreaker cb = new Resilience4JCircuitBreakerFactory( + CircuitBreakerRegistry.ofDefaults(), TimeLimiterRegistry.ofDefaults(), + new Resilience4jBulkheadProvider(ThreadPoolBulkheadRegistry.ofDefaults(), + BulkheadRegistry.ofDefaults())).create("foo", "groupFoo"); assertThat(cb.run(() -> "foobar")).isEqualTo("foobar"); } @@ -97,11 +100,13 @@ public class Resilience4JCircuitBreakerTest { @Test public void runWithFallbackBulkheadProviderAndGroupName() { - CircuitBreaker cb = new Resilience4JCircuitBreakerFactory(CircuitBreakerRegistry.ofDefaults(), - TimeLimiterRegistry.ofDefaults(), new Resilience4jBulkheadProvider( - ThreadPoolBulkheadRegistry.ofDefaults(), BulkheadRegistry.ofDefaults())).create("foo", "groupFoo"); + CircuitBreaker cb = new Resilience4JCircuitBreakerFactory( + CircuitBreakerRegistry.ofDefaults(), TimeLimiterRegistry.ofDefaults(), + new Resilience4jBulkheadProvider(ThreadPoolBulkheadRegistry.ofDefaults(), + BulkheadRegistry.ofDefaults())).create("foo", "groupFoo"); assertThat((String) cb.run(() -> { throw new RuntimeException("boom"); }, t -> "fallback")).isEqualTo("fallback"); } + } diff --git a/spring-cloud-circuitbreaker-spring-retry/pom.xml b/spring-cloud-circuitbreaker-spring-retry/pom.xml index cd32e58..5726d7a 100644 --- a/spring-cloud-circuitbreaker-spring-retry/pom.xml +++ b/spring-cloud-circuitbreaker-spring-retry/pom.xml @@ -5,7 +5,7 @@ spring-cloud-circuitbreaker org.springframework.cloud - 1.0.5.BUILD-SNAPSHOT + 1.0.5.RELEASE 4.0.0 diff --git a/spring-cloud-starter-circuitbreaker/pom.xml b/spring-cloud-starter-circuitbreaker/pom.xml index 3a2910f..c1c376f 100644 --- a/spring-cloud-starter-circuitbreaker/pom.xml +++ b/spring-cloud-starter-circuitbreaker/pom.xml @@ -5,7 +5,7 @@ spring-cloud-circuitbreaker org.springframework.cloud - 1.0.5.BUILD-SNAPSHOT + 1.0.5.RELEASE 4.0.0 diff --git a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-reactor-resilience4j/pom.xml b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-reactor-resilience4j/pom.xml index 030959d..cd6265a 100644 --- a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-reactor-resilience4j/pom.xml +++ b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-reactor-resilience4j/pom.xml @@ -5,7 +5,7 @@ spring-cloud-starter-circuitbreaker org.springframework.cloud - 1.0.5.BUILD-SNAPSHOT + 1.0.5.RELEASE 4.0.0 diff --git a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-resilience4j/pom.xml b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-resilience4j/pom.xml index 1f828cd..0953c5c 100644 --- a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-resilience4j/pom.xml +++ b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-resilience4j/pom.xml @@ -5,7 +5,7 @@ spring-cloud-starter-circuitbreaker org.springframework.cloud - 1.0.5.BUILD-SNAPSHOT + 1.0.5.RELEASE 4.0.0 spring-cloud-starter-circuitbreaker-resilience4j diff --git a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-spring-retry/pom.xml b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-spring-retry/pom.xml index 4ecdb7a..9d5835b 100644 --- a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-spring-retry/pom.xml +++ b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-spring-retry/pom.xml @@ -5,7 +5,7 @@ spring-cloud-starter-circuitbreaker org.springframework.cloud - 1.0.5.BUILD-SNAPSHOT + 1.0.5.RELEASE 4.0.0 From 7ac3a31f090f4749a6ca2655051e42f89dd85b33 Mon Sep 17 00:00:00 2001 From: buildmaster Date: Wed, 21 Apr 2021 17:18:45 +0000 Subject: [PATCH 3/5] Going back to snapshots --- README.adoc | 104 ++++-------------- docs/pom.xml | 2 +- pom.xml | 6 +- .../pom.xml | 4 +- .../pom.xml | 2 +- .../Resilience4JCircuitBreaker.java | 33 +++--- .../Resilience4JCircuitBreakerFactory.java | 18 ++- .../Resilience4jBulkheadProvider.java | 12 +- ...lience4JCircuitBreakerIntegrationTest.java | 12 +- .../Resilience4JCircuitBreakerTest.java | 25 ++--- .../pom.xml | 2 +- spring-cloud-starter-circuitbreaker/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- 15 files changed, 70 insertions(+), 158 deletions(-) diff --git a/README.adoc b/README.adoc index f0d352d..1315b63 100644 --- a/README.adoc +++ b/README.adoc @@ -138,100 +138,34 @@ public Customizer slowCusomtizer() { ---- ==== -==== Bulkhead pattern supporting -If `resilience4j-bulkhead` is on the classpath, Spring Cloud CircuitBreaker will wrap all methods with a Resilience4j Bulkhead. -You can disable the Resilience4j Bulkhead by setting `spring.cloud.circuitbreaker.bulkhead.resilience4j.enabled` to `false`. -Spring Cloud CircuitBreaker Resilience4j provides two implementation of bulkhead pattern: +==== Properties Configuration -* a `SemaphoreBulkhead` which uses Semaphores -* a `FixedThreadPoolBulkhead` which uses a bounded queue and a fixed thread pool. - -By default, Spring Cloud CircuitBreaker Resilience4j uses `FixedThreadPoolBulkhead`. For more information on implementation -of Bulkhead patterns see the https://resilience4j.readme.io/docs/bulkhead[Resilience4j Bulkhead]. - -The `Customizer` can be used to provide a default `Bulkhead` and `ThreadPoolBulkhead` configuration. - -==== -[source,java] ----- -@Bean -public Customizer defaultBulkheadCustomizer() { - return provider -> provider.configureDefault(id -> new Resilience4jBulkheadConfigurationBuilder() - .bulkheadConfig(BulkheadConfig.custom().maxConcurrentCalls(4).build()) - .threadPoolBulkheadConfig(ThreadPoolBulkheadConfig.custom().coreThreadPoolSize(1).maxThreadPoolSize(1).build()) - .build() -); -} ----- -==== - -==== Specific Bulkhead Configuration - -Similarly to proving a default 'Bulkhead' or 'ThreadPoolBulkhead' configuration, you can create a `Customize` bean this -is passed a `Resilience4jBulkheadProvider`. - -==== -[source,java] ----- -@Bean -public Customizer slowBulkheadProviderCustomizer() { - return provider -> provider.configure(builder -> builder - .bulkheadConfig(BulkheadConfig.custom().maxConcurrentCalls(1).build()) - .threadPoolBulkheadConfig(ThreadPoolBulkheadConfig.ofDefaults()), "slowBulkhead"); -} ----- -==== - -In addition to configuring the Bulkhead that is created you can also customize the bulkhead and thread pool bulkhead after they -have been created but before they are returned to caller. To do this you can use the `addBulkheadCustomizer` and `addThreadPoolBulkheadCustomizer` -methods. - -===== Bulkhead Example - -==== -[source,java] ----- -@Bean -public Customizer customizer() { - return provider -> provider.addBulkheadCustomizer(bulkhead -> bulkhead.getEventPublisher() - .onCallRejected(slowRejectedConsumer) - .onCallFinished(slowFinishedConsumer), "slowBulkhead"); -} ----- -==== - -===== Thread Pool Bulkhead Example - -==== -[source,java] ----- -@Bean -public Customizer slowThreadPoolBulkheadCustomizer() { - return provider -> provider.addThreadPoolBulkheadCustomizer(threadPoolBulkhead -> threadPoolBulkhead.getEventPublisher() - .onCallRejected(slowThreadPoolRejectedConsumer) - .onCallFinished(slowThreadPoolFinishedConsumer), "slowThreadPoolBulkhead"); -} ----- -==== - -==== Bulkhead Properties Configuration - -You can configure ThreadPoolBulkhead and SemaphoreBulkhead instances in your application's configuration properties file. -Property configuration has higher priority than Java `Customizer` configuration. +You can configure CircuitBreaker and TimeLimiter instances in your application's configuration properties file. Property configuration has higher priority than Java `Customizer` configuration. ==== [source] ---- -resilience4j.thread-pool-bulkhead: +resilience4j.circuitbreaker: instances: backendA: - maxThreadPoolSize: 1 - coreThreadPoolSize: 1 -resilience4j.bulkhead: - instances: + registerHealthIndicator: true + slidingWindowSize: 100 backendB: - maxConcurrentCalls: 10 + registerHealthIndicator: true + slidingWindowSize: 10 + permittedNumberOfCallsInHalfOpenState: 3 + slidingWindowType: TIME_BASED + recordFailurePredicate: io.github.robwin.exception.RecordFailurePredicate + +resilience4j.timelimiter: + instances: + backendA: + timeoutDuration: 2s + cancelRunningFuture: true + backendB: + timeoutDuration: 1s + cancelRunningFuture: false ---- ==== diff --git a/docs/pom.xml b/docs/pom.xml index 2cab78c..58f8b78 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -5,7 +5,7 @@ spring-cloud-circuitbreaker org.springframework.cloud - 1.0.5.RELEASE + 1.0.5.BUILD-SNAPSHOT 4.0.0 diff --git a/pom.xml b/pom.xml index 380d9a2..2a3869e 100644 --- a/pom.xml +++ b/pom.xml @@ -6,12 +6,12 @@ spring-cloud-circuitbreaker pom - 1.0.5.RELEASE + 1.0.5.BUILD-SNAPSHOT org.springframework.cloud spring-cloud-build - 2.3.4.RELEASE + 2.3.2.BUILD-SNAPSHOT @@ -21,7 +21,7 @@ reuseReports ${project.basedir}/../target/jacoco.exec java - 2.2.8.RELEASE + 2.2.8.BUILD-SNAPSHOT diff --git a/spring-cloud-circuitbreaker-dependencies/pom.xml b/spring-cloud-circuitbreaker-dependencies/pom.xml index 6ed54d4..b0a1cb8 100644 --- a/spring-cloud-circuitbreaker-dependencies/pom.xml +++ b/spring-cloud-circuitbreaker-dependencies/pom.xml @@ -7,12 +7,12 @@ spring-cloud-dependencies-parent org.springframework.cloud - 2.3.4.RELEASE + 2.3.2.BUILD-SNAPSHOT spring-cloud-circuitbreaker-dependencies - 1.0.5.RELEASE + 1.0.5.BUILD-SNAPSHOT pom spring-cloud-circuitbreaker-dependencies Spring Cloud Circuit Breaker Dependencies diff --git a/spring-cloud-circuitbreaker-resilience4j/pom.xml b/spring-cloud-circuitbreaker-resilience4j/pom.xml index 73a09f4..8cb8c7a 100644 --- a/spring-cloud-circuitbreaker-resilience4j/pom.xml +++ b/spring-cloud-circuitbreaker-resilience4j/pom.xml @@ -5,7 +5,7 @@ spring-cloud-circuitbreaker org.springframework.cloud - 1.0.5.RELEASE + 1.0.5.BUILD-SNAPSHOT .. 4.0.0 diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java index 2fb9ec4..a16518d 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java @@ -83,18 +83,18 @@ public class Resilience4JCircuitBreaker implements CircuitBreaker { TimeLimiterRegistry timeLimiterRegistry, ExecutorService executorService, Optional> circuitBreakerCustomizer, Resilience4jBulkheadProvider bulkheadProvider) { - this(id, id, circuitBreakerConfig, timeLimiterConfig, circuitBreakerRegistry, - timeLimiterRegistry, executorService, circuitBreakerCustomizer, - bulkheadProvider); + this(id, id, circuitBreakerConfig, timeLimiterConfig, circuitBreakerRegistry, timeLimiterRegistry, executorService, + circuitBreakerCustomizer, bulkheadProvider); } - public Resilience4JCircuitBreaker(String id, String groupName, - io.github.resilience4j.circuitbreaker.CircuitBreakerConfig circuitBreakerConfig, - TimeLimiterConfig timeLimiterConfig, - CircuitBreakerRegistry circuitBreakerRegistry, - TimeLimiterRegistry timeLimiterRegistry, ExecutorService executorService, - Optional> circuitBreakerCustomizer, - Resilience4jBulkheadProvider bulkheadProvider) { + public Resilience4JCircuitBreaker(String id, + String groupName, + io.github.resilience4j.circuitbreaker.CircuitBreakerConfig circuitBreakerConfig, + TimeLimiterConfig timeLimiterConfig, + CircuitBreakerRegistry circuitBreakerRegistry, + TimeLimiterRegistry timeLimiterRegistry, ExecutorService executorService, + Optional> circuitBreakerCustomizer, + Resilience4jBulkheadProvider bulkheadProvider) { this.id = id; this.groupName = groupName; this.circuitBreakerConfig = circuitBreakerConfig; @@ -108,10 +108,8 @@ public class Resilience4JCircuitBreaker implements CircuitBreaker { @Override public T run(Supplier toRun, Function fallback) { - final io.vavr.collection.Map tags = io.vavr.collection.HashMap - .of(CIRCUIT_BREAKER_GROUP_TAG, this.groupName); - TimeLimiter timeLimiter = timeLimiterRegistry.timeLimiter(id, timeLimiterConfig, - tags); + final io.vavr.collection.Map tags = io.vavr.collection.HashMap.of(CIRCUIT_BREAKER_GROUP_TAG, this.groupName); + TimeLimiter timeLimiter = timeLimiterRegistry.timeLimiter(id, timeLimiterConfig, tags); Supplier> futureSupplier = () -> executorService.submit(toRun::get); Callable restrictedCall = TimeLimiter.decorateFutureSupplier(timeLimiter, futureSupplier); @@ -121,10 +119,9 @@ public class Resilience4JCircuitBreaker implements CircuitBreaker { .ifPresent(customizer -> customizer.customize(defaultCircuitBreaker)); if (bulkheadProvider != null) { - return bulkheadProvider.run(this.groupName, toRun, fallback, - defaultCircuitBreaker, timeLimiter, tags); - } - else { + return bulkheadProvider.run(this.groupName, toRun, fallback, defaultCircuitBreaker, + timeLimiter, tags); + } else { Callable callable = io.github.resilience4j.circuitbreaker.CircuitBreaker .decorateCallable(defaultCircuitBreaker, restrictedCall); return Try.of(callable::call).recover(fallback).get(); diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java index 0966274..7de0e2a 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java @@ -116,8 +116,7 @@ public class Resilience4JCircuitBreakerFactory extends public Resilience4JCircuitBreaker create(String id, String groupName) { Assert.hasText(id, "A CircuitBreaker must have an id."); Assert.hasText(groupName, "A CircuitBreaker must have a group name."); - final ExecutorService groupExecutorService = executorServices - .computeIfAbsent(groupName, group -> Executors.newCachedThreadPool()); + final ExecutorService groupExecutorService = executorServices.computeIfAbsent(groupName, group -> Executors.newCachedThreadPool()); return create(id, groupName, groupExecutorService); } @@ -128,15 +127,12 @@ public class Resilience4JCircuitBreakerFactory extends } } - private Resilience4JCircuitBreaker create(String id, String groupName, - ExecutorService circuitBreakerExecutorService) { + private Resilience4JCircuitBreaker create(String id, String groupName, ExecutorService circuitBreakerExecutorService) { Resilience4JConfigBuilder.Resilience4JCircuitBreakerConfiguration config = getConfigurations() - .computeIfAbsent(id, defaultConfiguration); - return new Resilience4JCircuitBreaker(id, groupName, - config.getCircuitBreakerConfig(), config.getTimeLimiterConfig(), - circuitBreakerRegistry, timeLimiterRegistry, - circuitBreakerExecutorService, - Optional.ofNullable(circuitBreakerCustomizers.get(id)), bulkheadProvider); + .computeIfAbsent(id, defaultConfiguration); + return new Resilience4JCircuitBreaker(id, groupName, config.getCircuitBreakerConfig(), + config.getTimeLimiterConfig(), circuitBreakerRegistry, + timeLimiterRegistry, circuitBreakerExecutorService, + Optional.ofNullable(circuitBreakerCustomizers.get(id)), bulkheadProvider); } - } diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4jBulkheadProvider.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4jBulkheadProvider.java index fdd59ca..ea8037d 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4jBulkheadProvider.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4jBulkheadProvider.java @@ -106,10 +106,8 @@ public class Resilience4jBulkheadProvider { } public T run(String groupName, Supplier toRun, Function fallback, - CircuitBreaker circuitBreaker, TimeLimiter timeLimiter, - io.vavr.collection.Map tags) { - Supplier> bulkheadCall = decorateBulkhead(groupName, tags, - toRun); + CircuitBreaker circuitBreaker, TimeLimiter timeLimiter, io.vavr.collection.Map tags) { + Supplier> bulkheadCall = decorateBulkhead(groupName, tags, toRun); final Callable timeLimiterCall = decorateTimeLimiter(bulkheadCall, timeLimiter); final Callable circuitBreakerCall = circuitBreaker @@ -117,16 +115,14 @@ public class Resilience4jBulkheadProvider { return Try.of(circuitBreakerCall::call).recover(fallback).get(); } - private Supplier> decorateBulkhead(final String id, - final io.vavr.collection.Map tags, + private Supplier> decorateBulkhead(final String id, final io.vavr.collection.Map tags, final Supplier supplier) { Resilience4jBulkheadConfigurationBuilder.BulkheadConfiguration configuration = configurations .computeIfAbsent(id, defaultConfiguration); if (bulkheadRegistry.find(id).isPresent() && !threadPoolBulkheadRegistry.find(id).isPresent()) { - Bulkhead bulkhead = bulkheadRegistry.bulkhead(id, - configuration.getBulkheadConfig(), tags); + Bulkhead bulkhead = bulkheadRegistry.bulkhead(id, configuration.getBulkheadConfig(), tags); CompletableFuture asyncCall = CompletableFuture.supplyAsync(supplier); return Bulkhead.decorateCompletionStage(bulkhead, () -> asyncCall); } diff --git a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java index 2d23fb6..710558c 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java @@ -109,15 +109,9 @@ public class Resilience4JCircuitBreakerIntegrationTest { assertThat(((List) rest.getForObject("/actuator/metrics", Map.class).get("names")) .contains("resilience4j.circuitbreaker.calls")).isTrue(); - // CircuitBreaker and TimeLimiter should have 3 metrics: name, kind, group - assertThat(((List) rest - .getForObject("/actuator/metrics/resilience4j.circuitbreaker.calls", - Map.class) - .get("availableTags"))).hasSize(3); - assertThat(((List) rest - .getForObject("/actuator/metrics/resilience4j.timelimiter.calls", - Map.class) - .get("availableTags"))).hasSize(3); + //CircuitBreaker and TimeLimiter should have 3 metrics: name, kind, group + assertThat(((List) rest.getForObject("/actuator/metrics/resilience4j.circuitbreaker.calls", Map.class).get("availableTags"))).hasSize(3); + assertThat(((List) rest.getForObject("/actuator/metrics/resilience4j.timelimiter.calls", Map.class).get("availableTags"))).hasSize(3); } @Configuration(proxyBeanMethods = false) diff --git a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java index 6e3c843..a21e2ff 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java @@ -42,9 +42,8 @@ public class Resilience4JCircuitBreakerTest { @Test public void runWithGroupName() { - CircuitBreaker cb = new Resilience4JCircuitBreakerFactory( - CircuitBreakerRegistry.ofDefaults(), TimeLimiterRegistry.ofDefaults(), - null).create("foo", "groupFoo"); + CircuitBreaker cb = new Resilience4JCircuitBreakerFactory(CircuitBreakerRegistry.ofDefaults(), + TimeLimiterRegistry.ofDefaults(), null).create("foo", "groupFoo"); assertThat(cb.run(() -> "foobar")).isEqualTo("foobar"); } @@ -61,9 +60,8 @@ public class Resilience4JCircuitBreakerTest { @Test public void runWithFallbackAndGroupName() { - CircuitBreaker cb = new Resilience4JCircuitBreakerFactory( - CircuitBreakerRegistry.ofDefaults(), TimeLimiterRegistry.ofDefaults(), - null).create("foo", "groupFoo"); + CircuitBreaker cb = new Resilience4JCircuitBreakerFactory(CircuitBreakerRegistry.ofDefaults(), + TimeLimiterRegistry.ofDefaults(), null).create("foo", "groupFoo"); assertThat((String) cb.run(() -> { throw new RuntimeException("boom"); }, t -> "fallback")).isEqualTo("fallback"); @@ -80,10 +78,9 @@ public class Resilience4JCircuitBreakerTest { @Test public void runWithBulkheadProviderAndGroupName() { - CircuitBreaker cb = new Resilience4JCircuitBreakerFactory( - CircuitBreakerRegistry.ofDefaults(), TimeLimiterRegistry.ofDefaults(), - new Resilience4jBulkheadProvider(ThreadPoolBulkheadRegistry.ofDefaults(), - BulkheadRegistry.ofDefaults())).create("foo", "groupFoo"); + CircuitBreaker cb = new Resilience4JCircuitBreakerFactory(CircuitBreakerRegistry.ofDefaults(), + TimeLimiterRegistry.ofDefaults(), new Resilience4jBulkheadProvider( + ThreadPoolBulkheadRegistry.ofDefaults(), BulkheadRegistry.ofDefaults())).create("foo", "groupFoo"); assertThat(cb.run(() -> "foobar")).isEqualTo("foobar"); } @@ -100,13 +97,11 @@ public class Resilience4JCircuitBreakerTest { @Test public void runWithFallbackBulkheadProviderAndGroupName() { - CircuitBreaker cb = new Resilience4JCircuitBreakerFactory( - CircuitBreakerRegistry.ofDefaults(), TimeLimiterRegistry.ofDefaults(), - new Resilience4jBulkheadProvider(ThreadPoolBulkheadRegistry.ofDefaults(), - BulkheadRegistry.ofDefaults())).create("foo", "groupFoo"); + CircuitBreaker cb = new Resilience4JCircuitBreakerFactory(CircuitBreakerRegistry.ofDefaults(), + TimeLimiterRegistry.ofDefaults(), new Resilience4jBulkheadProvider( + ThreadPoolBulkheadRegistry.ofDefaults(), BulkheadRegistry.ofDefaults())).create("foo", "groupFoo"); assertThat((String) cb.run(() -> { throw new RuntimeException("boom"); }, t -> "fallback")).isEqualTo("fallback"); } - } diff --git a/spring-cloud-circuitbreaker-spring-retry/pom.xml b/spring-cloud-circuitbreaker-spring-retry/pom.xml index 5726d7a..cd32e58 100644 --- a/spring-cloud-circuitbreaker-spring-retry/pom.xml +++ b/spring-cloud-circuitbreaker-spring-retry/pom.xml @@ -5,7 +5,7 @@ spring-cloud-circuitbreaker org.springframework.cloud - 1.0.5.RELEASE + 1.0.5.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-starter-circuitbreaker/pom.xml b/spring-cloud-starter-circuitbreaker/pom.xml index c1c376f..3a2910f 100644 --- a/spring-cloud-starter-circuitbreaker/pom.xml +++ b/spring-cloud-starter-circuitbreaker/pom.xml @@ -5,7 +5,7 @@ spring-cloud-circuitbreaker org.springframework.cloud - 1.0.5.RELEASE + 1.0.5.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-reactor-resilience4j/pom.xml b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-reactor-resilience4j/pom.xml index cd6265a..030959d 100644 --- a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-reactor-resilience4j/pom.xml +++ b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-reactor-resilience4j/pom.xml @@ -5,7 +5,7 @@ spring-cloud-starter-circuitbreaker org.springframework.cloud - 1.0.5.RELEASE + 1.0.5.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-resilience4j/pom.xml b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-resilience4j/pom.xml index 0953c5c..1f828cd 100644 --- a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-resilience4j/pom.xml +++ b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-resilience4j/pom.xml @@ -5,7 +5,7 @@ spring-cloud-starter-circuitbreaker org.springframework.cloud - 1.0.5.RELEASE + 1.0.5.BUILD-SNAPSHOT 4.0.0 spring-cloud-starter-circuitbreaker-resilience4j diff --git a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-spring-retry/pom.xml b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-spring-retry/pom.xml index 9d5835b..4ecdb7a 100644 --- a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-spring-retry/pom.xml +++ b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-spring-retry/pom.xml @@ -5,7 +5,7 @@ spring-cloud-starter-circuitbreaker org.springframework.cloud - 1.0.5.RELEASE + 1.0.5.BUILD-SNAPSHOT 4.0.0 From b737c502c0998fdcffebf78731537d19fccf4d67 Mon Sep 17 00:00:00 2001 From: buildmaster Date: Wed, 21 Apr 2021 17:18:45 +0000 Subject: [PATCH 4/5] Bumping versions to 1.0.6.BUILD-SNAPSHOT after release --- docs/pom.xml | 2 +- pom.xml | 6 +++--- spring-cloud-circuitbreaker-dependencies/pom.xml | 4 ++-- spring-cloud-circuitbreaker-resilience4j/pom.xml | 2 +- spring-cloud-circuitbreaker-spring-retry/pom.xml | 2 +- spring-cloud-starter-circuitbreaker/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/pom.xml b/docs/pom.xml index 58f8b78..74066a7 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -5,7 +5,7 @@ spring-cloud-circuitbreaker org.springframework.cloud - 1.0.5.BUILD-SNAPSHOT + 1.0.6.BUILD-SNAPSHOT 4.0.0 diff --git a/pom.xml b/pom.xml index 2a3869e..992cc01 100644 --- a/pom.xml +++ b/pom.xml @@ -6,12 +6,12 @@ spring-cloud-circuitbreaker pom - 1.0.5.BUILD-SNAPSHOT + 1.0.6.BUILD-SNAPSHOT org.springframework.cloud spring-cloud-build - 2.3.2.BUILD-SNAPSHOT + 2.3.4.RELEASE @@ -21,7 +21,7 @@ reuseReports ${project.basedir}/../target/jacoco.exec java - 2.2.8.BUILD-SNAPSHOT + 2.2.9.BUILD-SNAPSHOT diff --git a/spring-cloud-circuitbreaker-dependencies/pom.xml b/spring-cloud-circuitbreaker-dependencies/pom.xml index b0a1cb8..99526e2 100644 --- a/spring-cloud-circuitbreaker-dependencies/pom.xml +++ b/spring-cloud-circuitbreaker-dependencies/pom.xml @@ -7,12 +7,12 @@ spring-cloud-dependencies-parent org.springframework.cloud - 2.3.2.BUILD-SNAPSHOT + 2.3.5.BUILD-SNAPSHOT spring-cloud-circuitbreaker-dependencies - 1.0.5.BUILD-SNAPSHOT + 1.0.6.BUILD-SNAPSHOT pom spring-cloud-circuitbreaker-dependencies Spring Cloud Circuit Breaker Dependencies diff --git a/spring-cloud-circuitbreaker-resilience4j/pom.xml b/spring-cloud-circuitbreaker-resilience4j/pom.xml index 8cb8c7a..23a0aa4 100644 --- a/spring-cloud-circuitbreaker-resilience4j/pom.xml +++ b/spring-cloud-circuitbreaker-resilience4j/pom.xml @@ -5,7 +5,7 @@ spring-cloud-circuitbreaker org.springframework.cloud - 1.0.5.BUILD-SNAPSHOT + 1.0.6.BUILD-SNAPSHOT .. 4.0.0 diff --git a/spring-cloud-circuitbreaker-spring-retry/pom.xml b/spring-cloud-circuitbreaker-spring-retry/pom.xml index cd32e58..fa88d60 100644 --- a/spring-cloud-circuitbreaker-spring-retry/pom.xml +++ b/spring-cloud-circuitbreaker-spring-retry/pom.xml @@ -5,7 +5,7 @@ spring-cloud-circuitbreaker org.springframework.cloud - 1.0.5.BUILD-SNAPSHOT + 1.0.6.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-starter-circuitbreaker/pom.xml b/spring-cloud-starter-circuitbreaker/pom.xml index 3a2910f..627a8c6 100644 --- a/spring-cloud-starter-circuitbreaker/pom.xml +++ b/spring-cloud-starter-circuitbreaker/pom.xml @@ -5,7 +5,7 @@ spring-cloud-circuitbreaker org.springframework.cloud - 1.0.5.BUILD-SNAPSHOT + 1.0.6.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-reactor-resilience4j/pom.xml b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-reactor-resilience4j/pom.xml index 030959d..6abee46 100644 --- a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-reactor-resilience4j/pom.xml +++ b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-reactor-resilience4j/pom.xml @@ -5,7 +5,7 @@ spring-cloud-starter-circuitbreaker org.springframework.cloud - 1.0.5.BUILD-SNAPSHOT + 1.0.6.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-resilience4j/pom.xml b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-resilience4j/pom.xml index 1f828cd..1358af2 100644 --- a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-resilience4j/pom.xml +++ b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-resilience4j/pom.xml @@ -5,7 +5,7 @@ spring-cloud-starter-circuitbreaker org.springframework.cloud - 1.0.5.BUILD-SNAPSHOT + 1.0.6.BUILD-SNAPSHOT 4.0.0 spring-cloud-starter-circuitbreaker-resilience4j diff --git a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-spring-retry/pom.xml b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-spring-retry/pom.xml index 4ecdb7a..ef4e705 100644 --- a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-spring-retry/pom.xml +++ b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-spring-retry/pom.xml @@ -5,7 +5,7 @@ spring-cloud-starter-circuitbreaker org.springframework.cloud - 1.0.5.BUILD-SNAPSHOT + 1.0.6.BUILD-SNAPSHOT 4.0.0 From 9e5859f9c9323afb6fb84f6141475fd2f293dbb5 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Wed, 21 Apr 2021 16:31:42 -0400 Subject: [PATCH 5/5] Add link to spring cloud commons API docs. Fixes #106 --- .../asciidoc/spring-cloud-circuitbreaker.adoc | 6 ++++ .../Resilience4JCircuitBreaker.java | 33 ++++++++++--------- .../Resilience4JCircuitBreakerFactory.java | 18 ++++++---- .../Resilience4jBulkheadProvider.java | 12 ++++--- ...lience4JCircuitBreakerIntegrationTest.java | 12 +++++-- .../Resilience4JCircuitBreakerTest.java | 25 ++++++++------ 6 files changed, 67 insertions(+), 39 deletions(-) diff --git a/docs/src/main/asciidoc/spring-cloud-circuitbreaker.adoc b/docs/src/main/asciidoc/spring-cloud-circuitbreaker.adoc index 6223eeb..0047220 100755 --- a/docs/src/main/asciidoc/spring-cloud-circuitbreaker.adoc +++ b/docs/src/main/asciidoc/spring-cloud-circuitbreaker.adoc @@ -3,6 +3,12 @@ include::_attributes.adoc[] *{spring-cloud-version}* +## Usage Documentation + +The Spring Cloud CircuitBreaker project contains implementations for Resilience4J and Spring Retry. +The APIs implemented in Spring Cloud CircuitBreaker live in Spring Cloud Commons. The usage documentation +for these APIs are located in the https://docs.spring.io/spring-cloud-commons/docs/current/reference/html/#spring-cloud-circuit-breake[Spring Cloud Commons documentation]. + include::spring-cloud-circuitbreaker-resilience4j.adoc[] include::spring-cloud-circuitbreaker-spring-retry.adoc[] diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java index a16518d..2fb9ec4 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java @@ -83,18 +83,18 @@ public class Resilience4JCircuitBreaker implements CircuitBreaker { TimeLimiterRegistry timeLimiterRegistry, ExecutorService executorService, Optional> circuitBreakerCustomizer, Resilience4jBulkheadProvider bulkheadProvider) { - this(id, id, circuitBreakerConfig, timeLimiterConfig, circuitBreakerRegistry, timeLimiterRegistry, executorService, - circuitBreakerCustomizer, bulkheadProvider); + this(id, id, circuitBreakerConfig, timeLimiterConfig, circuitBreakerRegistry, + timeLimiterRegistry, executorService, circuitBreakerCustomizer, + bulkheadProvider); } - public Resilience4JCircuitBreaker(String id, - String groupName, - io.github.resilience4j.circuitbreaker.CircuitBreakerConfig circuitBreakerConfig, - TimeLimiterConfig timeLimiterConfig, - CircuitBreakerRegistry circuitBreakerRegistry, - TimeLimiterRegistry timeLimiterRegistry, ExecutorService executorService, - Optional> circuitBreakerCustomizer, - Resilience4jBulkheadProvider bulkheadProvider) { + public Resilience4JCircuitBreaker(String id, String groupName, + io.github.resilience4j.circuitbreaker.CircuitBreakerConfig circuitBreakerConfig, + TimeLimiterConfig timeLimiterConfig, + CircuitBreakerRegistry circuitBreakerRegistry, + TimeLimiterRegistry timeLimiterRegistry, ExecutorService executorService, + Optional> circuitBreakerCustomizer, + Resilience4jBulkheadProvider bulkheadProvider) { this.id = id; this.groupName = groupName; this.circuitBreakerConfig = circuitBreakerConfig; @@ -108,8 +108,10 @@ public class Resilience4JCircuitBreaker implements CircuitBreaker { @Override public T run(Supplier toRun, Function fallback) { - final io.vavr.collection.Map tags = io.vavr.collection.HashMap.of(CIRCUIT_BREAKER_GROUP_TAG, this.groupName); - TimeLimiter timeLimiter = timeLimiterRegistry.timeLimiter(id, timeLimiterConfig, tags); + final io.vavr.collection.Map tags = io.vavr.collection.HashMap + .of(CIRCUIT_BREAKER_GROUP_TAG, this.groupName); + TimeLimiter timeLimiter = timeLimiterRegistry.timeLimiter(id, timeLimiterConfig, + tags); Supplier> futureSupplier = () -> executorService.submit(toRun::get); Callable restrictedCall = TimeLimiter.decorateFutureSupplier(timeLimiter, futureSupplier); @@ -119,9 +121,10 @@ public class Resilience4JCircuitBreaker implements CircuitBreaker { .ifPresent(customizer -> customizer.customize(defaultCircuitBreaker)); if (bulkheadProvider != null) { - return bulkheadProvider.run(this.groupName, toRun, fallback, defaultCircuitBreaker, - timeLimiter, tags); - } else { + return bulkheadProvider.run(this.groupName, toRun, fallback, + defaultCircuitBreaker, timeLimiter, tags); + } + else { Callable callable = io.github.resilience4j.circuitbreaker.CircuitBreaker .decorateCallable(defaultCircuitBreaker, restrictedCall); return Try.of(callable::call).recover(fallback).get(); diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java index 7de0e2a..0966274 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java @@ -116,7 +116,8 @@ public class Resilience4JCircuitBreakerFactory extends public Resilience4JCircuitBreaker create(String id, String groupName) { Assert.hasText(id, "A CircuitBreaker must have an id."); Assert.hasText(groupName, "A CircuitBreaker must have a group name."); - final ExecutorService groupExecutorService = executorServices.computeIfAbsent(groupName, group -> Executors.newCachedThreadPool()); + final ExecutorService groupExecutorService = executorServices + .computeIfAbsent(groupName, group -> Executors.newCachedThreadPool()); return create(id, groupName, groupExecutorService); } @@ -127,12 +128,15 @@ public class Resilience4JCircuitBreakerFactory extends } } - private Resilience4JCircuitBreaker create(String id, String groupName, ExecutorService circuitBreakerExecutorService) { + private Resilience4JCircuitBreaker create(String id, String groupName, + ExecutorService circuitBreakerExecutorService) { Resilience4JConfigBuilder.Resilience4JCircuitBreakerConfiguration config = getConfigurations() - .computeIfAbsent(id, defaultConfiguration); - return new Resilience4JCircuitBreaker(id, groupName, config.getCircuitBreakerConfig(), - config.getTimeLimiterConfig(), circuitBreakerRegistry, - timeLimiterRegistry, circuitBreakerExecutorService, - Optional.ofNullable(circuitBreakerCustomizers.get(id)), bulkheadProvider); + .computeIfAbsent(id, defaultConfiguration); + return new Resilience4JCircuitBreaker(id, groupName, + config.getCircuitBreakerConfig(), config.getTimeLimiterConfig(), + circuitBreakerRegistry, timeLimiterRegistry, + circuitBreakerExecutorService, + Optional.ofNullable(circuitBreakerCustomizers.get(id)), bulkheadProvider); } + } diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4jBulkheadProvider.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4jBulkheadProvider.java index ea8037d..fdd59ca 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4jBulkheadProvider.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4jBulkheadProvider.java @@ -106,8 +106,10 @@ public class Resilience4jBulkheadProvider { } public T run(String groupName, Supplier toRun, Function fallback, - CircuitBreaker circuitBreaker, TimeLimiter timeLimiter, io.vavr.collection.Map tags) { - Supplier> bulkheadCall = decorateBulkhead(groupName, tags, toRun); + CircuitBreaker circuitBreaker, TimeLimiter timeLimiter, + io.vavr.collection.Map tags) { + Supplier> bulkheadCall = decorateBulkhead(groupName, tags, + toRun); final Callable timeLimiterCall = decorateTimeLimiter(bulkheadCall, timeLimiter); final Callable circuitBreakerCall = circuitBreaker @@ -115,14 +117,16 @@ public class Resilience4jBulkheadProvider { return Try.of(circuitBreakerCall::call).recover(fallback).get(); } - private Supplier> decorateBulkhead(final String id, final io.vavr.collection.Map tags, + private Supplier> decorateBulkhead(final String id, + final io.vavr.collection.Map tags, final Supplier supplier) { Resilience4jBulkheadConfigurationBuilder.BulkheadConfiguration configuration = configurations .computeIfAbsent(id, defaultConfiguration); if (bulkheadRegistry.find(id).isPresent() && !threadPoolBulkheadRegistry.find(id).isPresent()) { - Bulkhead bulkhead = bulkheadRegistry.bulkhead(id, configuration.getBulkheadConfig(), tags); + Bulkhead bulkhead = bulkheadRegistry.bulkhead(id, + configuration.getBulkheadConfig(), tags); CompletableFuture asyncCall = CompletableFuture.supplyAsync(supplier); return Bulkhead.decorateCompletionStage(bulkhead, () -> asyncCall); } diff --git a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java index 710558c..2d23fb6 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java @@ -109,9 +109,15 @@ public class Resilience4JCircuitBreakerIntegrationTest { assertThat(((List) rest.getForObject("/actuator/metrics", Map.class).get("names")) .contains("resilience4j.circuitbreaker.calls")).isTrue(); - //CircuitBreaker and TimeLimiter should have 3 metrics: name, kind, group - assertThat(((List) rest.getForObject("/actuator/metrics/resilience4j.circuitbreaker.calls", Map.class).get("availableTags"))).hasSize(3); - assertThat(((List) rest.getForObject("/actuator/metrics/resilience4j.timelimiter.calls", Map.class).get("availableTags"))).hasSize(3); + // CircuitBreaker and TimeLimiter should have 3 metrics: name, kind, group + assertThat(((List) rest + .getForObject("/actuator/metrics/resilience4j.circuitbreaker.calls", + Map.class) + .get("availableTags"))).hasSize(3); + assertThat(((List) rest + .getForObject("/actuator/metrics/resilience4j.timelimiter.calls", + Map.class) + .get("availableTags"))).hasSize(3); } @Configuration(proxyBeanMethods = false) diff --git a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java index a21e2ff..6e3c843 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java @@ -42,8 +42,9 @@ public class Resilience4JCircuitBreakerTest { @Test public void runWithGroupName() { - CircuitBreaker cb = new Resilience4JCircuitBreakerFactory(CircuitBreakerRegistry.ofDefaults(), - TimeLimiterRegistry.ofDefaults(), null).create("foo", "groupFoo"); + CircuitBreaker cb = new Resilience4JCircuitBreakerFactory( + CircuitBreakerRegistry.ofDefaults(), TimeLimiterRegistry.ofDefaults(), + null).create("foo", "groupFoo"); assertThat(cb.run(() -> "foobar")).isEqualTo("foobar"); } @@ -60,8 +61,9 @@ public class Resilience4JCircuitBreakerTest { @Test public void runWithFallbackAndGroupName() { - CircuitBreaker cb = new Resilience4JCircuitBreakerFactory(CircuitBreakerRegistry.ofDefaults(), - TimeLimiterRegistry.ofDefaults(), null).create("foo", "groupFoo"); + CircuitBreaker cb = new Resilience4JCircuitBreakerFactory( + CircuitBreakerRegistry.ofDefaults(), TimeLimiterRegistry.ofDefaults(), + null).create("foo", "groupFoo"); assertThat((String) cb.run(() -> { throw new RuntimeException("boom"); }, t -> "fallback")).isEqualTo("fallback"); @@ -78,9 +80,10 @@ public class Resilience4JCircuitBreakerTest { @Test public void runWithBulkheadProviderAndGroupName() { - CircuitBreaker cb = new Resilience4JCircuitBreakerFactory(CircuitBreakerRegistry.ofDefaults(), - TimeLimiterRegistry.ofDefaults(), new Resilience4jBulkheadProvider( - ThreadPoolBulkheadRegistry.ofDefaults(), BulkheadRegistry.ofDefaults())).create("foo", "groupFoo"); + CircuitBreaker cb = new Resilience4JCircuitBreakerFactory( + CircuitBreakerRegistry.ofDefaults(), TimeLimiterRegistry.ofDefaults(), + new Resilience4jBulkheadProvider(ThreadPoolBulkheadRegistry.ofDefaults(), + BulkheadRegistry.ofDefaults())).create("foo", "groupFoo"); assertThat(cb.run(() -> "foobar")).isEqualTo("foobar"); } @@ -97,11 +100,13 @@ public class Resilience4JCircuitBreakerTest { @Test public void runWithFallbackBulkheadProviderAndGroupName() { - CircuitBreaker cb = new Resilience4JCircuitBreakerFactory(CircuitBreakerRegistry.ofDefaults(), - TimeLimiterRegistry.ofDefaults(), new Resilience4jBulkheadProvider( - ThreadPoolBulkheadRegistry.ofDefaults(), BulkheadRegistry.ofDefaults())).create("foo", "groupFoo"); + CircuitBreaker cb = new Resilience4JCircuitBreakerFactory( + CircuitBreakerRegistry.ofDefaults(), TimeLimiterRegistry.ofDefaults(), + new Resilience4jBulkheadProvider(ThreadPoolBulkheadRegistry.ofDefaults(), + BulkheadRegistry.ofDefaults())).create("foo", "groupFoo"); assertThat((String) cb.run(() -> { throw new RuntimeException("boom"); }, t -> "fallback")).isEqualTo("fallback"); } + }