Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding basic Failsafe support #33

Closed
68 changes: 68 additions & 0 deletions docs/src/main/asciidoc/spring-cloud-circuitbreaker-failsafe.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
=== Configuring Failsafe Circuit Breakers

Failsafe is a lightweight, zero-dependency library for handling failures in Java 8+,
with a concise API for handling everyday use cases and the flexibility to handle everything else.
Failsafe provides https://github.com/jhalterman/failsafe#circuit-breakers[circuit breakers] along side with
https://github.com/jhalterman/failsafe#retries[retries] and
https://github.com/jhalterman/failsafe#fallbacks[fallbacks], which can be composed
together to form policies which wrap the execution logic.

All circuit breakers will be created using the `Failsafe` and a combination of the default implementation of
https://github.com/jhalterman/failsafe/blob/master/src/main/java/net/jodah/failsafe/Fallback.java[`Fallback`],
https://github.com/jhalterman/failsafe/blob/master/src/main/java/net/jodah/failsafe/RetryPolicy.java[`RetryPolicy`],
https://github.com/jhalterman/failsafe/blob/master/src/main/java/net/jodah/failsafe/CircuitBreaker.java[`CircuitBreaker`] - in that order.
All these these classes can be configured using `FailsafeConfigBuilder`.

==== Default Configuration

To provide a default configuration for all of your circuit breakers create a `Customize` bean that is passed a
`FailsafeCircuitBreakerFactory`.
The `configureDefault` method can be used to provide a default configuration.

====
[source,java]
----
@Bean
public Customizer<FailsafeCircuitBreakerFactory> defaultCustomizer() {
return factory -> factory.configureDefault(id -> new FailsafeConfigBuilder(id)
.retryPolicy(new RetryPolicy<>().withMaxAttempts(2))
.build());
}
----
====

==== Specific Circuit Breaker Configuration

Similarly to providing a default configuration, you can create a `Customize` bean this is passed a
`FailsafeCircuitBreakerFactory`.

====
[source,java]
----
@Bean
public Customizer<FailsafeCircuitBreakerFactory> slowCustomizer() {
return factory -> factory.configure(
builder -> builder
.retryPolicy(new RetryPolicy<>().withMaxAttempts(1))
.circuitBreaker(new net.jodah.failsafe.CircuitBreaker<>()
.handle(Exception.class).withFailureThreshold(1)
.withDelay(Duration.ofMinutes(1)))
.build(),
"slow");
----
====

In addition to configuring the circuit breaker that is created you can also customize the circuit breaker after it
has been created but before it is returned to the caller. To do this you can use the `addFailsafeCustomizers`
method. This can be useful for adding event handlers to the `Failsafe`.

====
[source,java]
----
@Bean
public Customizer<FailsafeCircuitBreakerFactory> slowCustomizer() {
return factory -> factory.addFailsafeCustomizers(
failsafe -> failsafe.onFailure(onFailureConsumer), "slow");
}
----
====
3 changes: 3 additions & 0 deletions docs/src/main/asciidoc/spring-cloud-circuitbreaker.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ include::spring-cloud-circuitbreaker-resilience4j.adoc[]

include::spring-cloud-circuitbreaker-spring-retry.adoc[]

include::spring-cloud-circuitbreaker-failsafe.adoc[]


== Building

include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/building-jdk8.adoc[]
Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
<module>spring-cloud-starter-circuitbreaker</module>
<module>docs</module>
<module>spring-cloud-circuitbreaker-spring-retry</module>
<module>spring-cloud-circuitbreaker-failsafe</module>
</modules>
<build>
<plugins>
Expand Down
16 changes: 16 additions & 0 deletions spring-cloud-circuitbreaker-dependencies/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

<properties>
<resilience4j.version>1.1.0</resilience4j.version>
<failsafe.version>2.3.1</failsafe.version>
</properties>

<dependencyManagement>
Expand All @@ -43,6 +44,11 @@
<artifactId>resilience4j-micrometer</artifactId>
<version>${resilience4j.version}</version>
</dependency>
<dependency>
<groupId>net.jodah</groupId>
<artifactId>failsafe</artifactId>
<version>${failsafe.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-circuitbreaker-resilience4j</artifactId>
Expand All @@ -53,6 +59,11 @@
<artifactId>spring-cloud-circuitbreaker-spring-retry</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-circuitbreaker-failsafe</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
Expand All @@ -63,6 +74,11 @@
<artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-failsafe</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

Expand Down
126 changes: 126 additions & 0 deletions spring-cloud-circuitbreaker-failsafe/.flattened-pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-circuitbreaker</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-circuitbreaker-failsafe</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<description>Spring Cloud parent pom, managing plugins and dependencies for Spring
Cloud projects</description>
<url>https://spring.io/spring-cloud/spring-cloud-circuitbreaker/spring-cloud-circuitbreaker-failsafe</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>https://www.spring.io</url>
</organization>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
<comments>Copyright 2014-2015 the original author or authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.

See the License for the specific language governing permissions and
limitations under the License.</comments>
</license>
</licenses>
<developers>
<developer>
<id>dsyer</id>
<name>Dave Syer</name>
<email>dsyer at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>sgibb</id>
<name>Spencer Gibb</name>
<email>sgibb at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>mgrzejszczak</id>
<name>Marcin Grzejszczak</name>
<email>mgrzejszczak at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>rbaxter</id>
<name>Ryan Baxter</name>
<email>rbaxter at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>omaciaszeksharma</id>
<name>Olga Maciaszek-Sharma</name>
<email>omaciaszeksharma at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
</developers>
<scm>
<connection>scm:git:git://github.com/spring-cloud/spring-cloud-build.git/spring-cloud-circuitbreaker/spring-cloud-circuitbreaker-failsafe</connection>
<developerConnection>scm:git:ssh://git@github.com/spring-cloud/spring-cloud-build.git/spring-cloud-circuitbreaker/spring-cloud-circuitbreaker-failsafe</developerConnection>
<url>https://github.com/spring-cloud/spring-cloud-build/spring-cloud-circuitbreaker/spring-cloud-circuitbreaker-failsafe</url>
</scm>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.jodah</groupId>
<artifactId>failsafe</artifactId>
<version>2.3.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>
41 changes: 41 additions & 0 deletions spring-cloud-circuitbreaker-failsafe/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-circuitbreaker</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>spring-cloud-circuitbreaker-failsafe</artifactId>

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>net.jodah</groupId>
<artifactId>failsafe</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>


</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.cloud.circuitbreaker.failsafe;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;

import net.jodah.failsafe.Failsafe;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
import org.springframework.cloud.client.circuitbreaker.Customizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* @author Jakub Marchwicki
*/
@Configuration
@ConditionalOnClass(Failsafe.class)
public class FailsafeAutoConfiguration {

@Bean
@ConditionalOnMissingBean(CircuitBreakerFactory.class)
public CircuitBreakerFactory failsafeCircuitBreakerFactory() {
return new FailsafeCircuitBreakerFactory();
}

@Configuration
public static class FailsafeCustomizerConfiguration {

@Autowired(required = false)
private List<Customizer<FailsafeCircuitBreakerFactory>> customizers = new ArrayList<>();

@Autowired(required = false)
private FailsafeCircuitBreakerFactory factory;

@PostConstruct
public void init() {
customizers.forEach(customizer -> customizer.customize(factory));
}

}

}
Loading