I'm trying to setup the behaviour of the HystrixCommand on this way:
public abstract class AbstractCircuitBreakerCommand<E> extends HystrixCommand<E> {
protected AbstractCircuitBreakerCommand(final String groupKey, final String commandKey) {
this(groupKey, commandKey, TimeUnit.SECONDS, 10, TimeUnit.SECONDS, 3, TimeUnit.SECONDS, 10, 1);
}
protected AbstractCircuitBreakerCommand(
final String groupKey, final String commandKey,
final TimeUnit metricsWindowTimeUnit, final int metricsWindowTime,
final TimeUnit timeoutTimeUnit, final int timeoutTime,
final TimeUnit windowTimeUnit, final int windowTime,
final int threshold) {
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
.andCommandKey(HystrixCommandKey.Factory.asKey(commandKey))
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
.withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
.withMetricsRollingStatisticalWindowInMilliseconds((int) metricsWindowTimeUnit.toMillis(metricsWindowTime))
.withExecutionTimeoutEnabled(true)
.withExecutionTimeoutInMilliseconds((int) timeoutTimeUnit.toMillis(timeoutTime))
.withCircuitBreakerEnabled(true)
.withCircuitBreakerRequestVolumeThreshold(threshold)
.withCircuitBreakerErrorThresholdPercentage(0)
.withCircuitBreakerSleepWindowInMilliseconds((int) windowTimeUnit.toMillis(windowTime))
.withFallbackEnabled(true)));
}
}
What I expect is short-circuiting the incoming commands after only one exception (or timeout) happens for the next 10 secs (sleepwindowinmilis).
To test it, I've the next unit test.
public class AbstractCircuitBreakerCommandTest {
private final static int ERROR_VALUE = Integer.MIN_VALUE;
private final static String GROUP_KEY = "GROUP_KEY";
private final static String COMMAND_KEY = "COMMAND_KEY";
@Test
public void testSimpleExecution() {
final int expectedValue = 1;
final SimpleCircuitBreakerCommandToTest circuitBreakerCommand =
new SimpleCircuitBreakerCommandToTest(GROUP_KEY, COMMAND_KEY, value -> expectedValue);
Assert.assertEquals(expectedValue, (int) circuitBreakerCommand.execute());
Assert.assertTrue(circuitBreakerCommand.isExecutionComplete());
Assert.assertTrue(circuitBreakerCommand.isSuccessfulExecution());
}
@Test
public void testSimpleUnsuccessfulExecutionBecauseException() {
final SimpleCircuitBreakerCommandToTest circuitBreakerCommand =
new SimpleCircuitBreakerCommandToTest(GROUP_KEY, COMMAND_KEY, value -> {
throw new Exception("Test");
});
Assert.assertEquals(ERROR_VALUE, (int) circuitBreakerCommand.execute());
Assert.assertTrue(circuitBreakerCommand.isExecutionComplete());
Assert.assertTrue(circuitBreakerCommand.isFailedExecution());
Assert.assertTrue(circuitBreakerCommand.isCircuitBreakerOpen());
}
@Test
public void testSimpleUnsuccessfulExecutionBecauseTimeout() {
final SimpleCircuitBreakerCommandToTest circuitBreakerCommand =
new SimpleCircuitBreakerCommandToTest(GROUP_KEY, COMMAND_KEY, value -> {
SleepHelper.sleep(TimeUnit.SECONDS, 4); // The default value is -> 3 seconds.
return 1;
});
Assert.assertEquals(ERROR_VALUE, (int) circuitBreakerCommand.execute());
Assert.assertTrue(circuitBreakerCommand.isExecutionComplete());
Assert.assertTrue(circuitBreakerCommand.isFailedExecution());
Assert.assertTrue(circuitBreakerCommand.isCircuitBreakerOpen());
}
private static abstract class AbstractCircuitBreakerCommandToTest extends AbstractCircuitBreakerCommand<Integer> {
private final Integer value;
private final TestAction testAction;
protected AbstractCircuitBreakerCommandToTest(
final String groupKey, final String commandKey,
final TestAction testAction) {
this(groupKey, commandKey, 1, testAction);
}
protected AbstractCircuitBreakerCommandToTest(
final String groupKey, final String commandKey,
final Integer value, final TestAction testAction) {
super(groupKey, commandKey);
this.value = value;
this.testAction = testAction;
}
@Override
protected Integer run() throws Exception {
return this.testAction.run(this.value);
}
@Override
protected Integer getFallback() {
return ERROR_VALUE;
}
@FunctionalInterface
interface TestAction {
Integer run(final Integer integer) throws Exception;
}
}
private static class SimpleCircuitBreakerCommandToTest extends AbstractCircuitBreakerCommandToTest {
protected SimpleCircuitBreakerCommandToTest(
final String groupKey, final String commandKey,
final TestAction testAction) {
super(groupKey, commandKey, testAction);
}
}
}
But the isCircuitBreakerOpen() method is returning false in the testSimpleUnsuccessfulExecutionBecauseException and the testSimpleUnsuccessfulExecutionBecauseTimeout tests.
Can someone guide me on the right way?. Thank you.