Skip to content

Commit

Permalink
Adding new circuitbreaker-failsafe with naive implementation
Browse files Browse the repository at this point in the history
- Started working on spring-cloud-incubator/spring-cloud-circuitbreaker/spring-cloud#30
  • Loading branch information
kubamarchwicki committed Apr 23, 2019
1 parent a32929a commit 78b2dff
Show file tree
Hide file tree
Showing 10 changed files with 616 additions and 0 deletions.
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
<module>spring-cloud-circuitbreaker-commons</module>
<module>spring-cloud-starter-circuitbreaker</module>
<module>spring-cloud-circuitbreaker-hystrix</module>
<module>spring-cloud-circuitbreaker-failsafe</module>
<module>spring-cloud-circuitbreaker-sentinel</module>
<module>docs</module>
<module>spring-cloud-circuitbreaker-spring-retry</module>
Expand Down
6 changes: 6 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>0.13.1</resilience4j.version>
<failsafe.version>2.0.1</failsafe.version>
<sentinel.version>1.5.1</sentinel.version>
</properties>

Expand All @@ -39,6 +40,11 @@
<artifactId>resilience4j-reactor</artifactId>
<version>${resilience4j.version}</version>
</dependency>
<dependency>
<groupId>net.jodah</groupId>
<artifactId>failsafe</artifactId>
<version>${failsafe.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
Expand Down
40 changes: 40 additions & 0 deletions spring-cloud-circuitbreaker-failsafe/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?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>0.0.1.BUILD-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

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

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-circuitbreaker-commons</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.circuitbreaker.commons.CircuitBreakerFactory;
import org.springframework.cloud.circuitbreaker.commons.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));
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* 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.function.Function;
import java.util.function.Supplier;

import net.jodah.failsafe.Failsafe;
import net.jodah.failsafe.Fallback;
import net.jodah.failsafe.event.ExecutionAttemptedEvent;
import net.jodah.failsafe.function.CheckedFunction;

import org.springframework.cloud.circuitbreaker.commons.CircuitBreaker;

/**
* @author Jakub Marchwicki
*/
public class FailsafeCircuitBreaker implements CircuitBreaker {

private String id;

private FailsafeConfigBuilder.FailsafeConfig config;

// private Optional<Customizer<RetryTemplate>> retryTemplateCustomizer;
//
// private RetryTemplate retryTemplate;

public FailsafeCircuitBreaker(String id,
FailsafeConfigBuilder.FailsafeConfig config) {
// ,
// Optional<Customizer<RetryTemplate>> retryTemplateCustomizer) {
this.id = id;
this.config = config;
// this.retryTemplateCustomizer = retryTemplateCustomizer;
// this.retryTemplate = new RetryTemplate();
}

@Override
public <T> T run(Supplier<T> toRun, Function<Throwable, T> fallback) {

// retryTemplate.setBackOffPolicy(config.getBackOffPolicy());
// retryTemplate.setRetryPolicy(config.getRetryPolicy());
//
// retryTemplateCustomizer
// .ifPresent(customizer -> customizer.customize(retryTemplate));

Fallback<T> f = Fallback.of(extract(fallback));
return Failsafe.with(f).get(ex -> toRun.get());
// return retryTemplate.execute(context -> toRun.get(),
// context -> fallback.apply(context.getLastThrowable()),
// new DefaultRetryState(id, config.isForceRefreshState(),
// config.getStateClassifier()));
}

private <T> CheckedFunction<ExecutionAttemptedEvent<? extends T>, ? extends T> extract(
Function<Throwable, T> fallback) {
return execution -> fallback.apply(execution.getLastFailure());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* 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.HashMap;
import java.util.Map;
import java.util.function.Function;

import net.jodah.failsafe.Policy;

import org.springframework.cloud.circuitbreaker.commons.CircuitBreaker;
import org.springframework.cloud.circuitbreaker.commons.CircuitBreakerFactory;
import org.springframework.cloud.circuitbreaker.commons.Customizer;
import org.springframework.util.Assert;

/**
* @author Jakub Marchwicki
*/
public class FailsafeCircuitBreakerFactory extends
CircuitBreakerFactory<FailsafeConfigBuilder.FailsafeConfig, FailsafeConfigBuilder> {

private Function<String, FailsafeConfigBuilder.FailsafeConfig> defaultConfig = id -> new FailsafeConfigBuilder(
id).build();

private Map<String, Customizer<Policy>> failsafeCustomizers = new HashMap<>();

@Override
protected FailsafeConfigBuilder configBuilder(String id) {
return new FailsafeConfigBuilder(id);
}

@Override
public void configureDefault(
Function<String, FailsafeConfigBuilder.FailsafeConfig> defaultConfiguration) {
this.defaultConfig = defaultConfiguration;
}

@Override
public CircuitBreaker create(String id) {
Assert.hasText(id, "A circuit breaker must have an id");
FailsafeConfigBuilder.FailsafeConfig config = getConfigurations()
.computeIfAbsent(id, defaultConfig);
return new FailsafeCircuitBreaker(id, config);
}

public void addRetryTemplateCustomizers(Customizer<Policy> customizer,
String... ids) {
for (String id : ids) {
this.failsafeCustomizers.put(id, customizer);
}
}

}
Loading

0 comments on commit 78b2dff

Please sign in to comment.