001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.camel.model;
018
019import java.util.concurrent.ThreadPoolExecutor;
020
021import javax.xml.bind.annotation.XmlAccessType;
022import javax.xml.bind.annotation.XmlAccessorType;
023import javax.xml.bind.annotation.XmlRootElement;
024import javax.xml.bind.annotation.XmlTransient;
025
026import org.apache.camel.spi.Metadata;
027
028/**
029 * Hystrix Circuit Breaker EIP configuration
030 */
031@Metadata(label = "eip,routing,circuitbreaker")
032@XmlRootElement(name = "hystrixConfiguration")
033@XmlAccessorType(XmlAccessType.FIELD)
034public class HystrixConfigurationDefinition extends HystrixConfigurationCommon {
035
036    public static final String DEFAULT_GROUP_KEY = "CamelHystrix";
037
038    @XmlTransient
039    private CircuitBreakerDefinition parent;
040
041    public HystrixConfigurationDefinition() {
042    }
043
044    public HystrixConfigurationDefinition(CircuitBreakerDefinition parent) {
045        this.parent = parent;
046    }
047
048    // Fluent API
049    // -------------------------------------------------------------------------
050
051    /**
052     * Sets the group key to use. The default value is CamelHystrix.
053     */
054    public HystrixConfigurationDefinition groupKey(String groupKey) {
055        setGroupKey(groupKey);
056        return this;
057    }
058
059    /**
060     * Sets the thread pool key to use. Will by default use the same value as
061     * groupKey has been configured to use.
062     */
063    public HystrixConfigurationDefinition threadPoolKey(String threadPoolKey) {
064        setThreadPoolKey(threadPoolKey);
065        return this;
066    }
067
068    /**
069     * Whether to use a HystrixCircuitBreaker or not. If false no
070     * circuit-breaker logic will be used and all requests permitted.
071     * <p>
072     * This is similar in effect to circuitBreakerForceClosed() except that
073     * continues tracking metrics and knowing whether it should be open/closed,
074     * this property results in not even instantiating a circuit-breaker.
075     */
076    public HystrixConfigurationDefinition circuitBreakerEnabled(boolean circuitBreakerEnabled) {
077        setCircuitBreakerEnabled(Boolean.toString(circuitBreakerEnabled));
078        return this;
079    }
080
081    /**
082     * Error percentage threshold (as whole number such as 50) at which point
083     * the circuit breaker will trip open and reject requests.
084     * <p>
085     * It will stay tripped for the duration defined in
086     * circuitBreakerSleepWindowInMilliseconds;
087     * <p>
088     * The error percentage this is compared against comes from
089     * HystrixCommandMetrics.getHealthCounts().
090     */
091    public HystrixConfigurationDefinition circuitBreakerErrorThresholdPercentage(int circuitBreakerErrorThresholdPercentage) {
092        setCircuitBreakerErrorThresholdPercentage(Integer.toString(circuitBreakerErrorThresholdPercentage));
093        return this;
094    }
095
096    /**
097     * If true the HystrixCircuitBreaker.allowRequest() will always return true
098     * to allow requests regardless of the error percentage from
099     * HystrixCommandMetrics.getHealthCounts().
100     * <p>
101     * The circuitBreakerForceOpen() property takes precedence so if it set to
102     * true this property does nothing.
103     */
104    public HystrixConfigurationDefinition circuitBreakerForceClosed(boolean circuitBreakerForceClosed) {
105        setCircuitBreakerForceClosed(Boolean.toString(circuitBreakerForceClosed));
106        return this;
107    }
108
109    /**
110     * If true the HystrixCircuitBreaker.allowRequest() will always return
111     * false, causing the circuit to be open (tripped) and reject all requests.
112     * <p>
113     * This property takes precedence over circuitBreakerForceClosed();
114     */
115    public HystrixConfigurationDefinition circuitBreakerForceOpen(Boolean circuitBreakerForceOpen) {
116        setCircuitBreakerForceOpen(Boolean.toString(circuitBreakerForceOpen));
117        return this;
118    }
119
120    /**
121     * Minimum number of requests in the
122     * metricsRollingStatisticalWindowInMilliseconds() that must exist before
123     * the HystrixCircuitBreaker will trip.
124     * <p>
125     * If below this number the circuit will not trip regardless of error
126     * percentage.
127     */
128    public HystrixConfigurationDefinition circuitBreakerRequestVolumeThreshold(int circuitBreakerRequestVolumeThreshold) {
129        setCircuitBreakerRequestVolumeThreshold(Integer.toString(circuitBreakerRequestVolumeThreshold));
130        return this;
131    }
132
133    /**
134     * The time in milliseconds after a HystrixCircuitBreaker trips open that it
135     * should wait before trying requests again.
136     */
137    public HystrixConfigurationDefinition circuitBreakerSleepWindowInMilliseconds(int circuitBreakerSleepWindowInMilliseconds) {
138        setCircuitBreakerSleepWindowInMilliseconds(Integer.toString(circuitBreakerSleepWindowInMilliseconds));
139        return this;
140    }
141
142    /**
143     * Number of concurrent requests permitted to HystrixCommand.run(). Requests
144     * beyond the concurrent limit will be rejected.
145     * <p>
146     * Applicable only when executionIsolationStrategy is SEMAPHORE.
147     */
148    public HystrixConfigurationDefinition executionIsolationSemaphoreMaxConcurrentRequests(int executionIsolationSemaphoreMaxConcurrentRequests) {
149        setExecutionIsolationSemaphoreMaxConcurrentRequests(Integer.toString(executionIsolationSemaphoreMaxConcurrentRequests));
150        return this;
151    }
152
153    /**
154     * What isolation strategy HystrixCommand.run() will be executed with.
155     * <p>
156     * If THREAD then it will be executed on a separate thread and concurrent
157     * requests limited by the number of threads in the thread-pool.
158     * <p>
159     * If SEMAPHORE then it will be executed on the calling thread and
160     * concurrent requests limited by the semaphore count.
161     */
162    public HystrixConfigurationDefinition executionIsolationStrategy(String executionIsolationStrategy) {
163        setExecutionIsolationStrategy(executionIsolationStrategy);
164        return this;
165    }
166
167    /**
168     * Whether the execution thread should attempt an interrupt (using Future
169     * cancel) when a thread times out.
170     * <p>
171     * Applicable only when executionIsolationStrategy() is set to THREAD.
172     */
173    public HystrixConfigurationDefinition executionIsolationThreadInterruptOnTimeout(boolean executionIsolationThreadInterruptOnTimeout) {
174        setExecutionIsolationThreadInterruptOnTimeout(Boolean.toString(executionIsolationThreadInterruptOnTimeout));
175        return this;
176    }
177
178    /**
179     * Time in milliseconds at which point the command will timeout and halt
180     * execution.
181     * <p>
182     * If executionIsolationThreadInterruptOnTimeout is true and the command is
183     * thread-isolated, the executing thread will be interrupted. If the command
184     * is semaphore-isolated and a HystrixObservableCommand, that command will
185     * get unsubscribed.
186     */
187    public HystrixConfigurationDefinition executionTimeoutInMilliseconds(int executionTimeoutInMilliseconds) {
188        setExecutionTimeoutInMilliseconds(Integer.toString(executionTimeoutInMilliseconds));
189        return this;
190    }
191
192    /**
193     * Whether the timeout mechanism is enabled for this command
194     */
195    public HystrixConfigurationDefinition executionTimeoutEnabled(boolean executionTimeoutEnabled) {
196        setExecutionTimeoutEnabled(Boolean.toString(executionTimeoutEnabled));
197        return this;
198    }
199
200    /**
201     * Number of concurrent requests permitted to HystrixCommand.getFallback().
202     * Requests beyond the concurrent limit will fail-fast and not attempt
203     * retrieving a fallback.
204     */
205    public HystrixConfigurationDefinition fallbackIsolationSemaphoreMaxConcurrentRequests(int fallbackIsolationSemaphoreMaxConcurrentRequests) {
206        setFallbackIsolationSemaphoreMaxConcurrentRequests(Integer.toString(fallbackIsolationSemaphoreMaxConcurrentRequests));
207        return this;
208    }
209
210    /**
211     * Whether HystrixCommand.getFallback() should be attempted when failure
212     * occurs.
213     */
214    public HystrixConfigurationDefinition fallbackEnabled(boolean fallbackEnabled) {
215        setFallbackEnabled(Boolean.toString(fallbackEnabled));
216        return this;
217    }
218
219    /**
220     * Time in milliseconds to wait between allowing health snapshots to be
221     * taken that calculate success and error percentages and affect
222     * HystrixCircuitBreaker.isOpen() status.
223     * <p>
224     * On high-volume circuits the continual calculation of error percentage can
225     * become CPU intensive thus this controls how often it is calculated.
226     */
227    public HystrixConfigurationDefinition metricsHealthSnapshotIntervalInMilliseconds(int metricsHealthSnapshotIntervalInMilliseconds) {
228        setMetricsHealthSnapshotIntervalInMilliseconds(Integer.toString(metricsHealthSnapshotIntervalInMilliseconds));
229        return this;
230    }
231
232    /**
233     * Maximum number of values stored in each bucket of the rolling percentile.
234     * This is passed into HystrixRollingPercentile inside
235     * HystrixCommandMetrics.
236     */
237    public HystrixConfigurationDefinition metricsRollingPercentileBucketSize(int metricsRollingPercentileBucketSize) {
238        setMetricsRollingPercentileBucketSize(Integer.toString(metricsRollingPercentileBucketSize));
239        return this;
240    }
241
242    /**
243     * Whether percentile metrics should be captured using
244     * HystrixRollingPercentile inside HystrixCommandMetrics.
245     */
246    public HystrixConfigurationDefinition metricsRollingPercentileEnabled(boolean metricsRollingPercentileEnabled) {
247        setMetricsRollingPercentileEnabled(Boolean.toString(metricsRollingPercentileEnabled));
248        return this;
249    }
250
251    /**
252     * Duration of percentile rolling window in milliseconds. This is passed
253     * into HystrixRollingPercentile inside HystrixCommandMetrics.
254     */
255    public HystrixConfigurationDefinition metricsRollingPercentileWindowInMilliseconds(int metricsRollingPercentileWindowInMilliseconds) {
256        setMetricsRollingPercentileWindowInMilliseconds(Integer.toString(metricsRollingPercentileWindowInMilliseconds));
257        return this;
258    }
259
260    /**
261     * Number of buckets the rolling percentile window is broken into. This is
262     * passed into HystrixRollingPercentile inside HystrixCommandMetrics.
263     */
264    public HystrixConfigurationDefinition metricsRollingPercentileWindowBuckets(int metricsRollingPercentileWindowBuckets) {
265        setMetricsRollingPercentileWindowBuckets(Integer.toString(metricsRollingPercentileWindowBuckets));
266        return this;
267    }
268
269    /**
270     * This property sets the duration of the statistical rolling window, in
271     * milliseconds. This is how long metrics are kept for the thread pool. The
272     * window is divided into buckets and “rolls” by those increments.
273     */
274    public HystrixConfigurationDefinition metricsRollingStatisticalWindowInMilliseconds(int metricsRollingStatisticalWindowInMilliseconds) {
275        setMetricsRollingStatisticalWindowInMilliseconds(Integer.toString(metricsRollingStatisticalWindowInMilliseconds));
276        return this;
277    }
278
279    /**
280     * Number of buckets the rolling statistical window is broken into. This is
281     * passed into HystrixRollingNumber inside HystrixCommandMetrics.
282     */
283    public HystrixConfigurationDefinition metricsRollingStatisticalWindowBuckets(int metricsRollingStatisticalWindowBuckets) {
284        setMetricsRollingStatisticalWindowBuckets(Integer.toString(metricsRollingStatisticalWindowBuckets));
285        return this;
286    }
287
288    /**
289     * Whether HystrixCommand execution and events should be logged to
290     * HystrixRequestLog.
291     */
292    public HystrixConfigurationDefinition requestLogEnabled(boolean requestLogEnabled) {
293        setRequestLogEnabled(Boolean.toString(requestLogEnabled));
294        return this;
295    }
296
297    /**
298     * Core thread-pool size.
299     */
300    public HystrixConfigurationDefinition corePoolSize(int corePoolSize) {
301        setCorePoolSize(Integer.toString(corePoolSize));
302        return this;
303    }
304
305    /**
306     * Keep-alive time in minutes.
307     */
308    public HystrixConfigurationDefinition keepAliveTime(int keepAliveTime) {
309        setKeepAliveTime(Integer.toString(keepAliveTime));
310        return this;
311    }
312
313    /**
314     * Max queue size. This should only affect the instantiation of the
315     * thread-pool - it is not eligible to change a queue size on the fly.
316     */
317    public HystrixConfigurationDefinition maxQueueSize(int maxQueueSize) {
318        setMaxQueueSize(Integer.toString(maxQueueSize));
319        return this;
320    }
321
322    /**
323     * Maximum thread-pool size that gets passed to
324     * {@link ThreadPoolExecutor#setMaximumPoolSize(int)}. This is the maximum
325     * amount of concurrency that can be supported without starting to reject
326     * HystrixCommands. Please note that this setting only takes effect if you
327     * also set allowMaximumSizeToDivergeFromCoreSize
328     */
329    public HystrixConfigurationDefinition maximumSize(int maximumSize) {
330        setMaximumSize(Integer.toString(maximumSize));
331        return this;
332    }
333
334    /**
335     * Queue size rejection threshold is an artificial max size at which
336     * rejections will occur even if maxQueueSize has not been reached. This is
337     * done because the maxQueueSize of a blocking queue can not be dynamically
338     * changed and we want to support dynamically changing the queue size that
339     * affects rejections.
340     * <p>
341     * This is used by HystrixCommand when queuing a thread for execution.
342     */
343    public HystrixConfigurationDefinition queueSizeRejectionThreshold(int queueSizeRejectionThreshold) {
344        setQueueSizeRejectionThreshold(Integer.toString(queueSizeRejectionThreshold));
345        return this;
346    }
347
348    /**
349     * Duration of statistical rolling window in milliseconds. This is passed
350     * into HystrixRollingNumber inside each HystrixThreadPoolMetrics instance.
351     */
352    public HystrixConfigurationDefinition threadPoolRollingNumberStatisticalWindowInMilliseconds(int threadPoolRollingNumberStatisticalWindowInMilliseconds) {
353        setThreadPoolRollingNumberStatisticalWindowInMilliseconds(Integer.toString(threadPoolRollingNumberStatisticalWindowInMilliseconds));
354        return this;
355    }
356
357    /**
358     * Number of buckets the rolling statistical window is broken into. This is
359     * passed into HystrixRollingNumber inside each HystrixThreadPoolMetrics
360     * instance.
361     */
362    public HystrixConfigurationDefinition threadPoolRollingNumberStatisticalWindowBuckets(int threadPoolRollingNumberStatisticalWindowBuckets) {
363        setThreadPoolRollingNumberStatisticalWindowBuckets(Integer.toString(threadPoolRollingNumberStatisticalWindowBuckets));
364        return this;
365    }
366
367    /**
368     * Allows the configuration for maximumSize to take effect. That value can
369     * then be equal to, or higher, than coreSize
370     */
371    public HystrixConfigurationDefinition allowMaximumSizeToDivergeFromCoreSize(boolean allowMaximumSizeToDivergeFromCoreSize) {
372        setAllowMaximumSizeToDivergeFromCoreSize(Boolean.toString(allowMaximumSizeToDivergeFromCoreSize));
373        return this;
374    }
375
376    /**
377     * End of configuration.
378     */
379    public CircuitBreakerDefinition end() {
380        return parent;
381    }
382
383}