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.BlockingQueue;
020import java.util.concurrent.Future;
021import java.util.concurrent.ThreadPoolExecutor;
022import java.util.concurrent.TimeUnit;
023
024import javax.xml.bind.annotation.XmlAccessType;
025import javax.xml.bind.annotation.XmlAccessorType;
026import javax.xml.bind.annotation.XmlAttribute;
027
028import org.apache.camel.spi.Metadata;
029
030@XmlAccessorType(XmlAccessType.FIELD)
031public class HystrixConfigurationCommon extends IdentifiedType {
032
033    @XmlAttribute
034    @Metadata(defaultValue = "CamelHystrix")
035    private String groupKey;
036    @XmlAttribute
037    @Metadata(defaultValue = "CamelHystrix")
038    private String threadPoolKey;
039    @XmlAttribute
040    @Metadata(label = "command", defaultValue = "true")
041    private Boolean circuitBreakerEnabled;
042    @XmlAttribute
043    @Metadata(label = "command", defaultValue = "50")
044    private Integer circuitBreakerErrorThresholdPercentage;
045    @XmlAttribute
046    @Metadata(label = "command", defaultValue = "false")
047    private Boolean circuitBreakerForceClosed;
048    @XmlAttribute
049    @Metadata(label = "command", defaultValue = "false")
050    private Boolean circuitBreakerForceOpen;
051    @XmlAttribute
052    @Metadata(label = "command", defaultValue = "20")
053    private Integer circuitBreakerRequestVolumeThreshold;
054    @XmlAttribute
055    @Metadata(label = "command", defaultValue = "5000")
056    private Integer circuitBreakerSleepWindowInMilliseconds;
057    @XmlAttribute
058    @Metadata(label = "command", defaultValue = "20")
059    private Integer executionIsolationSemaphoreMaxConcurrentRequests;
060    @XmlAttribute
061    @Metadata(label = "command", defaultValue = "THREAD", enums = "THREAD,SEMAPHORE")
062    private String executionIsolationStrategy;
063    @XmlAttribute
064    @Metadata(label = "command", defaultValue = "true")
065    private Boolean executionIsolationThreadInterruptOnTimeout;
066    @XmlAttribute
067    @Metadata(label = "command", defaultValue = "1000")
068    private Integer executionTimeoutInMilliseconds;
069    @XmlAttribute
070    @Metadata(label = "command", defaultValue = "true")
071    private Boolean executionTimeoutEnabled;
072    @XmlAttribute
073    @Metadata(label = "command", defaultValue = "10")
074    private Integer fallbackIsolationSemaphoreMaxConcurrentRequests;
075    @XmlAttribute
076    @Metadata(label = "command", defaultValue = "true")
077    private Boolean fallbackEnabled;
078    @XmlAttribute
079    @Metadata(label = "command", defaultValue = "500")
080    private Integer metricsHealthSnapshotIntervalInMilliseconds;
081    @XmlAttribute
082    @Metadata(label = "command", defaultValue = "10")
083    private Integer metricsRollingPercentileBucketSize;
084    @XmlAttribute
085    @Metadata(label = "command", defaultValue = "true")
086    private Boolean metricsRollingPercentileEnabled;
087    @XmlAttribute
088    @Metadata(label = "command", defaultValue = "10000")
089    private Integer metricsRollingPercentileWindowInMilliseconds;
090    @XmlAttribute
091    @Metadata(label = "command", defaultValue = "6")
092    private Integer metricsRollingPercentileWindowBuckets;
093    @XmlAttribute
094    @Metadata(label = "command", defaultValue = "10000")
095    private Integer metricsRollingStatisticalWindowInMilliseconds;
096    @XmlAttribute
097    @Metadata(label = "command", defaultValue = "10")
098    private Integer metricsRollingStatisticalWindowBuckets;
099    @XmlAttribute
100    @Metadata(label = "command", defaultValue = "true")
101    private Boolean requestLogEnabled;
102
103    // thread-pool
104
105    @XmlAttribute
106    @Metadata(label = "threadpool", defaultValue = "10")
107    private Integer corePoolSize;
108    @XmlAttribute
109    @Metadata(label = "threadpool", defaultValue = "10")
110    private Integer maximumSize;
111    @XmlAttribute
112    @Metadata(label = "threadpool", defaultValue = "1")
113    private Integer keepAliveTime;
114    @XmlAttribute
115    @Metadata(label = "threadpool", defaultValue = "-1")
116    private Integer maxQueueSize;
117    @XmlAttribute
118    @Metadata(label = "threadpool", defaultValue = "5")
119    private Integer queueSizeRejectionThreshold;
120    @XmlAttribute
121    @Metadata(label = "threadpool", defaultValue = "10000")
122    private Integer threadPoolRollingNumberStatisticalWindowInMilliseconds;
123    @XmlAttribute
124    @Metadata(label = "threadpool", defaultValue = "10")
125    private Integer threadPoolRollingNumberStatisticalWindowBuckets;
126    @XmlAttribute
127    @Metadata(label = "threadpool", defaultValue = "false")
128    private Boolean allowMaximumSizeToDivergeFromCoreSize;
129
130    // Getter/Setter
131    // -------------------------------------------------------------------------
132
133    public String getGroupKey() {
134        return groupKey;
135    }
136
137    /**
138     * Sets the group key to use. The default value is CamelHystrix.
139     */
140    public void setGroupKey(String groupKey) {
141        this.groupKey = groupKey;
142    }
143
144    public String getThreadPoolKey() {
145        return threadPoolKey;
146    }
147
148    /**
149     * Sets the thread pool key to use. Will by default use the same value as
150     * groupKey has been configured to use.
151     */
152    public void setThreadPoolKey(String threadPoolKey) {
153        this.threadPoolKey = threadPoolKey;
154    }
155
156    public Boolean getCircuitBreakerEnabled() {
157        return circuitBreakerEnabled;
158    }
159
160    /**
161     * Whether to use a HystrixCircuitBreaker or not. If false no
162     * circuit-breaker logic will be used and all requests permitted.
163     * <p>
164     * This is similar in effect to circuitBreakerForceClosed() except that
165     * continues tracking metrics and knowing whether it should be open/closed,
166     * this property results in not even instantiating a circuit-breaker.
167     */
168    public void setCircuitBreakerEnabled(Boolean circuitBreakerEnabled) {
169        this.circuitBreakerEnabled = circuitBreakerEnabled;
170    }
171
172    public Integer getCircuitBreakerErrorThresholdPercentage() {
173        return circuitBreakerErrorThresholdPercentage;
174    }
175
176    /**
177     * Error percentage threshold (as whole number such as 50) at which point
178     * the circuit breaker will trip open and reject requests.
179     * <p>
180     * It will stay tripped for the duration defined in
181     * circuitBreakerSleepWindowInMilliseconds;
182     * <p>
183     * The error percentage this is compared against comes from
184     * HystrixCommandMetrics.getHealthCounts().
185     */
186    public void setCircuitBreakerErrorThresholdPercentage(Integer circuitBreakerErrorThresholdPercentage) {
187        this.circuitBreakerErrorThresholdPercentage = circuitBreakerErrorThresholdPercentage;
188    }
189
190    public Boolean getCircuitBreakerForceClosed() {
191        return circuitBreakerForceClosed;
192    }
193
194    /**
195     * If true the HystrixCircuitBreaker#allowRequest() will always return true
196     * to allow requests regardless of the error percentage from
197     * HystrixCommandMetrics.getHealthCounts().
198     * <p>
199     * The circuitBreakerForceOpen() property takes precedence so if it set to
200     * true this property does nothing.
201     */
202    public void setCircuitBreakerForceClosed(Boolean circuitBreakerForceClosed) {
203        this.circuitBreakerForceClosed = circuitBreakerForceClosed;
204    }
205
206    public Boolean getCircuitBreakerForceOpen() {
207        return circuitBreakerForceOpen;
208    }
209
210    /**
211     * If true the HystrixCircuitBreaker.allowRequest() will always return
212     * false, causing the circuit to be open (tripped) and reject all requests.
213     * <p>
214     * This property takes precedence over circuitBreakerForceClosed();
215     */
216    public void setCircuitBreakerForceOpen(Boolean circuitBreakerForceOpen) {
217        this.circuitBreakerForceOpen = circuitBreakerForceOpen;
218    }
219
220    public Integer getCircuitBreakerRequestVolumeThreshold() {
221        return circuitBreakerRequestVolumeThreshold;
222    }
223
224    /**
225     * Minimum number of requests in the
226     * metricsRollingStatisticalWindowInMilliseconds() that must exist before
227     * the HystrixCircuitBreaker will trip.
228     * <p>
229     * If below this number the circuit will not trip regardless of error
230     * percentage.
231     */
232    public void setCircuitBreakerRequestVolumeThreshold(Integer circuitBreakerRequestVolumeThreshold) {
233        this.circuitBreakerRequestVolumeThreshold = circuitBreakerRequestVolumeThreshold;
234    }
235
236    public Integer getCircuitBreakerSleepWindowInMilliseconds() {
237        return circuitBreakerSleepWindowInMilliseconds;
238    }
239
240    /**
241     * The time in milliseconds after a HystrixCircuitBreaker trips open that it
242     * should wait before trying requests again.
243     */
244    public void setCircuitBreakerSleepWindowInMilliseconds(Integer circuitBreakerSleepWindowInMilliseconds) {
245        this.circuitBreakerSleepWindowInMilliseconds = circuitBreakerSleepWindowInMilliseconds;
246    }
247
248    public Integer getExecutionIsolationSemaphoreMaxConcurrentRequests() {
249        return executionIsolationSemaphoreMaxConcurrentRequests;
250    }
251
252    /**
253     * Number of concurrent requests permitted to HystrixCommand.run(). Requests
254     * beyond the concurrent limit will be rejected.
255     * <p>
256     * Applicable only when executionIsolationStrategy == SEMAPHORE.
257     */
258    public void setExecutionIsolationSemaphoreMaxConcurrentRequests(Integer executionIsolationSemaphoreMaxConcurrentRequests) {
259        this.executionIsolationSemaphoreMaxConcurrentRequests = executionIsolationSemaphoreMaxConcurrentRequests;
260    }
261
262    public String getExecutionIsolationStrategy() {
263        return executionIsolationStrategy;
264    }
265
266    /**
267     * What isolation strategy HystrixCommand.run() will be executed with.
268     * <p>
269     * If THREAD then it will be executed on a separate thread and concurrent
270     * requests limited by the number of threads in the thread-pool.
271     * <p>
272     * If SEMAPHORE then it will be executed on the calling thread and
273     * concurrent requests limited by the semaphore count.
274     */
275    public void setExecutionIsolationStrategy(String executionIsolationStrategy) {
276        this.executionIsolationStrategy = executionIsolationStrategy;
277    }
278
279    public Boolean getExecutionIsolationThreadInterruptOnTimeout() {
280        return executionIsolationThreadInterruptOnTimeout;
281    }
282
283    /**
284     * Whether the execution thread should attempt an interrupt (using
285     * {@link Future#cancel}) when a thread times out.
286     * <p>
287     * Applicable only when executionIsolationStrategy() == THREAD.
288     */
289    public void setExecutionIsolationThreadInterruptOnTimeout(Boolean executionIsolationThreadInterruptOnTimeout) {
290        this.executionIsolationThreadInterruptOnTimeout = executionIsolationThreadInterruptOnTimeout;
291    }
292
293    public Integer getExecutionTimeoutInMilliseconds() {
294        return executionTimeoutInMilliseconds;
295    }
296
297    /**
298     * Time in milliseconds at which point the command will timeout and halt
299     * execution.
300     * <p>
301     * If {@link #executionIsolationThreadInterruptOnTimeout} == true and the
302     * command is thread-isolated, the executing thread will be interrupted. If
303     * the command is semaphore-isolated and a HystrixObservableCommand, that
304     * command will get unsubscribed.
305     */
306    public void setExecutionTimeoutInMilliseconds(Integer executionTimeoutInMilliseconds) {
307        this.executionTimeoutInMilliseconds = executionTimeoutInMilliseconds;
308    }
309
310    public Boolean getExecutionTimeoutEnabled() {
311        return executionTimeoutEnabled;
312    }
313
314    /**
315     * Whether the timeout mechanism is enabled for this command
316     */
317    public void setExecutionTimeoutEnabled(Boolean executionTimeoutEnabled) {
318        this.executionTimeoutEnabled = executionTimeoutEnabled;
319    }
320
321    public Integer getFallbackIsolationSemaphoreMaxConcurrentRequests() {
322        return fallbackIsolationSemaphoreMaxConcurrentRequests;
323    }
324
325    /**
326     * Number of concurrent requests permitted to HystrixCommand.getFallback().
327     * Requests beyond the concurrent limit will fail-fast and not attempt
328     * retrieving a fallback.
329     */
330    public void setFallbackIsolationSemaphoreMaxConcurrentRequests(Integer fallbackIsolationSemaphoreMaxConcurrentRequests) {
331        this.fallbackIsolationSemaphoreMaxConcurrentRequests = fallbackIsolationSemaphoreMaxConcurrentRequests;
332    }
333
334    public Boolean getFallbackEnabled() {
335        return fallbackEnabled;
336    }
337
338    /**
339     * Whether HystrixCommand.getFallback() should be attempted when failure
340     * occurs.
341     */
342    public void setFallbackEnabled(Boolean fallbackEnabled) {
343        this.fallbackEnabled = fallbackEnabled;
344    }
345
346    public Integer getMetricsHealthSnapshotIntervalInMilliseconds() {
347        return metricsHealthSnapshotIntervalInMilliseconds;
348    }
349
350    /**
351     * Time in milliseconds to wait between allowing health snapshots to be
352     * taken that calculate success and error percentages and affect
353     * HystrixCircuitBreaker.isOpen() status.
354     * <p>
355     * On high-volume circuits the continual calculation of error percentage can
356     * become CPU intensive thus this controls how often it is calculated.
357     */
358    public void setMetricsHealthSnapshotIntervalInMilliseconds(Integer metricsHealthSnapshotIntervalInMilliseconds) {
359        this.metricsHealthSnapshotIntervalInMilliseconds = metricsHealthSnapshotIntervalInMilliseconds;
360    }
361
362    public Integer getMetricsRollingPercentileBucketSize() {
363        return metricsRollingPercentileBucketSize;
364    }
365
366    /**
367     * Maximum number of values stored in each bucket of the rolling percentile.
368     * This is passed into HystrixRollingPercentile inside
369     * HystrixCommandMetrics.
370     */
371    public void setMetricsRollingPercentileBucketSize(Integer metricsRollingPercentileBucketSize) {
372        this.metricsRollingPercentileBucketSize = metricsRollingPercentileBucketSize;
373    }
374
375    public Boolean getMetricsRollingPercentileEnabled() {
376        return metricsRollingPercentileEnabled;
377    }
378
379    /**
380     * Whether percentile metrics should be captured using
381     * HystrixRollingPercentile inside HystrixCommandMetrics.
382     */
383    public void setMetricsRollingPercentileEnabled(Boolean metricsRollingPercentileEnabled) {
384        this.metricsRollingPercentileEnabled = metricsRollingPercentileEnabled;
385    }
386
387    public Integer getMetricsRollingPercentileWindowInMilliseconds() {
388        return metricsRollingPercentileWindowInMilliseconds;
389    }
390
391    /**
392     * Duration of percentile rolling window in milliseconds. This is passed
393     * into HystrixRollingPercentile inside HystrixCommandMetrics.
394     */
395    public void setMetricsRollingPercentileWindowInMilliseconds(Integer metricsRollingPercentileWindowInMilliseconds) {
396        this.metricsRollingPercentileWindowInMilliseconds = metricsRollingPercentileWindowInMilliseconds;
397    }
398
399    public Integer getMetricsRollingPercentileWindowBuckets() {
400        return metricsRollingPercentileWindowBuckets;
401    }
402
403    /**
404     * Number of buckets the rolling percentile window is broken into. This is
405     * passed into HystrixRollingPercentile inside HystrixCommandMetrics.
406     */
407    public void setMetricsRollingPercentileWindowBuckets(Integer metricsRollingPercentileWindowBuckets) {
408        this.metricsRollingPercentileWindowBuckets = metricsRollingPercentileWindowBuckets;
409    }
410
411    public Integer getMetricsRollingStatisticalWindowInMilliseconds() {
412        return metricsRollingStatisticalWindowInMilliseconds;
413    }
414
415    /**
416     * This property sets the duration of the statistical rolling window, in
417     * milliseconds. This is how long metrics are kept for the thread pool. The
418     * window is divided into buckets and “rolls” by those increments.
419     */
420    public void setMetricsRollingStatisticalWindowInMilliseconds(Integer metricsRollingStatisticalWindowInMilliseconds) {
421        this.metricsRollingStatisticalWindowInMilliseconds = metricsRollingStatisticalWindowInMilliseconds;
422    }
423
424    public Integer getMetricsRollingStatisticalWindowBuckets() {
425        return metricsRollingStatisticalWindowBuckets;
426    }
427
428    /**
429     * Number of buckets the rolling statistical window is broken into. This is
430     * passed into HystrixRollingNumber inside HystrixCommandMetrics.
431     */
432    public void setMetricsRollingStatisticalWindowBuckets(Integer metricsRollingStatisticalWindowBuckets) {
433        this.metricsRollingStatisticalWindowBuckets = metricsRollingStatisticalWindowBuckets;
434    }
435
436    public Boolean getRequestLogEnabled() {
437        return requestLogEnabled;
438    }
439
440    /**
441     * Whether HystrixCommand execution and events should be logged to
442     * HystrixRequestLog.
443     */
444    public void setRequestLogEnabled(Boolean requestLogEnabled) {
445        this.requestLogEnabled = requestLogEnabled;
446    }
447
448    public Integer getCorePoolSize() {
449        return corePoolSize;
450    }
451
452    /**
453     * Core thread-pool size that gets passed to
454     * {@link java.util.concurrent.ThreadPoolExecutor#setCorePoolSize(int)}
455     */
456    public void setCorePoolSize(Integer corePoolSize) {
457        this.corePoolSize = corePoolSize;
458    }
459
460    public Integer getMaximumSize() {
461        return maximumSize;
462    }
463
464    /**
465     * Maximum thread-pool size that gets passed to
466     * {@link ThreadPoolExecutor#setMaximumPoolSize(int)}. This is the maximum
467     * amount of concurrency that can be supported without starting to reject
468     * HystrixCommands. Please note that this setting only takes effect if you
469     * also set allowMaximumSizeToDivergeFromCoreSize
470     */
471    public void setMaximumSize(Integer maximumSize) {
472        this.maximumSize = maximumSize;
473    }
474
475    public Integer getKeepAliveTime() {
476        return keepAliveTime;
477    }
478
479    /**
480     * Keep-alive time in minutes that gets passed to
481     * {@link ThreadPoolExecutor#setKeepAliveTime(long, TimeUnit)}
482     */
483    public void setKeepAliveTime(Integer keepAliveTime) {
484        this.keepAliveTime = keepAliveTime;
485    }
486
487    public Integer getMaxQueueSize() {
488        return maxQueueSize;
489    }
490
491    /**
492     * Max queue size that gets passed to {@link BlockingQueue} in
493     * HystrixConcurrencyStrategy.getBlockingQueue(int) This should only affect
494     * the instantiation of a threadpool - it is not eliglible to change a queue
495     * size on the fly. For that, use queueSizeRejectionThreshold().
496     */
497    public void setMaxQueueSize(Integer maxQueueSize) {
498        this.maxQueueSize = maxQueueSize;
499    }
500
501    public Integer getQueueSizeRejectionThreshold() {
502        return queueSizeRejectionThreshold;
503    }
504
505    /**
506     * Queue size rejection threshold is an artificial "max" size at which
507     * rejections will occur even if {@link #maxQueueSize} has not been reached.
508     * This is done because the {@link #maxQueueSize} of a {@link BlockingQueue}
509     * can not be dynamically changed and we want to support dynamically
510     * changing the queue size that affects rejections.
511     * <p>
512     * This is used by HystrixCommand when queuing a thread for execution.
513     */
514    public void setQueueSizeRejectionThreshold(Integer queueSizeRejectionThreshold) {
515        this.queueSizeRejectionThreshold = queueSizeRejectionThreshold;
516    }
517
518    public Integer getThreadPoolRollingNumberStatisticalWindowInMilliseconds() {
519        return threadPoolRollingNumberStatisticalWindowInMilliseconds;
520    }
521
522    /**
523     * Duration of statistical rolling window in milliseconds. This is passed
524     * into HystrixRollingNumber inside each HystrixThreadPoolMetrics instance.
525     */
526    public void setThreadPoolRollingNumberStatisticalWindowInMilliseconds(Integer threadPoolRollingNumberStatisticalWindowInMilliseconds) {
527        this.threadPoolRollingNumberStatisticalWindowInMilliseconds = threadPoolRollingNumberStatisticalWindowInMilliseconds;
528    }
529
530    public Integer getThreadPoolRollingNumberStatisticalWindowBuckets() {
531        return threadPoolRollingNumberStatisticalWindowBuckets;
532    }
533
534    /**
535     * Number of buckets the rolling statistical window is broken into. This is
536     * passed into HystrixRollingNumber inside each HystrixThreadPoolMetrics
537     * instance.
538     */
539    public void setThreadPoolRollingNumberStatisticalWindowBuckets(Integer threadPoolRollingNumberStatisticalWindowBuckets) {
540        this.threadPoolRollingNumberStatisticalWindowBuckets = threadPoolRollingNumberStatisticalWindowBuckets;
541    }
542
543    public Boolean getAllowMaximumSizeToDivergeFromCoreSize() {
544        return allowMaximumSizeToDivergeFromCoreSize;
545    }
546
547    /**
548     * Allows the configuration for maximumSize to take effect. That value can
549     * then be equal to, or higher, than coreSize
550     */
551    public void setAllowMaximumSizeToDivergeFromCoreSize(Boolean allowMaximumSizeToDivergeFromCoreSize) {
552        this.allowMaximumSizeToDivergeFromCoreSize = allowMaximumSizeToDivergeFromCoreSize;
553    }
554}