This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch CAMEL-13691
in repository https://gitbox.apache.org/repos/asf/camel.git

commit da3bf41f168026dd69b03ff0e3f911d630a1d36b
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Sun Nov 17 09:04:50 2019 +0100

    CAMEL-13691: camel-resilience4j - WIP
---
 .../component/resilience4j/ResilienceReifier.java  |   3 +
 .../org/apache/camel/main/BaseMainSupport.java     |   2 +-
 .../camel/main/MainConfigurationProperties.java    |   8 +
 .../main/Resilience4jConfigurationProperties.java  | 390 +++++++++++++++++++++
 4 files changed, 402 insertions(+), 1 deletion(-)

diff --git 
a/components/camel-resilience4j/src/main/java/org/apache/camel/component/resilience4j/ResilienceReifier.java
 
b/components/camel-resilience4j/src/main/java/org/apache/camel/component/resilience4j/ResilienceReifier.java
index 06399cd..912fb3e 100644
--- 
a/components/camel-resilience4j/src/main/java/org/apache/camel/component/resilience4j/ResilienceReifier.java
+++ 
b/components/camel-resilience4j/src/main/java/org/apache/camel/component/resilience4j/ResilienceReifier.java
@@ -45,6 +45,9 @@ public class ResilienceReifier extends 
ProcessorReifier<CircuitBreakerDefinition
     // TODO: metrics with state of CB
     // TODO: expose metrics as JMX on processor
     // TODO: Timeout
+    // TODO: thread pool bulkhead
+    // TODO: spring-boot allow to configure via resilience4j-spring-boot
+    // TODO: example
 
     public ResilienceReifier(CircuitBreakerDefinition definition) {
         super(definition);
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java 
b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
index 542ed8c..a87c01b 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
@@ -642,7 +642,7 @@ public abstract class BaseMainSupport extends 
ServiceSupport {
         // lookup and configure SPI beans
         DefaultConfigurationConfigurer.afterPropertiesSet(camelContext);
 
-        // now configure context/hystrix/rest with additional properties
+        // now configure context/hystrix/resilience4j/rest with additional 
properties
         Properties prop = 
camelContext.getPropertiesComponent().loadProperties(name -> 
name.startsWith("camel."));
 
         // load properties from ENV (override existing)
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
 
b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
index 433b18d..c5eca6d 100644
--- 
a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
+++ 
b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
@@ -35,6 +35,7 @@ public class MainConfigurationProperties extends 
DefaultConfigurationProperties<
 
     // extended configuration
     private final HystrixConfigurationProperties 
hystrixConfigurationProperties = new HystrixConfigurationProperties(this);
+    private final Resilience4jConfigurationProperties 
resilience4jConfigurationProperties = new 
Resilience4jConfigurationProperties(this);
     private final RestConfigurationProperties restConfigurationProperties = 
new RestConfigurationProperties(this);
 
     // extended
@@ -48,6 +49,13 @@ public class MainConfigurationProperties extends 
DefaultConfigurationProperties<
     }
 
     /**
+     * To configure Circuit Breaker EIP with Resilience4j
+     */
+    public Resilience4jConfigurationProperties resilience4j() {
+        return resilience4jConfigurationProperties;
+    }
+
+    /**
      * To configure Rest DSL
      */
     public RestConfigurationProperties rest() {
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/Resilience4jConfigurationProperties.java
 
b/core/camel-main/src/main/java/org/apache/camel/main/Resilience4jConfigurationProperties.java
new file mode 100644
index 0000000..db9c7b8
--- /dev/null
+++ 
b/core/camel-main/src/main/java/org/apache/camel/main/Resilience4jConfigurationProperties.java
@@ -0,0 +1,390 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *      http://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.apache.camel.main;
+
+/**
+ * Global configuration for Resilience EIP circuit breaker.
+ */
+public class Resilience4jConfigurationProperties {
+
+    private final MainConfigurationProperties parent;
+
+    private String configRef;
+    private Float failureRateThreshold;
+    private Integer permittedNumberOfCallsInHalfOpenState;
+    private Integer slidingWindowSize;
+    private String slidingWindowType;
+    private Integer minimumNumberOfCalls;
+    private Boolean writableStackTraceEnabled;
+    private Integer waitDurationInOpenState;
+    private Boolean automaticTransitionFromOpenToHalfOpenEnabled;
+    private Float slowCallRateThreshold;
+    private Integer slowCallDurationThreshold;
+    private Boolean bulkheadEnabled;
+    private Integer bulkheadMaxConcurrentCalls;
+    private Integer bulkheadMaxWaitDuration;
+
+    public Resilience4jConfigurationProperties(MainConfigurationProperties 
parent) {
+        this.parent = parent;
+    }
+
+    public MainConfigurationProperties end() {
+        return parent;
+    }
+
+    // getter and setters
+    // --------------------------------------------------------------
+
+    public String getConfigRef() {
+        return configRef;
+    }
+
+    /**
+     * Refers to an existing 
io.github.resilience4j.circuitbreaker.CircuitBreakerConfig instance
+     * to lookup and use from the registry.
+     */
+    public void setConfigRef(String configRef) {
+        this.configRef = configRef;
+    }
+
+    public Float getFailureRateThreshold() {
+        return failureRateThreshold;
+    }
+
+    /**
+     * Configures the failure rate threshold in percentage.
+     * If the failure rate is equal or greater than the threshold the 
CircuitBreaker transitions to open and starts short-circuiting calls.
+     * <p>
+     * The threshold must be greater than 0 and not greater than 100. Default 
value is 50 percentage.
+     */
+    public void setFailureRateThreshold(Float failureRateThreshold) {
+        this.failureRateThreshold = failureRateThreshold;
+    }
+
+    public Integer getPermittedNumberOfCallsInHalfOpenState() {
+        return permittedNumberOfCallsInHalfOpenState;
+    }
+
+    /**
+     * Configures the number of permitted calls when the CircuitBreaker is 
half open.
+     * <p>
+     * The size must be greater than 0. Default size is 10.
+     */
+    public void setPermittedNumberOfCallsInHalfOpenState(Integer 
permittedNumberOfCallsInHalfOpenState) {
+        this.permittedNumberOfCallsInHalfOpenState = 
permittedNumberOfCallsInHalfOpenState;
+    }
+
+    public Integer getSlidingWindowSize() {
+        return slidingWindowSize;
+    }
+
+    /**
+     * Configures the size of the sliding window which is used to record the 
outcome of calls when the CircuitBreaker is closed.
+     * {@code slidingWindowSize} configures the size of the sliding window. 
Sliding window can either be count-based or time-based.
+     *
+     * If {@code slidingWindowType} is COUNT_BASED, the last {@code 
slidingWindowSize} calls are recorded and aggregated.
+     * If {@code slidingWindowType} is TIME_BASED, the calls of the last 
{@code slidingWindowSize} seconds are recorded and aggregated.
+     * <p>
+     * The {@code slidingWindowSize} must be greater than 0.
+     * The {@code minimumNumberOfCalls} must be greater than 0.
+     * If the slidingWindowType is COUNT_BASED, the {@code 
minimumNumberOfCalls} cannot be greater than {@code slidingWindowSize}.
+     * If the slidingWindowType is TIME_BASED, you can pick whatever you want.
+     *
+     * Default slidingWindowSize is 100.
+     */
+    public void setSlidingWindowSize(Integer slidingWindowSize) {
+        this.slidingWindowSize = slidingWindowSize;
+    }
+
+    public String getSlidingWindowType() {
+        return slidingWindowType;
+    }
+
+    /**
+     * Configures the type of the sliding window which is used to record the 
outcome of calls when the CircuitBreaker is closed.
+     * Sliding window can either be count-based or time-based.
+     *
+     * If {@code slidingWindowType} is COUNT_BASED, the last {@code 
slidingWindowSize} calls are recorded and aggregated.
+     * If {@code slidingWindowType} is TIME_BASED, the calls of the last 
{@code slidingWindowSize} seconds are recorded and aggregated.
+     *
+     * Default slidingWindowType is COUNT_BASED.
+     */
+    public void setSlidingWindowType(String slidingWindowType) {
+        this.slidingWindowType = slidingWindowType;
+    }
+
+    public Integer getMinimumNumberOfCalls() {
+        return minimumNumberOfCalls;
+    }
+
+    /**
+     * Configures configures the minimum number of calls which are required 
(per sliding window period) before the CircuitBreaker can calculate the error 
rate.
+     * For example, if {@code minimumNumberOfCalls} is 10, then at least 10 
calls must be recorded, before the failure rate can be calculated.
+     * If only 9 calls have been recorded the CircuitBreaker will not 
transition to open even if all 9 calls have failed.
+     *
+     * Default minimumNumberOfCalls is 100
+     */
+    public void setMinimumNumberOfCalls(Integer minimumNumberOfCalls) {
+        this.minimumNumberOfCalls = minimumNumberOfCalls;
+    }
+
+    public Boolean getWritableStackTraceEnabled() {
+        return writableStackTraceEnabled;
+    }
+
+    /**
+     * Enables writable stack traces. When set to false, 
Exception.getStackTrace returns a zero length array.
+     * This may be used to reduce log spam when the circuit breaker is open as 
the cause of the exceptions is already known (the circuit breaker is 
short-circuiting calls).
+     */
+    public void setWritableStackTraceEnabled(Boolean 
writableStackTraceEnabled) {
+        this.writableStackTraceEnabled = writableStackTraceEnabled;
+    }
+
+    public Integer getWaitDurationInOpenState() {
+        return waitDurationInOpenState;
+    }
+
+    /**
+     * Configures the wait duration (in seconds) which specifies how long the 
CircuitBreaker should stay open, before it switches to half open.
+     * Default value is 60 seconds.
+     */
+    public void setWaitDurationInOpenState(Integer waitDurationInOpenState) {
+        this.waitDurationInOpenState = waitDurationInOpenState;
+    }
+
+    public Boolean getAutomaticTransitionFromOpenToHalfOpenEnabled() {
+        return automaticTransitionFromOpenToHalfOpenEnabled;
+    }
+
+    /**
+     * Enables automatic transition from OPEN to HALF_OPEN state once the 
waitDurationInOpenState has passed.
+     */
+    public void setAutomaticTransitionFromOpenToHalfOpenEnabled(Boolean 
automaticTransitionFromOpenToHalfOpenEnabled) {
+        this.automaticTransitionFromOpenToHalfOpenEnabled = 
automaticTransitionFromOpenToHalfOpenEnabled;
+    }
+
+    public Float getSlowCallRateThreshold() {
+        return slowCallRateThreshold;
+    }
+
+    /**
+     * Configures a threshold in percentage. The CircuitBreaker considers a 
call as slow when the call duration is greater than 
slowCallDurationThreshold(Duration.
+     * When the percentage of slow calls is equal or greater the threshold, 
the CircuitBreaker transitions to open and starts short-circuiting calls.
+     * <p>
+     * The threshold must be greater than 0 and not greater than 100.
+     * Default value is 100 percentage which means that all recorded calls 
must be slower than slowCallDurationThreshold.
+     */
+    public void setSlowCallRateThreshold(Float slowCallRateThreshold) {
+        this.slowCallRateThreshold = slowCallRateThreshold;
+    }
+
+    public Integer getSlowCallDurationThreshold() {
+        return slowCallDurationThreshold;
+    }
+
+    /**
+     * Configures the duration threshold (seconds) above which calls are 
considered as slow and increase the slow calls percentage.
+     * Default value is 60 seconds.
+     */
+    public void setSlowCallDurationThreshold(Integer 
slowCallDurationThreshold) {
+        this.slowCallDurationThreshold = slowCallDurationThreshold;
+    }
+
+    public Boolean getBulkheadEnabled() {
+        return bulkheadEnabled;
+    }
+
+    /**
+     * Whether bulkhead is enabled or not on the circuit breaker.
+     */
+    public void setBulkheadEnabled(Boolean bulkheadEnabled) {
+        this.bulkheadEnabled = bulkheadEnabled;
+    }
+
+    public Integer getBulkheadMaxConcurrentCalls() {
+        return bulkheadMaxConcurrentCalls;
+    }
+
+    /**
+     * Configures the max amount of concurrent calls the bulkhead will support.
+     */
+    public void setBulkheadMaxConcurrentCalls(Integer 
bulkheadMaxConcurrentCalls) {
+        this.bulkheadMaxConcurrentCalls = bulkheadMaxConcurrentCalls;
+    }
+
+    public Integer getBulkheadMaxWaitDuration() {
+        return bulkheadMaxWaitDuration;
+    }
+
+    /**
+     * Configures a maximum amount of time which the calling thread will wait 
to enter the bulkhead. If bulkhead has space available, entry
+     * is guaranteed and immediate. If bulkhead is full, calling threads will 
contest for space, if it becomes available. maxWaitDuration can be set to 0.
+     * <p>
+     * Note: for threads running on an event-loop or equivalent (rx 
computation pool, etc), setting maxWaitDuration to 0 is highly recommended. 
Blocking
+     * an event-loop thread will most likely have a negative effect on 
application throughput.
+     */
+    public void setBulkheadMaxWaitDuration(Integer bulkheadMaxWaitDuration) {
+        this.bulkheadMaxWaitDuration = bulkheadMaxWaitDuration;
+    }
+
+    /**
+     * Refers to an existing 
io.github.resilience4j.circuitbreaker.CircuitBreakerConfig instance
+     * to lookup and use from the registry.
+     */
+    public Resilience4jConfigurationProperties withConfigRef(String configRef) 
{
+        this.configRef = configRef;
+        return this;
+    }
+
+    /**
+     * Configures the failure rate threshold in percentage.
+     * If the failure rate is equal or greater than the threshold the 
CircuitBreaker transitions to open and starts short-circuiting calls.
+     * <p>
+     * The threshold must be greater than 0 and not greater than 100. Default 
value is 50 percentage.
+     */
+    public Resilience4jConfigurationProperties withFailureRateThreshold(Float 
failureRateThreshold) {
+        this.failureRateThreshold = failureRateThreshold;
+        return this;
+    }
+
+    /**
+     * Configures the number of permitted calls when the CircuitBreaker is 
half open.
+     * <p>
+     * The size must be greater than 0. Default size is 10.
+     */
+    public Resilience4jConfigurationProperties 
withPermittedNumberOfCallsInHalfOpenState(Integer 
permittedNumberOfCallsInHalfOpenState) {
+        this.permittedNumberOfCallsInHalfOpenState = 
permittedNumberOfCallsInHalfOpenState;
+        return this;
+    }
+
+    /**
+     * Configures the size of the sliding window which is used to record the 
outcome of calls when the CircuitBreaker is closed.
+     * {@code slidingWindowSize} configures the size of the sliding window. 
Sliding window can either be count-based or time-based.
+     *
+     * If {@code slidingWindowType} is COUNT_BASED, the last {@code 
slidingWindowSize} calls are recorded and aggregated.
+     * If {@code slidingWindowType} is TIME_BASED, the calls of the last 
{@code slidingWindowSize} seconds are recorded and aggregated.
+     * <p>
+     * The {@code slidingWindowSize} must be greater than 0.
+     * The {@code minimumNumberOfCalls} must be greater than 0.
+     * If the slidingWindowType is COUNT_BASED, the {@code 
minimumNumberOfCalls} cannot be greater than {@code slidingWindowSize}.
+     * If the slidingWindowType is TIME_BASED, you can pick whatever you want.
+     *
+     * Default slidingWindowSize is 100.
+     */
+    public Resilience4jConfigurationProperties withSlidingWindowSize(Integer 
slidingWindowSize) {
+        this.slidingWindowSize = slidingWindowSize;
+        return this;
+    }
+
+    /**
+     * Configures the type of the sliding window which is used to record the 
outcome of calls when the CircuitBreaker is closed.
+     * Sliding window can either be count-based or time-based.
+     *
+     * If {@code slidingWindowType} is COUNT_BASED, the last {@code 
slidingWindowSize} calls are recorded and aggregated.
+     * If {@code slidingWindowType} is TIME_BASED, the calls of the last 
{@code slidingWindowSize} seconds are recorded and aggregated.
+     *
+     * Default slidingWindowType is COUNT_BASED.
+     */
+    public Resilience4jConfigurationProperties withSlidingWindowType(String 
slidingWindowType) {
+        this.slidingWindowType = slidingWindowType;
+        return this;
+    }
+
+    /**
+     * Configures configures the minimum number of calls which are required 
(per sliding window period) before the CircuitBreaker can calculate the error 
rate.
+     * For example, if {@code minimumNumberOfCalls} is 10, then at least 10 
calls must be recorded, before the failure rate can be calculated.
+     * If only 9 calls have been recorded the CircuitBreaker will not 
transition to open even if all 9 calls have failed.
+     *
+     * Default minimumNumberOfCalls is 100
+     */
+    public Resilience4jConfigurationProperties 
withMinimumNumberOfCalls(Integer minimumNumberOfCalls) {
+        this.minimumNumberOfCalls = minimumNumberOfCalls;
+        return this;
+    }
+
+    /**
+     * Enables writable stack traces. When set to false, 
Exception.getStackTrace returns a zero length array.
+     * This may be used to reduce log spam when the circuit breaker is open as 
the cause of the exceptions is already known (the circuit breaker is 
short-circuiting calls).
+     */
+    public Resilience4jConfigurationProperties 
withWritableStackTraceEnabled(Boolean writableStackTraceEnabled) {
+        this.writableStackTraceEnabled = writableStackTraceEnabled;
+        return this;
+    }
+
+    /**
+     * Configures the wait duration (in seconds) which specifies how long the 
CircuitBreaker should stay open, before it switches to half open.
+     * Default value is 60 seconds.
+     */
+    public Resilience4jConfigurationProperties 
withWaitDurationInOpenState(Integer waitDurationInOpenState) {
+        this.waitDurationInOpenState = waitDurationInOpenState;
+        return this;
+    }
+
+    public Resilience4jConfigurationProperties 
withAutomaticTransitionFromOpenToHalfOpenEnabled(Boolean 
automaticTransitionFromOpenToHalfOpenEnabled) {
+        this.automaticTransitionFromOpenToHalfOpenEnabled = 
automaticTransitionFromOpenToHalfOpenEnabled;
+        return this;
+    }
+
+    /**
+     * Configures a threshold in percentage. The CircuitBreaker considers a 
call as slow when the call duration is greater than 
slowCallDurationThreshold(Duration.
+     * When the percentage of slow calls is equal or greater the threshold, 
the CircuitBreaker transitions to open and starts short-circuiting calls.
+     * <p>
+     * The threshold must be greater than 0 and not greater than 100.
+     * Default value is 100 percentage which means that all recorded calls 
must be slower than slowCallDurationThreshold.
+     */
+    public Resilience4jConfigurationProperties withSlowCallRateThreshold(Float 
slowCallRateThreshold) {
+        this.slowCallRateThreshold = slowCallRateThreshold;
+        return this;
+    }
+
+    /**
+     * Configures the duration threshold (seconds) above which calls are 
considered as slow and increase the slow calls percentage.
+     * Default value is 60 seconds.
+     */
+    public Resilience4jConfigurationProperties 
withSlowCallDurationThreshold(Integer slowCallDurationThreshold) {
+        this.slowCallDurationThreshold = slowCallDurationThreshold;
+        return this;
+    }
+
+    /**
+     * Whether bulkhead is enabled or not on the circuit breaker.
+     */
+    public Resilience4jConfigurationProperties withBulkheadEnabled(Boolean 
bulkheadEnabled) {
+        this.bulkheadEnabled = bulkheadEnabled;
+        return this;
+    }
+
+    /**
+     * Configures the max amount of concurrent calls the bulkhead will support.
+     */
+    public Resilience4jConfigurationProperties 
withBulkheadMaxConcurrentCalls(Integer bulkheadMaxConcurrentCalls) {
+        this.bulkheadMaxConcurrentCalls = bulkheadMaxConcurrentCalls;
+        return this;
+    }
+
+    /**
+     * Configures a maximum amount of time which the calling thread will wait 
to enter the bulkhead. If bulkhead has space available, entry
+     * is guaranteed and immediate. If bulkhead is full, calling threads will 
contest for space, if it becomes available. maxWaitDuration can be set to 0.
+     * <p>
+     * Note: for threads running on an event-loop or equivalent (rx 
computation pool, etc), setting maxWaitDuration to 0 is highly recommended. 
Blocking
+     * an event-loop thread will most likely have a negative effect on 
application throughput.
+     */
+    public Resilience4jConfigurationProperties 
withBulkheadMaxWaitDuration(Integer bulkheadMaxWaitDuration) {
+        this.bulkheadMaxWaitDuration = bulkheadMaxWaitDuration;
+        return this;
+    }
+}

Reply via email to