/*
* Copyright 2012-2015, the original author or authors.
*
* Licensed 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 com.flipkart.phantom.task.impl;
import java.util.HashMap;
import java.util.Map;
import com.flipkart.phantom.task.spi.Decoder;
import com.flipkart.phantom.task.spi.TaskContext;
import com.flipkart.phantom.task.spi.TaskRequestWrapper;
import com.flipkart.phantom.task.spi.TaskResult;
import com.netflix.hystrix.HystrixCommandProperties.ExecutionIsolationStrategy;
/**
* An extension of {@link TaskHandler}. Provides methods to additionally set/customize Hytrix Command properties {https://github.com/Netflix/Hystrix}.
* Uses {@link TaskHandler#getName()} as the HystrixCommand name for display on the dashboard.
*
* @author devashishshankar
* @version 1.0, 19 March, 2013
*/
public abstract class HystrixTaskHandler extends TaskHandler {
/** The default executor timeout in millis*/
public static final int DEFAULT_EXECUTOR_TIMEOUT = 1000;
/**
* These can be used to limit the maximum concurrent requests for a Proxy or a command
* The key will be the Proxy name optionally overridden by a command name
* The value will be the concurrent pool size.
* If isolation strategy is @ExecutionIsolationStrategy#Thread then this param is used as a thread-concurrency pool
* as otherwise if the isolation strategy is @ExecutionIsolationStrategy#Semaphore , then this param is used for semaphore-concurrency pool
* (If no. of concurrent requests for this concurrent pool exceed this value, they will be rejected by Hystrix)
* Note: the incoming request should have a "pool" param for it to be routed to the correct Thread Pool. If it doesn't,
* the default command level thread pool will be used. (It's core size is 10 by default)
*/
private Map<String,Integer> concurrentPoolSizeParams = new HashMap<String,Integer>();
/**
* Similar behaviour as {@link #concurrentPoolSizeParams} but defines the core pool size instead of maximum.
* See {@link java.util.concurrent.ThreadPoolExecutor#corePoolSize}.
*
* @see <a href="https://github.com/Netflix/Hystrix/issues/1242">Hystrix Issue</a>
*/
private Map<String, Integer> coreConcurrentPoolSizeParams = new HashMap<>();
/**
* These can be used to limit the maximum concurrent requests at a command level.
* The key will be the HystrixCommand name. It should be a valid commandName. (Else an exception is thrown)
* The value will be the thread pool size.
* Note: commandPoolSizeParams override concurrentPoolSizeParams. commandPoolSizeParams will only be applied if there is no
* "pool" param in incoming requests.
* (If no. of concurrent requests for this thread pool exceed this value, they will be rejected by Hystrix)
* If this property is not set for a command, default Hystrix Value for thread pool size(10) will be used.
*/
private Map<String,Integer> commandPoolSizeParams = new HashMap<String,Integer>();
/**
* Similar behaviour as {@link #commandPoolSizeParams} but defines the core pool size instead of maximum.
* See {@link java.util.concurrent.ThreadPoolExecutor#corePoolSize}.
*
* @see <a href="https://github.com/Netflix/Hystrix/issues/1242">Hystrix Issue</a>
*/
private Map<String, Integer> coreCommandPoolSizeParams = new HashMap<>();
/**
/**
* Map of command names and their respective executor timeouts in milliseconds
*/
protected Map<String,Integer> executorTimeouts = new HashMap<String, Integer>();
/**
* This method will be executed if execute() fails.
* @param command the command used
* @param params thrift parameters
* @param data extra data if any
* @return response
*/
public abstract <T, S> TaskResult<T> getFallBack(TaskContext taskContext, String command, Map<String, Object> params, S data);
/**
* Returns null. Sub-Classes should override it, if they need fallback functionality.
* @param taskContext
* @param command
* @param taskRequestWrapper
* @param decoder
* @param <T>
* @return
* @throws RuntimeException
*/
public <T, S> TaskResult<T> getFallBack(TaskContext taskContext, String command, TaskRequestWrapper<S> taskRequestWrapper,Decoder<T> decoder) throws RuntimeException {
return null;
}
/**
* Call to optionally release any resources used to create the specified response. Useful when Hystrix command
* timeouts result in the call being aborted. This callback is intended to be used for freeing up underlying connections/resources.
* @param taskResult
*/
public <T> void releaseResources(TaskResult<T> taskResult) {
// do nothing
}
/**
* Return the ExecutionIsolationStrategy. Thread is the default.
*/
public ExecutionIsolationStrategy getIsolationStrategy() {
return ExecutionIsolationStrategy.THREAD;
}
/** Getter/Setter methods */
/**
* Returns a command specific executor timeout. Default implementation returns {@value HystrixTaskHandler#DEFAULT_EXECUTOR_TIMEOUT}
* @param commandName the command name being executed
* @return the executor timeout value in milli seconds
*/
public int getExecutorTimeout(String commandName) {
Integer timeout = this.getExecutorTimeouts().get(commandName);
return timeout != null ? timeout : HystrixTaskHandler.DEFAULT_EXECUTOR_TIMEOUT;
}
public Map<String,Integer> getCommandPoolSizeParams() {
return commandPoolSizeParams;
}
public void setCommandPoolSizeParams(Map<String,Integer> commandPoolSizeParams) {
this.commandPoolSizeParams = commandPoolSizeParams;
}
public Map<String,Integer> getConcurrentPoolSizeParams() {
return concurrentPoolSizeParams;
}
public void setConcurrentPoolSizeParams(Map<String,Integer> concurrentPoolSizeParams) {
this.concurrentPoolSizeParams = concurrentPoolSizeParams;
}
public Map<String, Integer> getCoreConcurrentPoolSizeParams() {
return coreConcurrentPoolSizeParams;
}
public void setCoreConcurrentPoolSizeParams(Map<String, Integer> coreConcurrentPoolSizeParams) {
this.coreConcurrentPoolSizeParams = coreConcurrentPoolSizeParams;
}
public Map<String, Integer> getCoreCommandPoolSizeParams() {
return coreCommandPoolSizeParams;
}
public void setCoreCommandPoolSizeParams(Map<String, Integer> coreCommandPoolSizeParams) {
this.coreCommandPoolSizeParams = coreCommandPoolSizeParams;
}
public Map<String, Integer> getExecutorTimeouts() {
return this.executorTimeouts;
}
public void setExecutorTimeouts(Map<String, Integer> executorTimeouts) {
this.executorTimeouts = executorTimeouts;
}
/** End Getter/Setter methods */
}