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