Skip to content

Commit 3ed5995

Browse files
committed
Merge pull request #456 from gerrit-hntschl/badrequestexception-from-executionhook
Bypass fallback/circuit breaker for BadRequestExceptions from ExecutionHook
2 parents 33b1ea3 + c05aca4 commit 3ed5995

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

hystrix-core/src/main/java/com/netflix/hystrix/AbstractCommand.java

+6
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,12 @@ public Observable<R> call(Throwable t) {
624624
} catch (Exception hookException) {
625625
logger.warn("Error calling ExecutionHook.endRunFailure", hookException);
626626
}
627+
/*
628+
* Treat HystrixBadRequestException from ExecutionHook like a plain HystrixBadRequestException.
629+
*/
630+
if (e instanceof HystrixBadRequestException){
631+
return Observable.error(e);
632+
}
627633

628634
logger.debug("Error executing HystrixCommand.run(). Proceeding to fallback logic ...", e);
629635

hystrix-core/src/test/java/com/netflix/hystrix/HystrixCommandTest.java

+56
Original file line numberDiff line numberDiff line change
@@ -4347,6 +4347,25 @@ public void call(Throwable t1) {
43474347
assertEquals(1, HystrixRequestLog.getCurrentRequest().getAllExecutedCommands().size());
43484348
}
43494349

4350+
@Test
4351+
public void testExceptionConvertedToBadRequestExceptionInExecutionHookBypassesCircuitBreaker(){
4352+
TestCircuitBreaker circuitBreaker = new TestCircuitBreaker();
4353+
try {
4354+
new ExceptionToBadRequestByExecutionHookCommand(circuitBreaker, ExecutionIsolationStrategy.THREAD).execute();
4355+
fail("we expect to receive a " + HystrixBadRequestException.class.getSimpleName());
4356+
} catch (HystrixBadRequestException e) {
4357+
// success
4358+
e.printStackTrace();
4359+
} catch (Exception e) {
4360+
e.printStackTrace();
4361+
fail("We expect a " + HystrixBadRequestException.class.getSimpleName() + " but got a " + e.getClass().getSimpleName());
4362+
}
4363+
4364+
assertEquals(0, circuitBreaker.metrics.getRollingCount(HystrixRollingNumberEvent.SUCCESS));
4365+
assertEquals(0, circuitBreaker.metrics.getRollingCount(HystrixRollingNumberEvent.EXCEPTION_THROWN));
4366+
assertEquals(0, circuitBreaker.metrics.getRollingCount(HystrixRollingNumberEvent.FAILURE));
4367+
}
4368+
43504369
/* ******************************************************************************** */
43514370
/* ******************************************************************************** */
43524371
/* private HystrixCommand class implementations for unit testing */
@@ -4435,6 +4454,11 @@ TestCommandBuilder setExecutionSemaphore(TryableSemaphore executionSemaphore) {
44354454
return this;
44364455
}
44374456

4457+
TestCommandBuilder setExecutionHook(TestExecutionHook executionHook) {
4458+
this.executionHook = executionHook;
4459+
return this;
4460+
}
4461+
44384462
}
44394463

44404464
}
@@ -5217,6 +5241,37 @@ protected String getCacheKey() {
52175241

52185242
}
52195243

5244+
private static class BusinessException extends Exception {
5245+
public BusinessException(String msg) {
5246+
super(msg);
5247+
}
5248+
}
5249+
5250+
private static class ExceptionToBadRequestByExecutionHookCommand extends TestHystrixCommand<Boolean> {
5251+
public ExceptionToBadRequestByExecutionHookCommand(TestCircuitBreaker circuitBreaker, ExecutionIsolationStrategy isolationType) {
5252+
super(testPropsBuilder()
5253+
.setCircuitBreaker(circuitBreaker)
5254+
.setCommandPropertiesDefaults(HystrixCommandPropertiesTest.getUnitTestPropertiesSetter().withExecutionIsolationStrategy(isolationType))
5255+
.setExecutionHook(new TestExecutionHook(){
5256+
@Override
5257+
public <T> Exception onRunError(HystrixInvokable<T> commandInstance, Exception e) {
5258+
super.onRunError(commandInstance, e);
5259+
return new HystrixBadRequestException("autoconverted exception", e);
5260+
}
5261+
}));
5262+
}
5263+
5264+
@Override
5265+
protected Boolean run() throws BusinessException {
5266+
throw new BusinessException("invalid input by the user");
5267+
}
5268+
5269+
@Override
5270+
protected String getCacheKey() {
5271+
return "nein";
5272+
}
5273+
}
5274+
52205275
private static class CommandWithErrorThrown extends TestHystrixCommand<Boolean> {
52215276

52225277
public CommandWithErrorThrown(TestCircuitBreaker circuitBreaker) {
@@ -5404,4 +5459,5 @@ public <T> void onThreadComplete(HystrixInvokable<T> commandInstance) {
54045459
}
54055460

54065461
}
5462+
54075463
}

0 commit comments

Comments
 (0)