This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch fix/CAMEL-24137-circuit-breaker-modernize in repository https://gitbox.apache.org/repos/asf/camel.git
commit d18fd349896b49660c7a5aef2123ee619c50729e Author: Claus Ibsen <[email protected]> AuthorDate: Mon Jul 20 18:01:26 2026 +0200 CAMEL-24137: Circuit Breaker EIP modernization (Z1, Z4, Z5, Z6, Z7, Z8) Co-Authored-By: Claude Opus 4.6 <[email protected]> Signed-off-by: Claus Ibsen <[email protected]> --- .../apache/camel/catalog/models/onFallback.json | 2 +- .../catalog/models/resilience4jConfiguration.json | 35 +++++---- components/camel-resilience4j/pom.xml | 17 ----- .../resilience4j/ResilienceProcessor.java | 20 +++-- .../component/resilience4j/ResilienceReifier.java | 20 ++++- .../resilience4j/ResiliencePooledFallbackTest.java | 75 +++++++++++++++++++ .../resilience4j/ResiliencePooledTimeoutTest.java | 73 ++++++++++++++++++ .../ResilienceTimeoutExchangePropertyTest.java | 62 ++++++++++++++++ ...nceTimeoutWithFallbackExchangePropertyTest.java | 70 ++++++++++++++++++ ...ilience4jConfigurationDefinitionConfigurer.java | 21 ++++++ .../org/apache/camel/model/onFallback.json | 2 +- .../camel/model/resilience4jConfiguration.json | 35 +++++---- .../camel/model/CircuitBreakerDefinition.java | 8 +- .../apache/camel/model/OnFallbackDefinition.java | 4 + .../model/Resilience4jConfigurationCommon.java | 66 +++++++++++++++-- .../model/Resilience4jConfigurationDefinition.java | 86 +++++++++++++++++----- .../java/org/apache/camel/xml/in/ModelParser.java | 3 + .../java/org/apache/camel/xml/out/ModelWriter.java | 19 +++-- .../org/apache/camel/yaml/out/YamlModelWriter.java | 19 +++-- .../ROOT/pages/camel-4x-upgrade-guide-4_22.adoc | 40 ++++++++++ .../dsl/yaml/deserializers/ModelDeserializers.java | 30 ++++++-- .../resources/schema/camelYamlDsl-canonical.json | 44 ++++++++--- .../generated/resources/schema/camelYamlDsl.json | 44 ++++++++--- parent/pom.xml | 1 - 24 files changed, 659 insertions(+), 137 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/onFallback.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/onFallback.json index fcc732c0c363..115d7228f588 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/onFallback.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/onFallback.json @@ -16,7 +16,7 @@ "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "note": { "index": 1, "kind": "attribute", "displayName": "Note", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The note for this node" }, "description": { "index": 2, "kind": "attribute", "displayName": "Description", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The description for this node" }, - "fallbackViaNetwork": { "index": 3, "kind": "attribute", "displayName": "Fallback Via Network", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the fallback goes over the network. If so, the fallback is executed on a separate thread-pool to avoid exhausting the main thread-pool." }, + "fallbackViaNetwork": { "index": 3, "kind": "attribute", "displayName": "Fallback Via Network", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": true, "deprecationNote": "Not supported by any circuit breaker implementation.", "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the fallback goes over the network. If so, the fallback is executed on a separate thread-pool to avo [...] "outputs": { "index": 4, "kind": "element", "displayName": "Outputs", "group": "common", "required": true, "type": "array", "javaType": "java.util.List<org.apache.camel.model.ProcessorDefinition<java.lang.Object>>", "oneOf": [ "a2aSubTask", "aggregate", "bean", "choice", "circuitBreaker", "claimCheck", "convertBodyTo", "convertHeaderTo", "convertVariableTo", "delay", "doCatch", "doFinally", "doTry", "dynamicRouter", "enrich", "filter", "idempotentConsumer", "intercept", "interceptFro [...] } } diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/resilience4jConfiguration.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/resilience4jConfiguration.json index e2ee2d25745b..9b1452808a39 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/resilience4jConfiguration.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/resilience4jConfiguration.json @@ -20,21 +20,24 @@ "throwExceptionWhenHalfOpenOrOpenState": { "index": 5, "kind": "attribute", "displayName": "Throw Exception When Half Open Or Open State", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to throw io.github.resilience4j.circuitbreaker.CallNotPermittedException when the call is rejected because the circuit breaker is half open or open." }, "slidingWindowSize": { "index": 6, "kind": "attribute", "displayName": "Sliding Window Size", "group": "common", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 100, "description": "Configures the size 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." }, "slidingWindowType": { "index": 7, "kind": "attribute", "displayName": "Sliding Window Type", "group": "advanced", "label": "advanced", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "TIME_BASED", "COUNT_BASED" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "COUNT_BASED", "description": "Configures the type of the sliding window which is used to record the outcome of calls when the CircuitBreaker is closed. Sliding window ca [...] - "minimumNumberOfCalls": { "index": 8, "kind": "attribute", "displayName": "Minimum Number Of Calls", "group": "common", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 100, "description": "Configures the minimum number of calls which are required (per sliding window period) before the CircuitBreaker can calculate the error rate." }, - "writableStackTraceEnabled": { "index": 9, "kind": "attribute", "displayName": "Writable Stack Trace Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "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 o [...] - "waitDurationInOpenState": { "index": 10, "kind": "attribute", "displayName": "Wait Duration In Open State", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 60, "description": "Configures the wait duration (in seconds) which specifies how long the CircuitBreaker should stay open, before it switches to half open." }, - "automaticTransitionFromOpenToHalfOpenEnabled": { "index": 11, "kind": "attribute", "displayName": "Automatic Transition From Open To Half Open Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enables automatic transition from OPEN to HALF_OPEN state once the waitDurationInOpenState has passed." }, - "slowCallRateThreshold": { "index": 12, "kind": "attribute", "displayName": "Slow Call Rate Threshold", "group": "advanced", "label": "advanced", "required": false, "type": "number", "javaType": "java.lang.Float", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "100", "description": "Configures a threshold in percentage. The CircuitBreaker considers a call as slow when the call duration is greater than slowCallDurationThreshold. When the percentage of slow c [...] - "slowCallDurationThreshold": { "index": 13, "kind": "attribute", "displayName": "Slow Call Duration Threshold", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 60, "description": "Configures the duration threshold (seconds) above which calls are considered as slow and increase the slow calls percentage." }, - "bulkheadEnabled": { "index": 14, "kind": "attribute", "displayName": "Bulkhead Enabled", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether bulkhead is enabled or not on the circuit breaker." }, - "bulkheadMaxConcurrentCalls": { "index": 15, "kind": "attribute", "displayName": "Bulkhead Max Concurrent Calls", "group": "common", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 25, "description": "Configures the max amount of concurrent calls the bulkhead will support." }, - "bulkheadMaxWaitDuration": { "index": 16, "kind": "attribute", "displayName": "Bulkhead Max Wait Duration", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Configures a maximum amount of time which the calling thread will wait to enter the bulkhead." }, - "timeoutEnabled": { "index": 17, "kind": "attribute", "displayName": "Timeout Enabled", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether timeout is enabled or not on the circuit breaker." }, - "timeoutExecutorService": { "index": 18, "kind": "attribute", "displayName": "Timeout Executor Service", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.concurrent.ExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "References to a custom thread pool to use when timeout is enabled (uses ForkJoinPool.commonPool() by default)." }, - "timeoutDuration": { "index": 19, "kind": "attribute", "displayName": "Timeout Duration", "group": "common", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Configures the thread execution timeout. Default value is 1 second." }, - "timeoutCancelRunningFuture": { "index": 20, "kind": "attribute", "displayName": "Timeout Cancel Running Future", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Configures whether cancel is called on the running future. Defaults to true." }, - "micrometerEnabled": { "index": 21, "kind": "attribute", "displayName": "Micrometer Enabled", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable collecting statistics using Micrometer. This requires adding camel-resilience4j-micrometer JAR to the classpath." }, - "recordException": { "index": 22, "kind": "element", "displayName": "Record Exception", "group": "advanced", "label": "advanced", "required": false, "type": "array", "javaType": "java.util.List<java.lang.String>", "deprecated": false, "autowired": false, "secret": false, "description": "Configure a list of exceptions that are recorded as a failure and thus increase the failure rate. Any exception matching or inheriting from one of the list counts as a failure, unless explicitly ignor [...] - "ignoreException": { "index": 23, "kind": "element", "displayName": "Ignore Exception", "group": "advanced", "label": "advanced", "required": false, "type": "array", "javaType": "java.util.List<java.lang.String>", "deprecated": false, "autowired": false, "secret": false, "description": "Configure a list of exceptions that are ignored and neither count as a failure nor success. Any exception matching or inheriting from one of the list will not count as a failure nor success, even if t [...] + "slidingWindowSynchronizationStrategy": { "index": 8, "kind": "attribute", "displayName": "Sliding Window Synchronization Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "LOCK_FREE", "SYNCHRONIZED" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "SYNCHRONIZED", "description": "Configures the synchronization strategy for the sliding window. LOCK_FREE uses a CAS-based lock-fre [...] + "minimumNumberOfCalls": { "index": 9, "kind": "attribute", "displayName": "Minimum Number Of Calls", "group": "common", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 100, "description": "Configures the minimum number of calls which are required (per sliding window period) before the CircuitBreaker can calculate the error rate." }, + "writableStackTraceEnabled": { "index": 10, "kind": "attribute", "displayName": "Writable Stack Trace Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "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 [...] + "waitDurationInOpenState": { "index": 11, "kind": "attribute", "displayName": "Wait Duration In Open State", "group": "advanced", "label": "advanced", "required": false, "type": "duration", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "60000", "description": "Configures the wait duration which specifies how long the CircuitBreaker should stay open, before it switches to half open. The default is 60 seconds." }, + "automaticTransitionFromOpenToHalfOpenEnabled": { "index": 12, "kind": "attribute", "displayName": "Automatic Transition From Open To Half Open Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enables automatic transition from OPEN to HALF_OPEN state once the waitDurationInOpenState has passed." }, + "maxWaitDurationInHalfOpenState": { "index": 13, "kind": "attribute", "displayName": "Max Wait Duration In Half Open State", "group": "advanced", "label": "advanced", "required": false, "type": "duration", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "0", "description": "Configures the maximum wait duration which controls how long the CircuitBreaker should stay in Half Open state, before it switches to open. Value 0 means c [...] + "slowCallRateThreshold": { "index": 14, "kind": "attribute", "displayName": "Slow Call Rate Threshold", "group": "advanced", "label": "advanced", "required": false, "type": "number", "javaType": "java.lang.Float", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "100", "description": "Configures a threshold in percentage. The CircuitBreaker considers a call as slow when the call duration is greater than slowCallDurationThreshold. When the percentage of slow c [...] + "slowCallDurationThreshold": { "index": 15, "kind": "attribute", "displayName": "Slow Call Duration Threshold", "group": "advanced", "label": "advanced", "required": false, "type": "duration", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "60000", "description": "Configures the duration threshold above which calls are considered as slow and increase the slow calls percentage. The default is 60 seconds." }, + "bulkheadEnabled": { "index": 16, "kind": "attribute", "displayName": "Bulkhead Enabled", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether bulkhead is enabled or not on the circuit breaker." }, + "bulkheadMaxConcurrentCalls": { "index": 17, "kind": "attribute", "displayName": "Bulkhead Max Concurrent Calls", "group": "common", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 25, "description": "Configures the max amount of concurrent calls the bulkhead will support." }, + "bulkheadMaxWaitDuration": { "index": 18, "kind": "attribute", "displayName": "Bulkhead Max Wait Duration", "group": "advanced", "label": "advanced", "required": false, "type": "duration", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "0", "description": "Configures a maximum amount of time which the calling thread will wait to enter the bulkhead. The default is 0 (no waiting)." }, + "bulkheadFairCallHandlingEnabled": { "index": 19, "kind": "attribute", "displayName": "Bulkhead Fair Call Handling Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Configures whether the bulkhead uses a fair calling strategy. When enabled (default), a fair strategy guarantees the order of incoming requests (FIFO). Wh [...] + "timeoutEnabled": { "index": 20, "kind": "attribute", "displayName": "Timeout Enabled", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether timeout is enabled or not on the circuit breaker." }, + "timeoutExecutorService": { "index": 21, "kind": "attribute", "displayName": "Timeout Executor Service", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.concurrent.ExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "References to a custom thread pool to use when timeout is enabled (uses ForkJoinPool.commonPool() by default)." }, + "timeoutDuration": { "index": 22, "kind": "attribute", "displayName": "Timeout Duration", "group": "common", "required": false, "type": "duration", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1000", "description": "Configures the thread execution timeout. Default value is 1 second." }, + "timeoutCancelRunningFuture": { "index": 23, "kind": "attribute", "displayName": "Timeout Cancel Running Future", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Configures whether cancel is called on the running future. Defaults to true." }, + "micrometerEnabled": { "index": 24, "kind": "attribute", "displayName": "Micrometer Enabled", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable collecting statistics using Micrometer for all circuit breaker instances. This is a global setting (configure via camel.resilience4j.micrometerEnabled=true) and requires adding camel-resili [...] + "recordException": { "index": 25, "kind": "element", "displayName": "Record Exception", "group": "advanced", "label": "advanced", "required": false, "type": "array", "javaType": "java.util.List<java.lang.String>", "deprecated": false, "autowired": false, "secret": false, "description": "Configure a list of exceptions that are recorded as a failure and thus increase the failure rate. Any exception matching or inheriting from one of the list counts as a failure, unless explicitly ignor [...] + "ignoreException": { "index": 26, "kind": "element", "displayName": "Ignore Exception", "group": "advanced", "label": "advanced", "required": false, "type": "array", "javaType": "java.util.List<java.lang.String>", "deprecated": false, "autowired": false, "secret": false, "description": "Configure a list of exceptions that are ignored and neither count as a failure nor success. Any exception matching or inheriting from one of the list will not count as a failure nor success, even if t [...] } } diff --git a/components/camel-resilience4j/pom.xml b/components/camel-resilience4j/pom.xml index 4aa1ff1422d6..f85217cf33b4 100644 --- a/components/camel-resilience4j/pom.xml +++ b/components/camel-resilience4j/pom.xml @@ -57,12 +57,6 @@ <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-circuitbreaker</artifactId> <version>${resilience4j-version}</version> - <exclusions> - <exclusion> - <groupId>io.vavr</groupId> - <artifactId>vavr</artifactId> - </exclusion> - </exclusions> </dependency> <dependency> <groupId>io.github.resilience4j</groupId> @@ -74,17 +68,6 @@ <artifactId>resilience4j-timelimiter</artifactId> <version>${resilience4j-version}</version> </dependency> - <dependency> - <groupId>io.vavr</groupId> - <artifactId>vavr</artifactId> - <version>${vavr-version}</version> - </dependency> - <dependency> - <groupId>io.vavr</groupId> - <artifactId>vavr-match</artifactId> - <version>${vavr-version}</version> - </dependency> - <!-- for testing --> <dependency> <groupId>org.apache.camel</groupId> diff --git a/components/camel-resilience4j/src/main/java/org/apache/camel/component/resilience4j/ResilienceProcessor.java b/components/camel-resilience4j/src/main/java/org/apache/camel/component/resilience4j/ResilienceProcessor.java index 278487ffb3cb..eade71731573 100644 --- a/components/camel-resilience4j/src/main/java/org/apache/camel/component/resilience4j/ResilienceProcessor.java +++ b/components/camel-resilience4j/src/main/java/org/apache/camel/component/resilience4j/ResilienceProcessor.java @@ -39,7 +39,6 @@ import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry; import io.github.resilience4j.timelimiter.TimeLimiter; import io.github.resilience4j.timelimiter.TimeLimiterConfig; import io.github.resilience4j.timelimiter.TimeLimiterRegistry; -import io.vavr.control.Try; import org.apache.camel.AsyncCallback; import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; @@ -548,10 +547,12 @@ public class ResilienceProcessor extends BaseProcessorSupport if (LOG.isTraceEnabled()) { LOG.trace("Processing exchange: {} using circuit breaker: {}", exchange.getExchangeId(), id); } - Try.ofCallable(callable) - .andThen(this::successState) - .recover(fallbackTask) - .get(); + try { + Exchange result = callable.call(); + successState(result); + } catch (Exception e) { + fallbackTask.apply(e); + } } catch (Exception e) { exchange.setException(e); } finally { @@ -788,6 +789,9 @@ public class ResilienceProcessor extends BaseProcessorSupport exchange.setProperty(ExchangePropertyKey.CIRCUIT_BREAKER_RESPONSE_SUCCESSFUL_EXECUTION, false); exchange.setProperty(ExchangePropertyKey.CIRCUIT_BREAKER_RESPONSE_FROM_FALLBACK, true); exchange.setProperty(ExchangePropertyKey.CIRCUIT_BREAKER_RESPONSE_SHORT_CIRCUITED, true); + if (throwable instanceof TimeoutException) { + exchange.setProperty(ExchangePropertyKey.CIRCUIT_BREAKER_RESPONSE_TIMED_OUT, true); + } // store the last to endpoint as the failure endpoint if (exchange.getProperty(ExchangePropertyKey.FAILURE_ENDPOINT) == null) { @@ -796,7 +800,11 @@ public class ResilienceProcessor extends BaseProcessorSupport } // give the rest of the pipeline another chance exchange.setProperty(ExchangePropertyKey.EXCEPTION_HANDLED, true); - exchange.setProperty(ExchangePropertyKey.EXCEPTION_CAUGHT, exchange.getException()); + // use the guard-level throwable for EXCEPTION_CAUGHT since the exchange + // may not have the exception set (e.g. on timeout the exception is thrown + // by the TimeLimiter on the caller thread, not set on the exchange) + Throwable caught = exchange.getException() != null ? exchange.getException() : throwable; + exchange.setProperty(ExchangePropertyKey.EXCEPTION_CAUGHT, caught); exchange.setRouteStop(false); exchange.setException(null); // and we should not be regarded as exhausted as we are in a try .. 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 d0f386e95ae2..f198261372d2 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 @@ -151,14 +151,23 @@ public class ResilienceReifier extends ProcessorReifier<CircuitBreakerDefinition if (config.getSlidingWindowType() != null) { builder.slidingWindowType(CircuitBreakerConfig.SlidingWindowType.valueOf(config.getSlidingWindowType())); } + if (config.getSlidingWindowSynchronizationStrategy() != null) { + builder.slidingWindowSynchronizationStrategy( + CircuitBreakerConfig.SlidingWindowSynchronizationStrategy + .valueOf(config.getSlidingWindowSynchronizationStrategy())); + } if (config.getSlowCallDurationThreshold() != null) { - builder.slowCallDurationThreshold(Duration.ofSeconds(parseLong(config.getSlowCallDurationThreshold()))); + builder.slowCallDurationThreshold(Duration.ofMillis(parseDuration(config.getSlowCallDurationThreshold()))); } if (config.getSlowCallRateThreshold() != null) { builder.slowCallRateThreshold(parseFloat(config.getSlowCallRateThreshold())); } if (config.getWaitDurationInOpenState() != null) { - builder.waitDurationInOpenState(Duration.ofSeconds(parseLong(config.getWaitDurationInOpenState()))); + builder.waitDurationInOpenState(Duration.ofMillis(parseDuration(config.getWaitDurationInOpenState()))); + } + if (config.getMaxWaitDurationInHalfOpenState() != null) { + builder.maxWaitDurationInHalfOpenState( + Duration.ofMillis(parseDuration(config.getMaxWaitDurationInHalfOpenState()))); } if (config.getWritableStackTraceEnabled() != null) { builder.writableStackTraceEnabled(parseBoolean(config.getWritableStackTraceEnabled())); @@ -182,13 +191,16 @@ public class ResilienceReifier extends ProcessorReifier<CircuitBreakerDefinition builder.maxConcurrentCalls(parseInt(config.getBulkheadMaxConcurrentCalls())); } if (config.getBulkheadMaxWaitDuration() != null) { - long duration = parseLong(config.getBulkheadMaxWaitDuration()); + long duration = parseDuration(config.getBulkheadMaxWaitDuration()); if (duration <= 0) { builder.maxWaitDuration(Duration.ZERO); } else { builder.maxWaitDuration(Duration.ofMillis(duration)); } } + if (config.getBulkheadFairCallHandlingEnabled() != null) { + builder.fairCallHandlingStrategyEnabled(parseBoolean(config.getBulkheadFairCallHandlingEnabled())); + } return builder.build(); } @@ -199,7 +211,7 @@ public class ResilienceReifier extends ProcessorReifier<CircuitBreakerDefinition TimeLimiterConfig.Builder builder = TimeLimiterConfig.custom(); if (config.getTimeoutDuration() != null) { - builder.timeoutDuration(Duration.ofMillis(parseLong(config.getTimeoutDuration()))); + builder.timeoutDuration(Duration.ofMillis(parseDuration(config.getTimeoutDuration()))); } if (config.getTimeoutCancelRunningFuture() != null) { builder.cancelRunningFuture(parseBoolean(config.getTimeoutCancelRunningFuture())); diff --git a/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResiliencePooledFallbackTest.java b/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResiliencePooledFallbackTest.java new file mode 100644 index 000000000000..930cf2ee56dd --- /dev/null +++ b/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResiliencePooledFallbackTest.java @@ -0,0 +1,75 @@ +/* + * 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.component.resilience4j; + +import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; +import org.apache.camel.RoutesBuilder; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.impl.engine.PooledExchangeFactory; +import org.apache.camel.impl.engine.PooledProcessorExchangeFactory; +import org.apache.camel.spi.CircuitBreakerConstants; +import org.apache.camel.test.junit6.CamelTestSupport; +import org.junit.jupiter.api.Test; + +import static org.apache.camel.test.junit6.TestSupport.assertIsInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNull; + +public class ResiliencePooledFallbackTest extends CamelTestSupport { + + @Override + protected CamelContext createCamelContext() throws Exception { + CamelContext context = super.createCamelContext(); + context.getCamelContextExtension().setExchangeFactory(new PooledExchangeFactory()); + context.getCamelContextExtension().setProcessorExchangeFactory(new PooledProcessorExchangeFactory()); + return context; + } + + @Test + public void testFallbackExceptionCaughtPooled() throws Exception { + getMockEndpoint("mock:result").expectedBodiesReceived("Fallback message"); + getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SUCCESSFUL_EXECUTION, false); + getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_FROM_FALLBACK, true); + getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SHORT_CIRCUITED, true); + + template.sendBody("direct:start", "Hello World"); + + MockEndpoint.assertIsSatisfied(context); + } + + @Override + protected RoutesBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:start") + .circuitBreaker() + .throwException(new IllegalArgumentException("Forced")) + .onFallback() + .process(e -> { + Throwable caught = e.getProperty(Exchange.EXCEPTION_CAUGHT, Throwable.class); + assertIsInstanceOf(IllegalArgumentException.class, caught); + assertNull(e.getException()); + }) + .transform().constant("Fallback message") + .end() + .to("mock:result"); + } + }; + } +} diff --git a/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResiliencePooledTimeoutTest.java b/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResiliencePooledTimeoutTest.java new file mode 100644 index 000000000000..299a707eb13e --- /dev/null +++ b/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResiliencePooledTimeoutTest.java @@ -0,0 +1,73 @@ +/* + * 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.component.resilience4j; + +import java.util.concurrent.TimeoutException; + +import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; +import org.apache.camel.RoutesBuilder; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.impl.engine.PooledExchangeFactory; +import org.apache.camel.impl.engine.PooledProcessorExchangeFactory; +import org.apache.camel.spi.CircuitBreakerConstants; +import org.apache.camel.test.junit6.CamelTestSupport; +import org.junit.jupiter.api.Test; + +import static org.apache.camel.test.junit6.TestSupport.assertIsInstanceOf; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class ResiliencePooledTimeoutTest extends CamelTestSupport { + + @Override + protected CamelContext createCamelContext() throws Exception { + CamelContext context = super.createCamelContext(); + context.getCamelContextExtension().setExchangeFactory(new PooledExchangeFactory()); + context.getCamelContextExtension().setProcessorExchangeFactory(new PooledProcessorExchangeFactory()); + return context; + } + + @Test + public void testTimeoutExchangePropertiesPooled() { + Exchange out = template.send("direct:start", e -> e.getIn().setBody("Hello World")); + + assertNotNull(out.getException()); + assertIsInstanceOf(TimeoutException.class, out.getException()); + assertEquals(false, out.getProperty(CircuitBreakerConstants.RESPONSE_SUCCESSFUL_EXECUTION)); + assertEquals(false, out.getProperty(CircuitBreakerConstants.RESPONSE_FROM_FALLBACK)); + assertEquals(false, out.getProperty(CircuitBreakerConstants.RESPONSE_SHORT_CIRCUITED)); + assertEquals(true, out.getProperty(CircuitBreakerConstants.RESPONSE_TIMED_OUT)); + } + + @Override + protected RoutesBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:start") + .circuitBreaker() + .resilience4jConfiguration().timeoutEnabled(true).timeoutDuration(2000).end() + .to("direct:slow") + .end(); + + from("direct:slow") + .delay(5000).transform().constant("Slow response"); + } + }; + } +} diff --git a/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResilienceTimeoutExchangePropertyTest.java b/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResilienceTimeoutExchangePropertyTest.java new file mode 100644 index 000000000000..e5e921d6d573 --- /dev/null +++ b/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResilienceTimeoutExchangePropertyTest.java @@ -0,0 +1,62 @@ +/* + * 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.component.resilience4j; + +import java.util.concurrent.TimeoutException; + +import org.apache.camel.Exchange; +import org.apache.camel.RoutesBuilder; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.spi.CircuitBreakerConstants; +import org.apache.camel.test.junit6.CamelTestSupport; +import org.junit.jupiter.api.Test; + +import static org.apache.camel.test.junit6.TestSupport.assertIsInstanceOf; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class ResilienceTimeoutExchangePropertyTest extends CamelTestSupport { + + @Test + public void testTimeoutExchangeProperties() { + Exchange out = template.send("direct:start", e -> e.getIn().setBody("Hello World")); + + assertNotNull(out.getException()); + assertIsInstanceOf(TimeoutException.class, out.getException()); + assertEquals(false, out.getProperty(CircuitBreakerConstants.RESPONSE_SUCCESSFUL_EXECUTION)); + assertEquals(false, out.getProperty(CircuitBreakerConstants.RESPONSE_FROM_FALLBACK)); + assertEquals(false, out.getProperty(CircuitBreakerConstants.RESPONSE_SHORT_CIRCUITED)); + assertEquals(true, out.getProperty(CircuitBreakerConstants.RESPONSE_TIMED_OUT)); + } + + @Override + protected RoutesBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:start") + .circuitBreaker() + .resilience4jConfiguration().timeoutEnabled(true).timeoutDuration(2000).end() + .to("direct:slow") + .end(); + + from("direct:slow") + .delay(5000).transform().constant("Slow response"); + } + }; + } +} diff --git a/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResilienceTimeoutWithFallbackExchangePropertyTest.java b/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResilienceTimeoutWithFallbackExchangePropertyTest.java new file mode 100644 index 000000000000..167617ea991a --- /dev/null +++ b/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResilienceTimeoutWithFallbackExchangePropertyTest.java @@ -0,0 +1,70 @@ +/* + * 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.component.resilience4j; + +import java.util.concurrent.TimeoutException; + +import org.apache.camel.Exchange; +import org.apache.camel.RoutesBuilder; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.spi.CircuitBreakerConstants; +import org.apache.camel.test.junit6.CamelTestSupport; +import org.junit.jupiter.api.Test; + +import static org.apache.camel.test.junit6.TestSupport.assertIsInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNull; + +public class ResilienceTimeoutWithFallbackExchangePropertyTest extends CamelTestSupport { + + @Test + public void testTimeoutWithFallbackExchangeProperties() throws Exception { + getMockEndpoint("mock:result").expectedBodiesReceived("Fallback response"); + getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SUCCESSFUL_EXECUTION, false); + getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_FROM_FALLBACK, true); + getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_TIMED_OUT, true); + + template.sendBody("direct:start", "Hello World"); + + MockEndpoint.assertIsSatisfied(context); + } + + @Override + protected RoutesBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:start") + .circuitBreaker() + .resilience4jConfiguration().timeoutEnabled(true).timeoutDuration(2000).end() + .to("direct:slow") + .onFallback() + .process(e -> { + Throwable caught = e.getProperty(Exchange.EXCEPTION_CAUGHT, Throwable.class); + assertIsInstanceOf(TimeoutException.class, caught); + assertNull(e.getException()); + }) + .transform().constant("Fallback response") + .end() + .to("mock:result"); + + from("direct:slow") + .delay(5000).transform().constant("Slow response"); + } + }; + } +} diff --git a/core/camel-core-model/src/generated/java/org/apache/camel/model/Resilience4jConfigurationDefinitionConfigurer.java b/core/camel-core-model/src/generated/java/org/apache/camel/model/Resilience4jConfigurationDefinitionConfigurer.java index e39a21bcf02b..3504155b89f5 100644 --- a/core/camel-core-model/src/generated/java/org/apache/camel/model/Resilience4jConfigurationDefinitionConfigurer.java +++ b/core/camel-core-model/src/generated/java/org/apache/camel/model/Resilience4jConfigurationDefinitionConfigurer.java @@ -24,6 +24,7 @@ public class Resilience4jConfigurationDefinitionConfigurer extends org.apache.ca Map<String, Object> map = new CaseInsensitiveMap(); map.put("AutomaticTransitionFromOpenToHalfOpenEnabled", java.lang.String.class); map.put("BulkheadEnabled", java.lang.String.class); + map.put("BulkheadFairCallHandlingEnabled", java.lang.String.class); map.put("BulkheadMaxConcurrentCalls", java.lang.String.class); map.put("BulkheadMaxWaitDuration", java.lang.String.class); map.put("CircuitBreaker", java.lang.String.class); @@ -31,11 +32,13 @@ public class Resilience4jConfigurationDefinitionConfigurer extends org.apache.ca map.put("FailureRateThreshold", java.lang.String.class); map.put("Id", java.lang.String.class); map.put("IgnoreExceptions", java.util.List.class); + map.put("MaxWaitDurationInHalfOpenState", java.lang.String.class); map.put("MicrometerEnabled", java.lang.String.class); map.put("MinimumNumberOfCalls", java.lang.String.class); map.put("PermittedNumberOfCallsInHalfOpenState", java.lang.String.class); map.put("RecordExceptions", java.util.List.class); map.put("SlidingWindowSize", java.lang.String.class); + map.put("SlidingWindowSynchronizationStrategy", java.lang.String.class); map.put("SlidingWindowType", java.lang.String.class); map.put("SlowCallDurationThreshold", java.lang.String.class); map.put("SlowCallRateThreshold", java.lang.String.class); @@ -57,6 +60,8 @@ public class Resilience4jConfigurationDefinitionConfigurer extends org.apache.ca case "automaticTransitionFromOpenToHalfOpenEnabled": target.setAutomaticTransitionFromOpenToHalfOpenEnabled(property(camelContext, java.lang.String.class, value)); return true; case "bulkheadenabled": case "bulkheadEnabled": target.setBulkheadEnabled(property(camelContext, java.lang.String.class, value)); return true; + case "bulkheadfaircallhandlingenabled": + case "bulkheadFairCallHandlingEnabled": target.setBulkheadFairCallHandlingEnabled(property(camelContext, java.lang.String.class, value)); return true; case "bulkheadmaxconcurrentcalls": case "bulkheadMaxConcurrentCalls": target.setBulkheadMaxConcurrentCalls(property(camelContext, java.lang.String.class, value)); return true; case "bulkheadmaxwaitduration": @@ -69,6 +74,8 @@ public class Resilience4jConfigurationDefinitionConfigurer extends org.apache.ca case "id": target.setId(property(camelContext, java.lang.String.class, value)); return true; case "ignoreexceptions": case "ignoreExceptions": target.setIgnoreExceptions(property(camelContext, java.util.List.class, value)); return true; + case "maxwaitdurationinhalfopenstate": + case "maxWaitDurationInHalfOpenState": target.setMaxWaitDurationInHalfOpenState(property(camelContext, java.lang.String.class, value)); return true; case "micrometerenabled": case "micrometerEnabled": target.setMicrometerEnabled(property(camelContext, java.lang.String.class, value)); return true; case "minimumnumberofcalls": @@ -79,6 +86,8 @@ public class Resilience4jConfigurationDefinitionConfigurer extends org.apache.ca case "recordExceptions": target.setRecordExceptions(property(camelContext, java.util.List.class, value)); return true; case "slidingwindowsize": case "slidingWindowSize": target.setSlidingWindowSize(property(camelContext, java.lang.String.class, value)); return true; + case "slidingwindowsynchronizationstrategy": + case "slidingWindowSynchronizationStrategy": target.setSlidingWindowSynchronizationStrategy(property(camelContext, java.lang.String.class, value)); return true; case "slidingwindowtype": case "slidingWindowType": target.setSlidingWindowType(property(camelContext, java.lang.String.class, value)); return true; case "slowcalldurationthreshold": @@ -115,6 +124,8 @@ public class Resilience4jConfigurationDefinitionConfigurer extends org.apache.ca case "automaticTransitionFromOpenToHalfOpenEnabled": return java.lang.String.class; case "bulkheadenabled": case "bulkheadEnabled": return java.lang.String.class; + case "bulkheadfaircallhandlingenabled": + case "bulkheadFairCallHandlingEnabled": return java.lang.String.class; case "bulkheadmaxconcurrentcalls": case "bulkheadMaxConcurrentCalls": return java.lang.String.class; case "bulkheadmaxwaitduration": @@ -127,6 +138,8 @@ public class Resilience4jConfigurationDefinitionConfigurer extends org.apache.ca case "id": return java.lang.String.class; case "ignoreexceptions": case "ignoreExceptions": return java.util.List.class; + case "maxwaitdurationinhalfopenstate": + case "maxWaitDurationInHalfOpenState": return java.lang.String.class; case "micrometerenabled": case "micrometerEnabled": return java.lang.String.class; case "minimumnumberofcalls": @@ -137,6 +150,8 @@ public class Resilience4jConfigurationDefinitionConfigurer extends org.apache.ca case "recordExceptions": return java.util.List.class; case "slidingwindowsize": case "slidingWindowSize": return java.lang.String.class; + case "slidingwindowsynchronizationstrategy": + case "slidingWindowSynchronizationStrategy": return java.lang.String.class; case "slidingwindowtype": case "slidingWindowType": return java.lang.String.class; case "slowcalldurationthreshold": @@ -169,6 +184,8 @@ public class Resilience4jConfigurationDefinitionConfigurer extends org.apache.ca case "automaticTransitionFromOpenToHalfOpenEnabled": return target.getAutomaticTransitionFromOpenToHalfOpenEnabled(); case "bulkheadenabled": case "bulkheadEnabled": return target.getBulkheadEnabled(); + case "bulkheadfaircallhandlingenabled": + case "bulkheadFairCallHandlingEnabled": return target.getBulkheadFairCallHandlingEnabled(); case "bulkheadmaxconcurrentcalls": case "bulkheadMaxConcurrentCalls": return target.getBulkheadMaxConcurrentCalls(); case "bulkheadmaxwaitduration": @@ -181,6 +198,8 @@ public class Resilience4jConfigurationDefinitionConfigurer extends org.apache.ca case "id": return target.getId(); case "ignoreexceptions": case "ignoreExceptions": return target.getIgnoreExceptions(); + case "maxwaitdurationinhalfopenstate": + case "maxWaitDurationInHalfOpenState": return target.getMaxWaitDurationInHalfOpenState(); case "micrometerenabled": case "micrometerEnabled": return target.getMicrometerEnabled(); case "minimumnumberofcalls": @@ -191,6 +210,8 @@ public class Resilience4jConfigurationDefinitionConfigurer extends org.apache.ca case "recordExceptions": return target.getRecordExceptions(); case "slidingwindowsize": case "slidingWindowSize": return target.getSlidingWindowSize(); + case "slidingwindowsynchronizationstrategy": + case "slidingWindowSynchronizationStrategy": return target.getSlidingWindowSynchronizationStrategy(); case "slidingwindowtype": case "slidingWindowType": return target.getSlidingWindowType(); case "slowcalldurationthreshold": diff --git a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/onFallback.json b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/onFallback.json index fcc732c0c363..115d7228f588 100644 --- a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/onFallback.json +++ b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/onFallback.json @@ -16,7 +16,7 @@ "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "note": { "index": 1, "kind": "attribute", "displayName": "Note", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The note for this node" }, "description": { "index": 2, "kind": "attribute", "displayName": "Description", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The description for this node" }, - "fallbackViaNetwork": { "index": 3, "kind": "attribute", "displayName": "Fallback Via Network", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the fallback goes over the network. If so, the fallback is executed on a separate thread-pool to avoid exhausting the main thread-pool." }, + "fallbackViaNetwork": { "index": 3, "kind": "attribute", "displayName": "Fallback Via Network", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": true, "deprecationNote": "Not supported by any circuit breaker implementation.", "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the fallback goes over the network. If so, the fallback is executed on a separate thread-pool to avo [...] "outputs": { "index": 4, "kind": "element", "displayName": "Outputs", "group": "common", "required": true, "type": "array", "javaType": "java.util.List<org.apache.camel.model.ProcessorDefinition<java.lang.Object>>", "oneOf": [ "a2aSubTask", "aggregate", "bean", "choice", "circuitBreaker", "claimCheck", "convertBodyTo", "convertHeaderTo", "convertVariableTo", "delay", "doCatch", "doFinally", "doTry", "dynamicRouter", "enrich", "filter", "idempotentConsumer", "intercept", "interceptFro [...] } } diff --git a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/resilience4jConfiguration.json b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/resilience4jConfiguration.json index e2ee2d25745b..9b1452808a39 100644 --- a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/resilience4jConfiguration.json +++ b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/resilience4jConfiguration.json @@ -20,21 +20,24 @@ "throwExceptionWhenHalfOpenOrOpenState": { "index": 5, "kind": "attribute", "displayName": "Throw Exception When Half Open Or Open State", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to throw io.github.resilience4j.circuitbreaker.CallNotPermittedException when the call is rejected because the circuit breaker is half open or open." }, "slidingWindowSize": { "index": 6, "kind": "attribute", "displayName": "Sliding Window Size", "group": "common", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 100, "description": "Configures the size 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." }, "slidingWindowType": { "index": 7, "kind": "attribute", "displayName": "Sliding Window Type", "group": "advanced", "label": "advanced", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "TIME_BASED", "COUNT_BASED" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "COUNT_BASED", "description": "Configures the type of the sliding window which is used to record the outcome of calls when the CircuitBreaker is closed. Sliding window ca [...] - "minimumNumberOfCalls": { "index": 8, "kind": "attribute", "displayName": "Minimum Number Of Calls", "group": "common", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 100, "description": "Configures the minimum number of calls which are required (per sliding window period) before the CircuitBreaker can calculate the error rate." }, - "writableStackTraceEnabled": { "index": 9, "kind": "attribute", "displayName": "Writable Stack Trace Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "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 o [...] - "waitDurationInOpenState": { "index": 10, "kind": "attribute", "displayName": "Wait Duration In Open State", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 60, "description": "Configures the wait duration (in seconds) which specifies how long the CircuitBreaker should stay open, before it switches to half open." }, - "automaticTransitionFromOpenToHalfOpenEnabled": { "index": 11, "kind": "attribute", "displayName": "Automatic Transition From Open To Half Open Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enables automatic transition from OPEN to HALF_OPEN state once the waitDurationInOpenState has passed." }, - "slowCallRateThreshold": { "index": 12, "kind": "attribute", "displayName": "Slow Call Rate Threshold", "group": "advanced", "label": "advanced", "required": false, "type": "number", "javaType": "java.lang.Float", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "100", "description": "Configures a threshold in percentage. The CircuitBreaker considers a call as slow when the call duration is greater than slowCallDurationThreshold. When the percentage of slow c [...] - "slowCallDurationThreshold": { "index": 13, "kind": "attribute", "displayName": "Slow Call Duration Threshold", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 60, "description": "Configures the duration threshold (seconds) above which calls are considered as slow and increase the slow calls percentage." }, - "bulkheadEnabled": { "index": 14, "kind": "attribute", "displayName": "Bulkhead Enabled", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether bulkhead is enabled or not on the circuit breaker." }, - "bulkheadMaxConcurrentCalls": { "index": 15, "kind": "attribute", "displayName": "Bulkhead Max Concurrent Calls", "group": "common", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 25, "description": "Configures the max amount of concurrent calls the bulkhead will support." }, - "bulkheadMaxWaitDuration": { "index": 16, "kind": "attribute", "displayName": "Bulkhead Max Wait Duration", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Configures a maximum amount of time which the calling thread will wait to enter the bulkhead." }, - "timeoutEnabled": { "index": 17, "kind": "attribute", "displayName": "Timeout Enabled", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether timeout is enabled or not on the circuit breaker." }, - "timeoutExecutorService": { "index": 18, "kind": "attribute", "displayName": "Timeout Executor Service", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.concurrent.ExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "References to a custom thread pool to use when timeout is enabled (uses ForkJoinPool.commonPool() by default)." }, - "timeoutDuration": { "index": 19, "kind": "attribute", "displayName": "Timeout Duration", "group": "common", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Configures the thread execution timeout. Default value is 1 second." }, - "timeoutCancelRunningFuture": { "index": 20, "kind": "attribute", "displayName": "Timeout Cancel Running Future", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Configures whether cancel is called on the running future. Defaults to true." }, - "micrometerEnabled": { "index": 21, "kind": "attribute", "displayName": "Micrometer Enabled", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable collecting statistics using Micrometer. This requires adding camel-resilience4j-micrometer JAR to the classpath." }, - "recordException": { "index": 22, "kind": "element", "displayName": "Record Exception", "group": "advanced", "label": "advanced", "required": false, "type": "array", "javaType": "java.util.List<java.lang.String>", "deprecated": false, "autowired": false, "secret": false, "description": "Configure a list of exceptions that are recorded as a failure and thus increase the failure rate. Any exception matching or inheriting from one of the list counts as a failure, unless explicitly ignor [...] - "ignoreException": { "index": 23, "kind": "element", "displayName": "Ignore Exception", "group": "advanced", "label": "advanced", "required": false, "type": "array", "javaType": "java.util.List<java.lang.String>", "deprecated": false, "autowired": false, "secret": false, "description": "Configure a list of exceptions that are ignored and neither count as a failure nor success. Any exception matching or inheriting from one of the list will not count as a failure nor success, even if t [...] + "slidingWindowSynchronizationStrategy": { "index": 8, "kind": "attribute", "displayName": "Sliding Window Synchronization Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "LOCK_FREE", "SYNCHRONIZED" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "SYNCHRONIZED", "description": "Configures the synchronization strategy for the sliding window. LOCK_FREE uses a CAS-based lock-fre [...] + "minimumNumberOfCalls": { "index": 9, "kind": "attribute", "displayName": "Minimum Number Of Calls", "group": "common", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 100, "description": "Configures the minimum number of calls which are required (per sliding window period) before the CircuitBreaker can calculate the error rate." }, + "writableStackTraceEnabled": { "index": 10, "kind": "attribute", "displayName": "Writable Stack Trace Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "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 [...] + "waitDurationInOpenState": { "index": 11, "kind": "attribute", "displayName": "Wait Duration In Open State", "group": "advanced", "label": "advanced", "required": false, "type": "duration", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "60000", "description": "Configures the wait duration which specifies how long the CircuitBreaker should stay open, before it switches to half open. The default is 60 seconds." }, + "automaticTransitionFromOpenToHalfOpenEnabled": { "index": 12, "kind": "attribute", "displayName": "Automatic Transition From Open To Half Open Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enables automatic transition from OPEN to HALF_OPEN state once the waitDurationInOpenState has passed." }, + "maxWaitDurationInHalfOpenState": { "index": 13, "kind": "attribute", "displayName": "Max Wait Duration In Half Open State", "group": "advanced", "label": "advanced", "required": false, "type": "duration", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "0", "description": "Configures the maximum wait duration which controls how long the CircuitBreaker should stay in Half Open state, before it switches to open. Value 0 means c [...] + "slowCallRateThreshold": { "index": 14, "kind": "attribute", "displayName": "Slow Call Rate Threshold", "group": "advanced", "label": "advanced", "required": false, "type": "number", "javaType": "java.lang.Float", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "100", "description": "Configures a threshold in percentage. The CircuitBreaker considers a call as slow when the call duration is greater than slowCallDurationThreshold. When the percentage of slow c [...] + "slowCallDurationThreshold": { "index": 15, "kind": "attribute", "displayName": "Slow Call Duration Threshold", "group": "advanced", "label": "advanced", "required": false, "type": "duration", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "60000", "description": "Configures the duration threshold above which calls are considered as slow and increase the slow calls percentage. The default is 60 seconds." }, + "bulkheadEnabled": { "index": 16, "kind": "attribute", "displayName": "Bulkhead Enabled", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether bulkhead is enabled or not on the circuit breaker." }, + "bulkheadMaxConcurrentCalls": { "index": 17, "kind": "attribute", "displayName": "Bulkhead Max Concurrent Calls", "group": "common", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 25, "description": "Configures the max amount of concurrent calls the bulkhead will support." }, + "bulkheadMaxWaitDuration": { "index": 18, "kind": "attribute", "displayName": "Bulkhead Max Wait Duration", "group": "advanced", "label": "advanced", "required": false, "type": "duration", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "0", "description": "Configures a maximum amount of time which the calling thread will wait to enter the bulkhead. The default is 0 (no waiting)." }, + "bulkheadFairCallHandlingEnabled": { "index": 19, "kind": "attribute", "displayName": "Bulkhead Fair Call Handling Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Configures whether the bulkhead uses a fair calling strategy. When enabled (default), a fair strategy guarantees the order of incoming requests (FIFO). Wh [...] + "timeoutEnabled": { "index": 20, "kind": "attribute", "displayName": "Timeout Enabled", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether timeout is enabled or not on the circuit breaker." }, + "timeoutExecutorService": { "index": 21, "kind": "attribute", "displayName": "Timeout Executor Service", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.concurrent.ExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "References to a custom thread pool to use when timeout is enabled (uses ForkJoinPool.commonPool() by default)." }, + "timeoutDuration": { "index": 22, "kind": "attribute", "displayName": "Timeout Duration", "group": "common", "required": false, "type": "duration", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1000", "description": "Configures the thread execution timeout. Default value is 1 second." }, + "timeoutCancelRunningFuture": { "index": 23, "kind": "attribute", "displayName": "Timeout Cancel Running Future", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Configures whether cancel is called on the running future. Defaults to true." }, + "micrometerEnabled": { "index": 24, "kind": "attribute", "displayName": "Micrometer Enabled", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable collecting statistics using Micrometer for all circuit breaker instances. This is a global setting (configure via camel.resilience4j.micrometerEnabled=true) and requires adding camel-resili [...] + "recordException": { "index": 25, "kind": "element", "displayName": "Record Exception", "group": "advanced", "label": "advanced", "required": false, "type": "array", "javaType": "java.util.List<java.lang.String>", "deprecated": false, "autowired": false, "secret": false, "description": "Configure a list of exceptions that are recorded as a failure and thus increase the failure rate. Any exception matching or inheriting from one of the list counts as a failure, unless explicitly ignor [...] + "ignoreException": { "index": 26, "kind": "element", "displayName": "Ignore Exception", "group": "advanced", "label": "advanced", "required": false, "type": "array", "javaType": "java.util.List<java.lang.String>", "deprecated": false, "autowired": false, "secret": false, "description": "Configure a list of exceptions that are ignored and neither count as a failure nor success. Any exception matching or inheriting from one of the list will not count as a failure nor success, even if t [...] } } diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/CircuitBreakerDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/CircuitBreakerDefinition.java index 5dd24e68c7e4..32a64820b317 100644 --- a/core/camel-core-model/src/main/java/org/apache/camel/model/CircuitBreakerDefinition.java +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/CircuitBreakerDefinition.java @@ -218,10 +218,7 @@ public class CircuitBreakerDefinition extends OutputDefinition<CircuitBreakerDef } /** - * The fallback route path to execute that does <b>not</b> go over the network. - * <p> - * This should be a static or cached result that can immediately be returned upon failure. If the fallback requires - * network connection then use {@link #onFallbackViaNetwork()}. + * The fallback route path to execute when the circuit breaker triggers. */ public CircuitBreakerDefinition onFallback() { onFallback = new OnFallbackDefinition(); @@ -233,7 +230,10 @@ public class CircuitBreakerDefinition extends OutputDefinition<CircuitBreakerDef * The fallback route path to execute that will go over the network. * <p/> * If the fallback will go over the network it is another possible point of failure. + * + * @deprecated Not supported by any circuit breaker implementation. Use {@link #onFallback()} instead. */ + @Deprecated(since = "4.22", forRemoval = true) public CircuitBreakerDefinition onFallbackViaNetwork() { onFallback = new OnFallbackDefinition(); onFallback.setFallbackViaNetwork(Boolean.toString(true)); diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/OnFallbackDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/OnFallbackDefinition.java index 3e737b87bfa6..319be4f80e7e 100644 --- a/core/camel-core-model/src/main/java/org/apache/camel/model/OnFallbackDefinition.java +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/OnFallbackDefinition.java @@ -46,7 +46,9 @@ public class OnFallbackDefinition extends OptionalIdentifiedDefinition<OnFallbac private ProcessorDefinition<?> parent; @XmlAttribute @Metadata(label = "advanced", defaultValue = "false", javaType = "java.lang.Boolean", + deprecationNote = "Not supported by any circuit breaker implementation.", description = "Whether the fallback goes over the network. If so, the fallback is executed on a separate thread-pool to avoid exhausting the main thread-pool.") + @Deprecated(since = "4.22", forRemoval = true) private String fallbackViaNetwork; @XmlElementRef @Metadata(description = "The processing steps to execute as fallback.") @@ -105,10 +107,12 @@ public class OnFallbackDefinition extends OptionalIdentifiedDefinition<OnFallbac .collect(Collectors.joining(",", name + "[", "]")); } + @Deprecated(since = "4.22", forRemoval = true) public String getFallbackViaNetwork() { return fallbackViaNetwork; } + @Deprecated(since = "4.22", forRemoval = true) public void setFallbackViaNetwork(String fallbackViaNetwork) { this.fallbackViaNetwork = fallbackViaNetwork; } diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/Resilience4jConfigurationCommon.java b/core/camel-core-model/src/main/java/org/apache/camel/model/Resilience4jConfigurationCommon.java index f465d2c9edad..0724a98c8f7b 100644 --- a/core/camel-core-model/src/main/java/org/apache/camel/model/Resilience4jConfigurationCommon.java +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/Resilience4jConfigurationCommon.java @@ -63,6 +63,12 @@ public class Resilience4jConfigurationCommon extends IdentifiedType { + " Sliding window can either be count-based or time-based.") private String slidingWindowType; @XmlAttribute + @Metadata(label = "advanced", defaultValue = "SYNCHRONIZED", enums = "LOCK_FREE,SYNCHRONIZED", + description = "Configures the synchronization strategy for the sliding window." + + " LOCK_FREE uses a CAS-based lock-free algorithm for better performance under high concurrency." + + " SYNCHRONIZED uses blocking locks with lower memory allocation.") + private String slidingWindowSynchronizationStrategy; + @XmlAttribute @Metadata(defaultValue = "100", javaType = "java.lang.Integer", description = "Configures the minimum number of calls which are required (per sliding window period) before the CircuitBreaker can calculate the error rate.") private String minimumNumberOfCalls; @@ -72,21 +78,29 @@ public class Resilience4jConfigurationCommon extends IdentifiedType { + " This may be used to reduce log spam when the circuit breaker is open.") private String writableStackTraceEnabled; @XmlAttribute - @Metadata(label = "advanced", defaultValue = "60", javaType = "java.lang.Integer", - description = "Configures the wait duration (in seconds) which specifies how long the CircuitBreaker should stay open, before it switches to half open.") + @Metadata(label = "advanced", defaultValue = "60000", javaType = "java.time.Duration", + description = "Configures the wait duration which specifies how long the CircuitBreaker should stay open, before it switches to half open." + + " The default is 60 seconds.") private String waitDurationInOpenState; @XmlAttribute @Metadata(label = "advanced", defaultValue = "false", javaType = "java.lang.Boolean", description = "Enables automatic transition from OPEN to HALF_OPEN state once the waitDurationInOpenState has passed.") private String automaticTransitionFromOpenToHalfOpenEnabled; @XmlAttribute + @Metadata(label = "advanced", defaultValue = "0", javaType = "java.time.Duration", + description = "Configures the maximum wait duration which controls how long the CircuitBreaker should stay in Half Open state," + + " before it switches to open. Value 0 means circuit breaker will wait in half open state" + + " until all permitted calls have been completed.") + private String maxWaitDurationInHalfOpenState; + @XmlAttribute @Metadata(label = "advanced", defaultValue = "100", javaType = "java.lang.Float", description = "Configures a threshold in percentage. The CircuitBreaker considers a call as slow when the call duration is greater than slowCallDurationThreshold." + " When the percentage of slow calls is equal or greater the threshold, the CircuitBreaker transitions to open and starts short-circuiting calls.") private String slowCallRateThreshold; @XmlAttribute - @Metadata(label = "advanced", defaultValue = "60", javaType = "java.lang.Integer", - description = "Configures the duration threshold (seconds) above which calls are considered as slow and increase the slow calls percentage.") + @Metadata(label = "advanced", defaultValue = "60000", javaType = "java.time.Duration", + description = "Configures the duration threshold above which calls are considered as slow and increase the slow calls percentage." + + " The default is 60 seconds.") private String slowCallDurationThreshold; @XmlAttribute @Metadata(defaultValue = "false", javaType = "java.lang.Boolean", @@ -97,10 +111,17 @@ public class Resilience4jConfigurationCommon extends IdentifiedType { description = "Configures the max amount of concurrent calls the bulkhead will support.") private String bulkheadMaxConcurrentCalls; @XmlAttribute - @Metadata(label = "advanced", defaultValue = "0", javaType = "java.lang.Integer", - description = "Configures a maximum amount of time which the calling thread will wait to enter the bulkhead.") + @Metadata(label = "advanced", defaultValue = "0", javaType = "java.time.Duration", + description = "Configures a maximum amount of time which the calling thread will wait to enter the bulkhead." + + " The default is 0 (no waiting).") private String bulkheadMaxWaitDuration; @XmlAttribute + @Metadata(label = "advanced", defaultValue = "true", javaType = "java.lang.Boolean", + description = "Configures whether the bulkhead uses a fair calling strategy." + + " When enabled (default), a fair strategy guarantees the order of incoming requests (FIFO)." + + " When disabled, no ordering is guaranteed and may improve throughput.") + private String bulkheadFairCallHandlingEnabled; + @XmlAttribute @Metadata(defaultValue = "false", javaType = "java.lang.Boolean", description = "Whether timeout is enabled or not on the circuit breaker.") private String timeoutEnabled; @@ -109,7 +130,7 @@ public class Resilience4jConfigurationCommon extends IdentifiedType { description = "References to a custom thread pool to use when timeout is enabled (uses ForkJoinPool.commonPool() by default).") private String timeoutExecutorService; @XmlAttribute - @Metadata(defaultValue = "1000", javaType = "java.lang.Integer", + @Metadata(defaultValue = "1000", javaType = "java.time.Duration", description = "Configures the thread execution timeout. Default value is 1 second.") private String timeoutDuration; @XmlAttribute @@ -118,7 +139,9 @@ public class Resilience4jConfigurationCommon extends IdentifiedType { private String timeoutCancelRunningFuture; @XmlAttribute @Metadata(defaultValue = "false", javaType = "java.lang.Boolean", - description = "Whether to enable collecting statistics using Micrometer. This requires adding camel-resilience4j-micrometer JAR to the classpath.") + description = "Whether to enable collecting statistics using Micrometer for all circuit breaker instances." + + " This is a global setting (configure via camel.resilience4j.micrometerEnabled=true)" + + " and requires adding camel-resilience4j-micrometer JAR to the classpath.") private String micrometerEnabled; @XmlElement(name = "recordException") @Metadata(label = "advanced", @@ -142,15 +165,18 @@ public class Resilience4jConfigurationCommon extends IdentifiedType { this.throwExceptionWhenHalfOpenOrOpenState = source.throwExceptionWhenHalfOpenOrOpenState; this.slidingWindowSize = source.slidingWindowSize; this.slidingWindowType = source.slidingWindowType; + this.slidingWindowSynchronizationStrategy = source.slidingWindowSynchronizationStrategy; this.minimumNumberOfCalls = source.minimumNumberOfCalls; this.writableStackTraceEnabled = source.writableStackTraceEnabled; this.waitDurationInOpenState = source.waitDurationInOpenState; this.automaticTransitionFromOpenToHalfOpenEnabled = source.automaticTransitionFromOpenToHalfOpenEnabled; + this.maxWaitDurationInHalfOpenState = source.maxWaitDurationInHalfOpenState; this.slowCallRateThreshold = source.slowCallRateThreshold; this.slowCallDurationThreshold = source.slowCallDurationThreshold; this.bulkheadEnabled = source.bulkheadEnabled; this.bulkheadMaxConcurrentCalls = source.bulkheadMaxConcurrentCalls; this.bulkheadMaxWaitDuration = source.bulkheadMaxWaitDuration; + this.bulkheadFairCallHandlingEnabled = source.bulkheadFairCallHandlingEnabled; this.timeoutEnabled = source.timeoutEnabled; this.micrometerEnabled = source.micrometerEnabled; this.timeoutExecutorService = source.timeoutExecutorService; @@ -223,6 +249,14 @@ public class Resilience4jConfigurationCommon extends IdentifiedType { this.slidingWindowType = slidingWindowType; } + public String getSlidingWindowSynchronizationStrategy() { + return slidingWindowSynchronizationStrategy; + } + + public void setSlidingWindowSynchronizationStrategy(String slidingWindowSynchronizationStrategy) { + this.slidingWindowSynchronizationStrategy = slidingWindowSynchronizationStrategy; + } + public String getMinimumNumberOfCalls() { return minimumNumberOfCalls; } @@ -255,6 +289,14 @@ public class Resilience4jConfigurationCommon extends IdentifiedType { this.automaticTransitionFromOpenToHalfOpenEnabled = automaticTransitionFromOpenToHalfOpenEnabled; } + public String getMaxWaitDurationInHalfOpenState() { + return maxWaitDurationInHalfOpenState; + } + + public void setMaxWaitDurationInHalfOpenState(String maxWaitDurationInHalfOpenState) { + this.maxWaitDurationInHalfOpenState = maxWaitDurationInHalfOpenState; + } + public String getSlowCallRateThreshold() { return slowCallRateThreshold; } @@ -295,6 +337,14 @@ public class Resilience4jConfigurationCommon extends IdentifiedType { this.bulkheadMaxWaitDuration = bulkheadMaxWaitDuration; } + public String getBulkheadFairCallHandlingEnabled() { + return bulkheadFairCallHandlingEnabled; + } + + public void setBulkheadFairCallHandlingEnabled(String bulkheadFairCallHandlingEnabled) { + this.bulkheadFairCallHandlingEnabled = bulkheadFairCallHandlingEnabled; + } + public String getTimeoutEnabled() { return timeoutEnabled; } diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/Resilience4jConfigurationDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/Resilience4jConfigurationDefinition.java index 7295c6f74d9f..edb2c701f627 100644 --- a/core/camel-core-model/src/main/java/org/apache/camel/model/Resilience4jConfigurationDefinition.java +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/Resilience4jConfigurationDefinition.java @@ -180,6 +180,18 @@ public class Resilience4jConfigurationDefinition extends Resilience4jConfigurati return this; } + /** + * Configures the synchronization strategy for the sliding window. LOCK_FREE uses a CAS-based lock-free algorithm + * for better performance under high concurrency. SYNCHRONIZED uses blocking locks with lower memory allocation. + * + * Default is SYNCHRONIZED. + */ + public Resilience4jConfigurationDefinition slidingWindowSynchronizationStrategy( + String slidingWindowSynchronizationStrategy) { + setSlidingWindowSynchronizationStrategy(slidingWindowSynchronizationStrategy); + 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 @@ -221,8 +233,8 @@ public class Resilience4jConfigurationDefinition extends Resilience4jConfigurati } /** - * 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. + * Configures the wait duration (in millis) which specifies how long the CircuitBreaker should stay open, before it + * switches to half open. Default value is 60 seconds (60000 millis). */ public Resilience4jConfigurationDefinition waitDurationInOpenState(int waitDurationInOpenState) { setWaitDurationInOpenState(Integer.toString(waitDurationInOpenState)); @@ -230,7 +242,8 @@ public class Resilience4jConfigurationDefinition extends Resilience4jConfigurati } /** - * Configures the wait duration in open state (seconds). Supports property placeholders. + * Configures the wait duration in open state. Accepts a Camel duration (e.g. 60s, 1m, 60000) or ISO-8601 format + * (e.g. PT1M). Default value is 60 seconds. Supports property placeholders. */ public Resilience4jConfigurationDefinition waitDurationInOpenState(String waitDurationInOpenState) { setWaitDurationInOpenState(waitDurationInOpenState); @@ -255,6 +268,25 @@ public class Resilience4jConfigurationDefinition extends Resilience4jConfigurati return this; } + /** + * Configures the maximum wait duration (in millis) which controls how long the CircuitBreaker should stay in Half + * Open state, before it switches to open. Value 0 means circuit breaker will wait in half open state until all + * permitted calls have been completed. + */ + public Resilience4jConfigurationDefinition maxWaitDurationInHalfOpenState(int maxWaitDurationInHalfOpenState) { + setMaxWaitDurationInHalfOpenState(Integer.toString(maxWaitDurationInHalfOpenState)); + return this; + } + + /** + * Configures the maximum wait duration which controls how long the CircuitBreaker should stay in Half Open state. + * Accepts a Camel duration (e.g. 30s, 1m, 30000) or ISO-8601 format (e.g. PT30S). Supports property placeholders. + */ + public Resilience4jConfigurationDefinition maxWaitDurationInHalfOpenState(String maxWaitDurationInHalfOpenState) { + setMaxWaitDurationInHalfOpenState(maxWaitDurationInHalfOpenState); + 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 @@ -277,8 +309,8 @@ public class Resilience4jConfigurationDefinition extends Resilience4jConfigurati } /** - * Configures the duration threshold (seconds) above which calls are considered as slow and increase the slow calls - * percentage. Default value is 60 seconds. + * Configures the duration threshold (in millis) above which calls are considered as slow and increase the slow + * calls percentage. Default value is 60 seconds (60000 millis). */ public Resilience4jConfigurationDefinition slowCallDurationThreshold(int slowCallDurationThreshold) { setSlowCallDurationThreshold(Integer.toString(slowCallDurationThreshold)); @@ -286,8 +318,8 @@ public class Resilience4jConfigurationDefinition extends Resilience4jConfigurati } /** - * Configures the duration threshold (seconds) above which calls are considered as slow. Supports property - * placeholders. + * Configures the duration threshold above which calls are considered as slow. Accepts a Camel duration (e.g. 60s, + * 1m, 60000) or ISO-8601 format (e.g. PT1M). Default value is 60 seconds. Supports property placeholders. */ public Resilience4jConfigurationDefinition slowCallDurationThreshold(String slowCallDurationThreshold) { setSlowCallDurationThreshold(slowCallDurationThreshold); @@ -327,9 +359,9 @@ public class Resilience4jConfigurationDefinition extends Resilience4jConfigurati } /** - * 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. + * Configures a maximum amount of time (in millis) 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 @@ -341,14 +373,31 @@ public class Resilience4jConfigurationDefinition extends Resilience4jConfigurati } /** - * Configures a maximum amount of time for the calling thread to wait to enter the bulkhead. Supports property - * placeholders. + * Configures a maximum amount of time for the calling thread to wait to enter the bulkhead. Accepts a Camel + * duration (e.g. 500ms, 5s, 5000) or ISO-8601 format (e.g. PT5S). Supports property placeholders. */ public Resilience4jConfigurationDefinition bulkheadMaxWaitDuration(String bulkheadMaxWaitDuration) { setBulkheadMaxWaitDuration(bulkheadMaxWaitDuration); return this; } + /** + * Configures whether the bulkhead uses a fair calling strategy. When enabled (default), a fair strategy guarantees + * the order of incoming requests (FIFO). When disabled, no ordering is guaranteed and may improve throughput. + */ + public Resilience4jConfigurationDefinition bulkheadFairCallHandlingEnabled(boolean bulkheadFairCallHandlingEnabled) { + setBulkheadFairCallHandlingEnabled(Boolean.toString(bulkheadFairCallHandlingEnabled)); + return this; + } + + /** + * Configures whether the bulkhead uses a fair calling strategy. Supports property placeholders. + */ + public Resilience4jConfigurationDefinition bulkheadFairCallHandlingEnabled(String bulkheadFairCallHandlingEnabled) { + setBulkheadFairCallHandlingEnabled(bulkheadFairCallHandlingEnabled); + return this; + } + /** * Whether timeout is enabled or not on the circuit breaker. Default is false. */ @@ -375,7 +424,7 @@ public class Resilience4jConfigurationDefinition extends Resilience4jConfigurati } /** - * Configures the thread execution timeout (millis). Default value is 1000 millis (1 second). + * Configures the thread execution timeout (in millis). Default value is 1000 millis (1 second). */ public Resilience4jConfigurationDefinition timeoutDuration(int timeoutDuration) { setTimeoutDuration(Integer.toString(timeoutDuration)); @@ -383,7 +432,8 @@ public class Resilience4jConfigurationDefinition extends Resilience4jConfigurati } /** - * Configures the thread execution timeout (millis). Supports property placeholders. + * Configures the thread execution timeout. Accepts a Camel duration (e.g. 1s, 1000, 500ms) or ISO-8601 format (e.g. + * PT1S). Default value is 1 second. Supports property placeholders. */ public Resilience4jConfigurationDefinition timeoutDuration(String timeoutDuration) { setTimeoutDuration(timeoutDuration); @@ -391,8 +441,9 @@ public class Resilience4jConfigurationDefinition extends Resilience4jConfigurati } /** - * Whether to enable collecting statistics using Micrometer. This requires adding camel-resilience4j-micrometer JAR - * to the classpath. + * Whether to enable collecting statistics using Micrometer for all circuit breaker instances. This is a global + * setting (configure via camel.resilience4j.micrometerEnabled=true) and requires adding + * camel-resilience4j-micrometer JAR to the classpath. */ public Resilience4jConfigurationDefinition micrometerEnabled(boolean micrometerEnabled) { setMicrometerEnabled(Boolean.toString(micrometerEnabled)); @@ -400,7 +451,8 @@ public class Resilience4jConfigurationDefinition extends Resilience4jConfigurati } /** - * Whether to enable collecting statistics using Micrometer. Supports property placeholders. + * Whether to enable collecting statistics using Micrometer for all circuit breaker instances. Supports property + * placeholders. */ public Resilience4jConfigurationDefinition micrometerEnabled(String micrometerEnabled) { setMicrometerEnabled(micrometerEnabled); diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java index c54e2fd73f63..4bd796100d35 100644 --- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java +++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java @@ -796,15 +796,18 @@ public class ModelParser extends BaseParser { return (def, key, val) -> switch (key) { case "automaticTransitionFromOpenToHalfOpenEnabled": def.setAutomaticTransitionFromOpenToHalfOpenEnabled(val); yield true; case "bulkheadEnabled": def.setBulkheadEnabled(val); yield true; + case "bulkheadFairCallHandlingEnabled": def.setBulkheadFairCallHandlingEnabled(val); yield true; case "bulkheadMaxConcurrentCalls": def.setBulkheadMaxConcurrentCalls(val); yield true; case "bulkheadMaxWaitDuration": def.setBulkheadMaxWaitDuration(val); yield true; case "circuitBreaker": def.setCircuitBreaker(val); yield true; case "config": def.setConfig(val); yield true; case "failureRateThreshold": def.setFailureRateThreshold(val); yield true; + case "maxWaitDurationInHalfOpenState": def.setMaxWaitDurationInHalfOpenState(val); yield true; case "micrometerEnabled": def.setMicrometerEnabled(val); yield true; case "minimumNumberOfCalls": def.setMinimumNumberOfCalls(val); yield true; case "permittedNumberOfCallsInHalfOpenState": def.setPermittedNumberOfCallsInHalfOpenState(val); yield true; case "slidingWindowSize": def.setSlidingWindowSize(val); yield true; + case "slidingWindowSynchronizationStrategy": def.setSlidingWindowSynchronizationStrategy(val); yield true; case "slidingWindowType": def.setSlidingWindowType(val); yield true; case "slowCallDurationThreshold": def.setSlowCallDurationThreshold(val); yield true; case "slowCallRateThreshold": def.setSlowCallRateThreshold(val); yield true; diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java index 01cb827aa25a..74a821b868bd 100644 --- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java +++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java @@ -1505,27 +1505,30 @@ public class ModelWriter extends BaseWriter { } protected void doWriteResilience4jConfigurationCommonAttributes(Resilience4jConfigurationCommon def) throws IOException { doWriteIdentifiedTypeAttributes(def); - doWriteAttribute("failureRateThreshold", def.getFailureRateThreshold(), "50"); doWriteAttribute("bulkheadMaxWaitDuration", def.getBulkheadMaxWaitDuration(), "0"); - doWriteAttribute("slowCallDurationThreshold", def.getSlowCallDurationThreshold(), "60"); doWriteAttribute("timeoutCancelRunningFuture", def.getTimeoutCancelRunningFuture(), "true"); doWriteAttribute("minimumNumberOfCalls", def.getMinimumNumberOfCalls(), "100"); + doWriteAttribute("slidingWindowSynchronizationStrategy", def.getSlidingWindowSynchronizationStrategy(), "SYNCHRONIZED"); doWriteAttribute("timeoutDuration", def.getTimeoutDuration(), "1000"); + doWriteAttribute("permittedNumberOfCallsInHalfOpenState", def.getPermittedNumberOfCallsInHalfOpenState(), "10"); + doWriteAttribute("slowCallRateThreshold", def.getSlowCallRateThreshold(), "100"); + doWriteAttribute("bulkheadFairCallHandlingEnabled", def.getBulkheadFairCallHandlingEnabled(), "true"); + doWriteAttribute("circuitBreaker", def.getCircuitBreaker(), null); + doWriteAttribute("bulkheadMaxConcurrentCalls", def.getBulkheadMaxConcurrentCalls(), "25"); + doWriteAttribute("bulkheadEnabled", def.getBulkheadEnabled(), "false"); + doWriteAttribute("maxWaitDurationInHalfOpenState", def.getMaxWaitDurationInHalfOpenState(), "0"); + doWriteAttribute("failureRateThreshold", def.getFailureRateThreshold(), "50"); + doWriteAttribute("slowCallDurationThreshold", def.getSlowCallDurationThreshold(), "60000"); doWriteAttribute("timeoutEnabled", def.getTimeoutEnabled(), "false"); doWriteAttribute("timeoutExecutorService", def.getTimeoutExecutorService(), null); - doWriteAttribute("permittedNumberOfCallsInHalfOpenState", def.getPermittedNumberOfCallsInHalfOpenState(), "10"); doWriteAttribute("throwExceptionWhenHalfOpenOrOpenState", def.getThrowExceptionWhenHalfOpenOrOpenState(), "false"); - doWriteAttribute("slowCallRateThreshold", def.getSlowCallRateThreshold(), "100"); doWriteAttribute("micrometerEnabled", def.getMicrometerEnabled(), "false"); doWriteAttribute("writableStackTraceEnabled", def.getWritableStackTraceEnabled(), "true"); doWriteAttribute("automaticTransitionFromOpenToHalfOpenEnabled", def.getAutomaticTransitionFromOpenToHalfOpenEnabled(), "false"); - doWriteAttribute("circuitBreaker", def.getCircuitBreaker(), null); doWriteAttribute("slidingWindowSize", def.getSlidingWindowSize(), "100"); doWriteAttribute("config", def.getConfig(), null); - doWriteAttribute("bulkheadMaxConcurrentCalls", def.getBulkheadMaxConcurrentCalls(), "25"); doWriteAttribute("slidingWindowType", def.getSlidingWindowType(), "COUNT_BASED"); - doWriteAttribute("bulkheadEnabled", def.getBulkheadEnabled(), "false"); - doWriteAttribute("waitDurationInOpenState", def.getWaitDurationInOpenState(), "60"); + doWriteAttribute("waitDurationInOpenState", def.getWaitDurationInOpenState(), "60000"); } protected void doWriteResilience4jConfigurationCommonElements(Resilience4jConfigurationCommon def) throws IOException { doWriteList(null, "ignoreException", def.getIgnoreExceptions(), this::doWriteString); diff --git a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/YamlModelWriter.java b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/YamlModelWriter.java index de61b92c6eab..cfccadbcb2ad 100644 --- a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/YamlModelWriter.java +++ b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/YamlModelWriter.java @@ -1500,27 +1500,30 @@ public class YamlModelWriter extends YamlModelWriterSupport { } protected void doWriteResilience4jConfigurationCommonAttributes(JsonObject jo, Resilience4jConfigurationCommon def) { doWriteIdentifiedTypeAttributes(jo, def); - doWriteAttribute(jo, "failureRateThreshold", def.getFailureRateThreshold(), "50"); doWriteAttribute(jo, "bulkheadMaxWaitDuration", def.getBulkheadMaxWaitDuration(), "0"); - doWriteAttribute(jo, "slowCallDurationThreshold", def.getSlowCallDurationThreshold(), "60"); doWriteAttribute(jo, "timeoutCancelRunningFuture", def.getTimeoutCancelRunningFuture(), "true"); doWriteAttribute(jo, "minimumNumberOfCalls", def.getMinimumNumberOfCalls(), "100"); + doWriteAttribute(jo, "slidingWindowSynchronizationStrategy", def.getSlidingWindowSynchronizationStrategy(), "SYNCHRONIZED"); doWriteAttribute(jo, "timeoutDuration", def.getTimeoutDuration(), "1000"); + doWriteAttribute(jo, "permittedNumberOfCallsInHalfOpenState", def.getPermittedNumberOfCallsInHalfOpenState(), "10"); + doWriteAttribute(jo, "slowCallRateThreshold", def.getSlowCallRateThreshold(), "100"); + doWriteAttribute(jo, "bulkheadFairCallHandlingEnabled", def.getBulkheadFairCallHandlingEnabled(), "true"); + doWriteAttribute(jo, "circuitBreaker", def.getCircuitBreaker(), null); + doWriteAttribute(jo, "bulkheadMaxConcurrentCalls", def.getBulkheadMaxConcurrentCalls(), "25"); + doWriteAttribute(jo, "bulkheadEnabled", def.getBulkheadEnabled(), "false"); + doWriteAttribute(jo, "maxWaitDurationInHalfOpenState", def.getMaxWaitDurationInHalfOpenState(), "0"); + doWriteAttribute(jo, "failureRateThreshold", def.getFailureRateThreshold(), "50"); + doWriteAttribute(jo, "slowCallDurationThreshold", def.getSlowCallDurationThreshold(), "60000"); doWriteAttribute(jo, "timeoutEnabled", def.getTimeoutEnabled(), "false"); doWriteAttribute(jo, "timeoutExecutorService", def.getTimeoutExecutorService(), null); - doWriteAttribute(jo, "permittedNumberOfCallsInHalfOpenState", def.getPermittedNumberOfCallsInHalfOpenState(), "10"); doWriteAttribute(jo, "throwExceptionWhenHalfOpenOrOpenState", def.getThrowExceptionWhenHalfOpenOrOpenState(), "false"); - doWriteAttribute(jo, "slowCallRateThreshold", def.getSlowCallRateThreshold(), "100"); doWriteAttribute(jo, "micrometerEnabled", def.getMicrometerEnabled(), "false"); doWriteAttribute(jo, "writableStackTraceEnabled", def.getWritableStackTraceEnabled(), "true"); doWriteAttribute(jo, "automaticTransitionFromOpenToHalfOpenEnabled", def.getAutomaticTransitionFromOpenToHalfOpenEnabled(), "false"); - doWriteAttribute(jo, "circuitBreaker", def.getCircuitBreaker(), null); doWriteAttribute(jo, "slidingWindowSize", def.getSlidingWindowSize(), "100"); doWriteAttribute(jo, "config", def.getConfig(), null); - doWriteAttribute(jo, "bulkheadMaxConcurrentCalls", def.getBulkheadMaxConcurrentCalls(), "25"); doWriteAttribute(jo, "slidingWindowType", def.getSlidingWindowType(), "COUNT_BASED"); - doWriteAttribute(jo, "bulkheadEnabled", def.getBulkheadEnabled(), "false"); - doWriteAttribute(jo, "waitDurationInOpenState", def.getWaitDurationInOpenState(), "60"); + doWriteAttribute(jo, "waitDurationInOpenState", def.getWaitDurationInOpenState(), "60000"); } protected void doWriteResilience4jConfigurationCommonElements(JsonObject jo, Resilience4jConfigurationCommon def) { doWriteStringList(jo, null, "ignoreException", def.getIgnoreExceptions()); diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc index e70c63e1c550..0cbcec0366f8 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc @@ -763,3 +763,43 @@ add `precision = 0` explicitly to your `@DataField` annotation. The `transformerFactoryConfigurationStrategy` option is now applied on all factory creation paths. Previously on `xslt-saxon` it was never invoked, and on plain `xslt` it was only invoked when `transformerFactoryClass` was explicitly set. + +=== Circuit Breaker EIP - onFallbackViaNetwork deprecated + +The `onFallbackViaNetwork()` DSL method and the `fallbackViaNetwork` option on `onFallback` have been +deprecated for removal. This was a Hystrix-era concept that has never been supported by any current +circuit breaker implementation — both `camel-resilience4j` and `camel-microprofile-fault-tolerance` +throw `UnsupportedOperationException` at route initialization when it is enabled. +Use `onFallback()` instead. + +=== camel-resilience4j - Duration options now use Camel duration format + +The following Resilience4j configuration options now use `java.time.Duration` type instead of plain integers, +and accept Camel duration expressions (e.g. `60s`, `1m`, `PT1M`) as well as plain millisecond values: + +- `waitDurationInOpenState` — previously accepted seconds (default `60`), now accepts millis or duration strings (default `60000` or `60s`) +- `slowCallDurationThreshold` — previously accepted seconds (default `60`), now accepts millis or duration strings (default `60000` or `60s`) +- `timeoutDuration` — unchanged (was already millis, default `1000`) +- `bulkheadMaxWaitDuration` — unchanged (was already millis, default `0`) + +If you configured `waitDurationInOpenState` or `slowCallDurationThreshold` with a plain integer meaning seconds, +you must update the value to use a duration suffix (e.g. `60s`) or convert to milliseconds (e.g. `60000`). + +For example: +[source,java] +---- +// Before (seconds): +.waitDurationInOpenState(60) + +// After (millis): +.waitDurationInOpenState(60000) + +// Or using duration string: +.waitDurationInOpenState("60s") +---- + +=== camel-resilience4j - Vavr dependency removed + +The `io.vavr:vavr` and `io.vavr:vavr-match` runtime dependencies have been removed from +`camel-resilience4j`. The single internal usage of Vavr's `Try` monad has been replaced with a +plain try-catch. This eliminates two transitive runtime JARs. No user-facing behavior change. diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java index bd73dd58e608..41b495835e32 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java @@ -10622,7 +10622,7 @@ public final class ModelDeserializers extends YamlDeserializerSupport { deprecated = false, properties = { @YamlProperty(name = "description", type = "string", description = "The description for this node", displayName = "Description"), - @YamlProperty(name = "fallbackViaNetwork", type = "boolean", defaultValue = "false", description = "Whether the fallback goes over the network. If so, the fallback is executed on a separate thread-pool to avoid exhausting the main thread-pool.", displayName = "Fallback Via Network"), + @YamlProperty(name = "fallbackViaNetwork", type = "boolean", deprecated = true, defaultValue = "false", description = "Whether the fallback goes over the network. If so, the fallback is executed on a separate thread-pool to avoid exhausting the main thread-pool.", displayName = "Fallback Via Network"), @YamlProperty(name = "id", type = "string", description = "The id of this node", displayName = "Id"), @YamlProperty(name = "note", type = "string", description = "The note for this node", displayName = "Note"), @YamlProperty(name = "steps", type = "array:org.apache.camel.model.ProcessorDefinition") @@ -13886,27 +13886,30 @@ public final class ModelDeserializers extends YamlDeserializerSupport { properties = { @YamlProperty(name = "automaticTransitionFromOpenToHalfOpenEnabled", type = "boolean", defaultValue = "false", description = "Enables automatic transition from OPEN to HALF_OPEN state once the waitDurationInOpenState has passed.", displayName = "Automatic Transition From Open To Half Open Enabled"), @YamlProperty(name = "bulkheadEnabled", type = "boolean", defaultValue = "false", description = "Whether bulkhead is enabled or not on the circuit breaker.", displayName = "Bulkhead Enabled"), + @YamlProperty(name = "bulkheadFairCallHandlingEnabled", type = "boolean", defaultValue = "true", description = "Configures whether the bulkhead uses a fair calling strategy. When enabled (default), a fair strategy guarantees the order of incoming requests (FIFO). When disabled, no ordering is guaranteed and may improve throughput.", displayName = "Bulkhead Fair Call Handling Enabled"), @YamlProperty(name = "bulkheadMaxConcurrentCalls", type = "number", defaultValue = "25", description = "Configures the max amount of concurrent calls the bulkhead will support.", displayName = "Bulkhead Max Concurrent Calls"), - @YamlProperty(name = "bulkheadMaxWaitDuration", type = "number", defaultValue = "0", description = "Configures a maximum amount of time which the calling thread will wait to enter the bulkhead.", displayName = "Bulkhead Max Wait Duration"), + @YamlProperty(name = "bulkheadMaxWaitDuration", type = "string", defaultValue = "0", description = "Configures a maximum amount of time which the calling thread will wait to enter the bulkhead. The default is 0 (no waiting).", displayName = "Bulkhead Max Wait Duration"), @YamlProperty(name = "circuitBreaker", type = "string", description = "Refers to an existing io.github.resilience4j.circuitbreaker.CircuitBreaker instance to lookup and use from the registry. When using this, then any other circuit breaker options are not in use.", displayName = "Circuit Breaker"), @YamlProperty(name = "config", type = "string", description = "Refers to an existing io.github.resilience4j.circuitbreaker.CircuitBreakerConfig instance to lookup and use from the registry.", displayName = "Config"), @YamlProperty(name = "failureRateThreshold", type = "number", defaultValue = "50", description = "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.", displayName = "Failure Rate Threshold"), @YamlProperty(name = "id", type = "string", description = "The id of this node", displayName = "Id"), @YamlProperty(name = "ignoreException", type = "array:string", description = "Configure a list of exceptions that are ignored and neither count as a failure nor success. Any exception matching or inheriting from one of the list will not count as a failure nor success, even if the exception is part of recordExceptions.", displayName = "Ignore Exception"), - @YamlProperty(name = "micrometerEnabled", type = "boolean", defaultValue = "false", description = "Whether to enable collecting statistics using Micrometer. This requires adding camel-resilience4j-micrometer JAR to the classpath.", displayName = "Micrometer Enabled"), + @YamlProperty(name = "maxWaitDurationInHalfOpenState", type = "string", defaultValue = "0", description = "Configures the maximum wait duration which controls how long the CircuitBreaker should stay in Half Open state, before it switches to open. Value 0 means circuit breaker will wait in half open state until all permitted calls have been completed.", displayName = "Max Wait Duration In Half Open State"), + @YamlProperty(name = "micrometerEnabled", type = "boolean", defaultValue = "false", description = "Whether to enable collecting statistics using Micrometer for all circuit breaker instances. This is a global setting (configure via camel.resilience4j.micrometerEnabled=true) and requires adding camel-resilience4j-micrometer JAR to the classpath.", displayName = "Micrometer Enabled"), @YamlProperty(name = "minimumNumberOfCalls", type = "number", defaultValue = "100", description = "Configures the minimum number of calls which are required (per sliding window period) before the CircuitBreaker can calculate the error rate.", displayName = "Minimum Number Of Calls"), @YamlProperty(name = "permittedNumberOfCallsInHalfOpenState", type = "number", defaultValue = "10", description = "Configures the number of permitted calls when the CircuitBreaker is half open.", displayName = "Permitted Number Of Calls In Half Open State"), @YamlProperty(name = "recordException", type = "array:string", description = "Configure a list of exceptions that are recorded as a failure and thus increase the failure rate. Any exception matching or inheriting from one of the list counts as a failure, unless explicitly ignored via ignoreExceptions.", displayName = "Record Exception"), @YamlProperty(name = "slidingWindowSize", type = "number", defaultValue = "100", description = "Configures the size 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.", displayName = "Sliding Window Size"), + @YamlProperty(name = "slidingWindowSynchronizationStrategy", type = "enum:LOCK_FREE,SYNCHRONIZED", defaultValue = "SYNCHRONIZED", description = "Configures the synchronization strategy for the sliding window. LOCK_FREE uses a CAS-based lock-free algorithm for better performance under high concurrency. SYNCHRONIZED uses blocking locks with lower memory allocation.", displayName = "Sliding Window Synchronization Strategy"), @YamlProperty(name = "slidingWindowType", type = "enum:TIME_BASED,COUNT_BASED", defaultValue = "COUNT_BASED", description = "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.", displayName = "Sliding Window Type"), - @YamlProperty(name = "slowCallDurationThreshold", type = "number", defaultValue = "60", description = "Configures the duration threshold (seconds) above which calls are considered as slow and increase the slow calls percentage.", displayName = "Slow Call Duration Threshold"), + @YamlProperty(name = "slowCallDurationThreshold", type = "string", defaultValue = "60000", description = "Configures the duration threshold above which calls are considered as slow and increase the slow calls percentage. The default is 60 seconds.", displayName = "Slow Call Duration Threshold"), @YamlProperty(name = "slowCallRateThreshold", type = "number", defaultValue = "100", description = "Configures a threshold in percentage. The CircuitBreaker considers a call as slow when the call duration is greater than slowCallDurationThreshold. When the percentage of slow calls is equal or greater the threshold, the CircuitBreaker transitions to open and starts short-circuiting calls.", displayName = "Slow Call Rate Threshold"), @YamlProperty(name = "throwExceptionWhenHalfOpenOrOpenState", type = "boolean", defaultValue = "false", description = "Whether to throw io.github.resilience4j.circuitbreaker.CallNotPermittedException when the call is rejected because the circuit breaker is half open or open.", displayName = "Throw Exception When Half Open Or Open State"), @YamlProperty(name = "timeoutCancelRunningFuture", type = "boolean", defaultValue = "true", description = "Configures whether cancel is called on the running future. Defaults to true.", displayName = "Timeout Cancel Running Future"), - @YamlProperty(name = "timeoutDuration", type = "number", defaultValue = "1000", description = "Configures the thread execution timeout. Default value is 1 second.", displayName = "Timeout Duration"), + @YamlProperty(name = "timeoutDuration", type = "string", defaultValue = "1000", description = "Configures the thread execution timeout. Default value is 1 second.", displayName = "Timeout Duration"), @YamlProperty(name = "timeoutEnabled", type = "boolean", defaultValue = "false", description = "Whether timeout is enabled or not on the circuit breaker.", displayName = "Timeout Enabled"), @YamlProperty(name = "timeoutExecutorService", type = "string", description = "References to a custom thread pool to use when timeout is enabled (uses ForkJoinPool.commonPool() by default).", displayName = "Timeout Executor Service"), - @YamlProperty(name = "waitDurationInOpenState", type = "number", defaultValue = "60", description = "Configures the wait duration (in seconds) which specifies how long the CircuitBreaker should stay open, before it switches to half open.", displayName = "Wait Duration In Open State"), + @YamlProperty(name = "waitDurationInOpenState", type = "string", defaultValue = "60000", description = "Configures the wait duration which specifies how long the CircuitBreaker should stay open, before it switches to half open. The default is 60 seconds.", displayName = "Wait Duration In Open State"), @YamlProperty(name = "writableStackTraceEnabled", type = "boolean", defaultValue = "true", description = "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.", displayName = "Writable Stack Trace Enabled") } ) @@ -13935,6 +13938,11 @@ public final class ModelDeserializers extends YamlDeserializerSupport { target.setBulkheadEnabled(val); break; } + case "bulkheadFairCallHandlingEnabled": { + String val = asText(node); + target.setBulkheadFairCallHandlingEnabled(val); + break; + } case "bulkheadMaxConcurrentCalls": { String val = asText(node); target.setBulkheadMaxConcurrentCalls(val); @@ -13970,6 +13978,11 @@ public final class ModelDeserializers extends YamlDeserializerSupport { target.setIgnoreExceptions(val); break; } + case "maxWaitDurationInHalfOpenState": { + String val = asText(node); + target.setMaxWaitDurationInHalfOpenState(val); + break; + } case "micrometerEnabled": { String val = asText(node); target.setMicrometerEnabled(val); @@ -13995,6 +14008,11 @@ public final class ModelDeserializers extends YamlDeserializerSupport { target.setSlidingWindowSize(val); break; } + case "slidingWindowSynchronizationStrategy": { + String val = asText(node); + target.setSlidingWindowSynchronizationStrategy(val); + break; + } case "slidingWindowType": { String val = asText(node); target.setSlidingWindowType(val); diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl-canonical.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl-canonical.json index a35878691db2..8d2f166078e8 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl-canonical.json +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl-canonical.json @@ -2555,6 +2555,7 @@ "type" : "boolean", "title" : "Fallback Via Network", "description" : "Whether the fallback goes over the network. If so, the fallback is executed on a separate thread-pool to avoid exhausting the main thread-pool.", + "deprecated" : true, "default" : false }, "id" : { @@ -3619,6 +3620,12 @@ "description" : "Whether bulkhead is enabled or not on the circuit breaker.", "default" : false }, + "bulkheadFairCallHandlingEnabled" : { + "type" : "boolean", + "title" : "Bulkhead Fair Call Handling Enabled", + "description" : "Configures whether the bulkhead uses a fair calling strategy. When enabled (default), a fair strategy guarantees the order of incoming requests (FIFO). When disabled, no ordering is guaranteed and may improve throughput.", + "default" : true + }, "bulkheadMaxConcurrentCalls" : { "type" : "number", "title" : "Bulkhead Max Concurrent Calls", @@ -3626,10 +3633,10 @@ "default" : 25 }, "bulkheadMaxWaitDuration" : { - "type" : "number", + "type" : "string", "title" : "Bulkhead Max Wait Duration", - "description" : "Configures a maximum amount of time which the calling thread will wait to enter the bulkhead.", - "default" : 0 + "description" : "Configures a maximum amount of time which the calling thread will wait to enter the bulkhead. The default is 0 (no waiting).", + "default" : "0" }, "circuitBreaker" : { "type" : "string", @@ -3660,10 +3667,16 @@ "type" : "string" } }, + "maxWaitDurationInHalfOpenState" : { + "type" : "string", + "title" : "Max Wait Duration In Half Open State", + "description" : "Configures the maximum wait duration which controls how long the CircuitBreaker should stay in Half Open state, before it switches to open. Value 0 means circuit breaker will wait in half open state until all permitted calls have been completed.", + "default" : "0" + }, "micrometerEnabled" : { "type" : "boolean", "title" : "Micrometer Enabled", - "description" : "Whether to enable collecting statistics using Micrometer. This requires adding camel-resilience4j-micrometer JAR to the classpath.", + "description" : "Whether to enable collecting statistics using Micrometer for all circuit breaker instances. This is a global setting (configure via camel.resilience4j.micrometerEnabled=true) and requires adding camel-resilience4j-micrometer JAR to the classpath.", "default" : false }, "minimumNumberOfCalls" : { @@ -3692,6 +3705,13 @@ "description" : "Configures the size 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.", "default" : 100 }, + "slidingWindowSynchronizationStrategy" : { + "type" : "string", + "title" : "Sliding Window Synchronization Strategy", + "description" : "Configures the synchronization strategy for the sliding window. LOCK_FREE uses a CAS-based lock-free algorithm for better performance under high concurrency. SYNCHRONIZED uses blocking locks with lower memory allocation.", + "default" : "SYNCHRONIZED", + "enum" : [ "LOCK_FREE", "SYNCHRONIZED" ] + }, "slidingWindowType" : { "type" : "string", "title" : "Sliding Window Type", @@ -3700,10 +3720,10 @@ "enum" : [ "TIME_BASED", "COUNT_BASED" ] }, "slowCallDurationThreshold" : { - "type" : "number", + "type" : "string", "title" : "Slow Call Duration Threshold", - "description" : "Configures the duration threshold (seconds) above which calls are considered as slow and increase the slow calls percentage.", - "default" : 60 + "description" : "Configures the duration threshold above which calls are considered as slow and increase the slow calls percentage. The default is 60 seconds.", + "default" : "60000" }, "slowCallRateThreshold" : { "type" : "number", @@ -3724,10 +3744,10 @@ "default" : true }, "timeoutDuration" : { - "type" : "number", + "type" : "string", "title" : "Timeout Duration", "description" : "Configures the thread execution timeout. Default value is 1 second.", - "default" : 1000 + "default" : "1000" }, "timeoutEnabled" : { "type" : "boolean", @@ -3741,10 +3761,10 @@ "description" : "References to a custom thread pool to use when timeout is enabled (uses ForkJoinPool.commonPool() by default)." }, "waitDurationInOpenState" : { - "type" : "number", + "type" : "string", "title" : "Wait Duration In Open State", - "description" : "Configures the wait duration (in seconds) which specifies how long the CircuitBreaker should stay open, before it switches to half open.", - "default" : 60 + "description" : "Configures the wait duration which specifies how long the CircuitBreaker should stay open, before it switches to half open. The default is 60 seconds.", + "default" : "60000" }, "writableStackTraceEnabled" : { "type" : "boolean", diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json index fc9d04490428..61a26525fb4f 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json @@ -3928,6 +3928,7 @@ "type" : "boolean", "title" : "Fallback Via Network", "description" : "Whether the fallback goes over the network. If so, the fallback is executed on a separate thread-pool to avoid exhausting the main thread-pool.", + "deprecated" : true, "default" : false }, "id" : { @@ -5508,6 +5509,12 @@ "description" : "Whether bulkhead is enabled or not on the circuit breaker.", "default" : false }, + "bulkheadFairCallHandlingEnabled" : { + "type" : "boolean", + "title" : "Bulkhead Fair Call Handling Enabled", + "description" : "Configures whether the bulkhead uses a fair calling strategy. When enabled (default), a fair strategy guarantees the order of incoming requests (FIFO). When disabled, no ordering is guaranteed and may improve throughput.", + "default" : true + }, "bulkheadMaxConcurrentCalls" : { "type" : "number", "title" : "Bulkhead Max Concurrent Calls", @@ -5515,10 +5522,10 @@ "default" : 25 }, "bulkheadMaxWaitDuration" : { - "type" : "number", + "type" : "string", "title" : "Bulkhead Max Wait Duration", - "description" : "Configures a maximum amount of time which the calling thread will wait to enter the bulkhead.", - "default" : 0 + "description" : "Configures a maximum amount of time which the calling thread will wait to enter the bulkhead. The default is 0 (no waiting).", + "default" : "0" }, "circuitBreaker" : { "type" : "string", @@ -5549,10 +5556,16 @@ "type" : "string" } }, + "maxWaitDurationInHalfOpenState" : { + "type" : "string", + "title" : "Max Wait Duration In Half Open State", + "description" : "Configures the maximum wait duration which controls how long the CircuitBreaker should stay in Half Open state, before it switches to open. Value 0 means circuit breaker will wait in half open state until all permitted calls have been completed.", + "default" : "0" + }, "micrometerEnabled" : { "type" : "boolean", "title" : "Micrometer Enabled", - "description" : "Whether to enable collecting statistics using Micrometer. This requires adding camel-resilience4j-micrometer JAR to the classpath.", + "description" : "Whether to enable collecting statistics using Micrometer for all circuit breaker instances. This is a global setting (configure via camel.resilience4j.micrometerEnabled=true) and requires adding camel-resilience4j-micrometer JAR to the classpath.", "default" : false }, "minimumNumberOfCalls" : { @@ -5581,6 +5594,13 @@ "description" : "Configures the size 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.", "default" : 100 }, + "slidingWindowSynchronizationStrategy" : { + "type" : "string", + "title" : "Sliding Window Synchronization Strategy", + "description" : "Configures the synchronization strategy for the sliding window. LOCK_FREE uses a CAS-based lock-free algorithm for better performance under high concurrency. SYNCHRONIZED uses blocking locks with lower memory allocation.", + "default" : "SYNCHRONIZED", + "enum" : [ "LOCK_FREE", "SYNCHRONIZED" ] + }, "slidingWindowType" : { "type" : "string", "title" : "Sliding Window Type", @@ -5589,10 +5609,10 @@ "enum" : [ "TIME_BASED", "COUNT_BASED" ] }, "slowCallDurationThreshold" : { - "type" : "number", + "type" : "string", "title" : "Slow Call Duration Threshold", - "description" : "Configures the duration threshold (seconds) above which calls are considered as slow and increase the slow calls percentage.", - "default" : 60 + "description" : "Configures the duration threshold above which calls are considered as slow and increase the slow calls percentage. The default is 60 seconds.", + "default" : "60000" }, "slowCallRateThreshold" : { "type" : "number", @@ -5613,10 +5633,10 @@ "default" : true }, "timeoutDuration" : { - "type" : "number", + "type" : "string", "title" : "Timeout Duration", "description" : "Configures the thread execution timeout. Default value is 1 second.", - "default" : 1000 + "default" : "1000" }, "timeoutEnabled" : { "type" : "boolean", @@ -5630,10 +5650,10 @@ "description" : "References to a custom thread pool to use when timeout is enabled (uses ForkJoinPool.commonPool() by default)." }, "waitDurationInOpenState" : { - "type" : "number", + "type" : "string", "title" : "Wait Duration In Open State", - "description" : "Configures the wait duration (in seconds) which specifies how long the CircuitBreaker should stay open, before it switches to half open.", - "default" : 60 + "description" : "Configures the wait duration which specifies how long the CircuitBreaker should stay open, before it switches to half open. The default is 60 seconds.", + "default" : "60000" }, "writableStackTraceEnabled" : { "type" : "boolean", diff --git a/parent/pom.xml b/parent/pom.xml index 0512aa9d7966..37d792e37f07 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -512,7 +512,6 @@ <undertow-servlet-version>2.3.26.Final</undertow-servlet-version> <undertow-version>2.4.2.Final</undertow-version> <univocity-parsers-version>2.10.2</univocity-parsers-version> - <vavr-version>1.0.0</vavr-version> <velocity-tools-version>3.1</velocity-tools-version> <velocity-version>2.4.1</velocity-version> <vertx-version>4.5.28</vertx-version>
