reactivefeign.cloud2.CloudReactiveFeign Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of feign-reactor-cloud2 Show documentation
Show all versions of feign-reactor-cloud2 Show documentation
Adds support of Spring Cloud Loadbalancer instead of Ribbon and Resilience4j instead of Hystrix
package reactivefeign.cloud2;
import feign.Contract;
import feign.MethodMetadata;
import feign.Target;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer;
import reactivefeign.FallbackFactory;
import reactivefeign.ReactiveFeignBuilder;
import reactivefeign.ReactiveOptions;
import reactivefeign.client.ReactiveHttpExchangeFilterFunction;
import reactivefeign.client.ReactiveHttpRequestInterceptor;
import reactivefeign.client.ReactiveHttpResponseMapper;
import reactivefeign.client.log.ReactiveLoggerListener;
import reactivefeign.client.statushandler.ReactiveStatusHandler;
import reactivefeign.cloud2.methodhandler.CircuitBreakerMethodHandlerFactory;
import reactivefeign.cloud2.publisher.LoadBalancerPublisherClient;
import reactivefeign.methodhandler.MethodHandlerFactory;
import reactivefeign.publisher.PublisherClientFactory;
import reactivefeign.publisher.PublisherHttpClient;
import reactivefeign.retry.ReactiveRetryPolicy;
import java.util.function.Function;
import static reactivefeign.ReactiveFeign.Builder.retry;
/**
* Allows to specify load balancer {@link ReactiveLoadBalancer.Factory}
* and ReactiveCircuitBreakerFactory with fallback factory.
*
* @author Sergii Karpenko
*/
public class CloudReactiveFeign {
private static final Logger logger = LoggerFactory.getLogger(CloudReactiveFeign.class);
public static Builder builder(ReactiveFeignBuilder builder) {
return new Builder<>(builder);
}
public static class Builder implements ReactiveFeignBuilder {
private ReactiveFeignBuilder builder;
private ReactiveFeignCircuitBreakerFactory circuitBreakerFactory;
private FallbackFactory fallbackFactory;
private ReactiveLoadBalancer.Factory loadBalancerFactory;
private ReactiveRetryPolicy retryOnNextPolicy;
protected Builder(ReactiveFeignBuilder builder) {
this.builder = builder;
}
public Builder enableCircuitBreaker(ReactiveFeignCircuitBreakerFactory circuitBreakerFactory) {
this.circuitBreakerFactory = circuitBreakerFactory;
return this;
}
public Builder enableLoadBalancer(
ReactiveLoadBalancer.Factory loadBalancerFactory){
this.loadBalancerFactory = loadBalancerFactory;
return this;
}
public Builder retryOnSame(ReactiveRetryPolicy retryOnSamePolicy){
if(this.loadBalancerFactory == null){
throw new IllegalArgumentException("loadBalancerFactory should be specified");
}
retryWhen(retryOnSamePolicy);
return this;
}
public Builder retryOnNext(ReactiveRetryPolicy retryOnNextPolicy){
if(this.loadBalancerFactory == null){
throw new IllegalArgumentException("loadBalancerFactory should be specified");
}
this.retryOnNextPolicy = retryOnNextPolicy;
return this;
}
@Override
public Builder fallback(T fallback) {
return fallbackFactory(throwable -> fallback);
}
@Override
public Builder fallbackFactory(FallbackFactory fallbackFactory) {
this.fallbackFactory = fallbackFactory;
return this;
}
@Override
public Builder contract(Contract contract) {
builder = builder.contract(contract);
return this;
}
@Override
public ReactiveFeignBuilder addExchangeFilterFunction(ReactiveHttpExchangeFilterFunction exchangeFilterFunction) {
builder = builder.addExchangeFilterFunction(exchangeFilterFunction);
return this;
}
@Override
public Builder options(ReactiveOptions options) {
builder = builder.options(options);
return this;
}
@Override
public Builder addRequestInterceptor(ReactiveHttpRequestInterceptor requestInterceptor) {
builder = builder.addRequestInterceptor(requestInterceptor);
return this;
}
@Override
public Builder addLoggerListener(ReactiveLoggerListener loggerListener) {
builder = builder.addLoggerListener(loggerListener);
return this;
}
@Override
public Builder decode404() {
builder = builder.decode404();
return this;
}
@Override
public Builder statusHandler(ReactiveStatusHandler statusHandler) {
builder = builder.statusHandler(statusHandler);
return this;
}
@Override
public Builder responseMapper(ReactiveHttpResponseMapper responseMapper) {
builder = builder.responseMapper(responseMapper);
return this;
}
@Override
public Builder retryWhen(ReactiveRetryPolicy retryPolicy) {
builder = builder.retryWhen(retryPolicy);
return this;
}
@Override
public Contract contract() {
return builder.contract();
}
@Override
public MethodHandlerFactory buildReactiveMethodHandlerFactory(PublisherClientFactory reactiveClientFactory) {
if(circuitBreakerFactory == null){
builder.fallbackFactory(fallbackFactory);
return builder.buildReactiveMethodHandlerFactory(reactiveClientFactory);
} else {
return new CircuitBreakerMethodHandlerFactory(
builder.buildReactiveMethodHandlerFactory(reactiveClientFactory),
circuitBreakerFactory,
(Function) fallbackFactory);
}
}
@Override
public PublisherClientFactory buildReactiveClientFactory() {
PublisherClientFactory publisherClientFactory = builder.buildReactiveClientFactory();
return new PublisherClientFactory(){
private Target target;
@Override
public void target(Target target) {
this.target = target;
publisherClientFactory.target(target);
}
@Override
public PublisherHttpClient create(MethodMetadata methodMetadata) {
PublisherHttpClient publisherClient = publisherClientFactory.create(methodMetadata);
if(!target.name().equals(target.url()) && loadBalancerFactory != null){
publisherClient = new LoadBalancerPublisherClient(
loadBalancerFactory.getInstance(target.name()), publisherClient);
if(retryOnNextPolicy != null){
publisherClient = retry(publisherClient, methodMetadata, retryOnNextPolicy.toRetryFunction());
}
return publisherClient;
} else {
if(retryOnNextPolicy != null){
logger.warn("retryOnNextPolicy will be ignored " +
"as loadBalancerFactory is not configured for {} reactive feign client", target.name());
}
return publisherClient;
}
}
};
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy