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