package org.ovirt.engine.core.vdsbroker.vdsbroker; import static com.netflix.hystrix.HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE; import javax.enterprise.inject.Alternative; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; import org.ovirt.engine.core.vdsbroker.VDSCommandBase; import com.netflix.hystrix.HystrixCommand; import com.netflix.hystrix.HystrixCommandGroupKey; import com.netflix.hystrix.HystrixCommandKey; import com.netflix.hystrix.HystrixCommandProperties; import com.netflix.hystrix.exception.HystrixRuntimeException; @Alternative public class HystrixVdsCommandExecutor implements VdsCommandExecutor { @Override public VDSReturnValue execute(final VDSCommandBase<?> command, final VDSCommandType commandType) { final HystrixCommand.Setter setter; if (command.isAsync()) { setter = setter("AsyncVds" + commandType.name()); } else { setter = setter("Vds" + commandType.name()); } final HystrixCommand<VDSReturnValue> hystrixCommand = new HystrixCommand(setter) { @Override protected VDSReturnValue run() throws Exception { command.execute(); if (command.isAsync()) { // Don't check if the command succeeded to avoid waiting for the result of the asynchronous // operation. return command.getVDSReturnValue(); } else if(command.getVDSReturnValue().getSucceeded()) { return command.getVDSReturnValue(); } else { // throw this so that hystrix can see that this command failed throw new ActionFailedException(command.getVDSReturnValue()); } } }; try { return hystrixCommand.execute(); } catch (HystrixRuntimeException e) { // only thrown for hystrix, so catch it and proceed normally if (e.getCause() instanceof ActionFailedException) { return ((ActionFailedException) e.getCause()).getReturnValue(); } throw e; } } private HystrixCommand.Setter setter(final String key) { return HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(key) ).andCommandKey( HystrixCommandKey.Factory.asKey(key) ).andCommandPropertiesDefaults( HystrixCommandProperties.Setter() .withExecutionIsolationStrategy(SEMAPHORE) .withExecutionTimeoutEnabled(false) .withCircuitBreakerEnabled(false) .withFallbackEnabled(false) .withMetricsRollingStatisticalWindowInMilliseconds(60000) .withMetricsRollingStatisticalWindowBuckets(60) .withExecutionIsolationSemaphoreMaxConcurrentRequests(200)); } private static class ActionFailedException extends Exception { VDSReturnValue returnValue; public ActionFailedException(VDSReturnValue returnValue) { this.returnValue = returnValue; } public VDSReturnValue getReturnValue() { return returnValue; } } }