Skip to content

Commit

Permalink
Merge pull request Netflix#1008 from mattrjacobs/rebased-pr-1003
Browse files Browse the repository at this point in the history
Added AbstractCommand.getExecutionException to solve Netflix#998
  • Loading branch information
mattrjacobs committed Dec 3, 2015
2 parents ba30ec6 + f286e31 commit d8a1ed7
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 20 deletions.
66 changes: 49 additions & 17 deletions hystrix-core/src/main/java/com/netflix/hystrix/AbstractCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -398,20 +398,24 @@ public void call() {
}
} else {
metrics.markSemaphoreRejection();
Exception semaphoreRejectionException = new RuntimeException("could not acquire a semaphore for execution");
executionResult = executionResult.setExecutionException(semaphoreRejectionException);
logger.debug("HystrixCommand Execution Rejection by Semaphore."); // debug only since we're throwing the exception and someone higher will do something with it
// retrieve a fallback or throw an exception if no fallback available
getFallbackOrThrowException(HystrixEventType.SEMAPHORE_REJECTED, FailureType.REJECTED_SEMAPHORE_EXECUTION,
"could not acquire a semaphore for execution", new RuntimeException("could not acquire a semaphore for execution"))
"could not acquire a semaphore for execution", semaphoreRejectionException)
.lift(new DeprecatedOnCompleteWithValueHookApplication(_this))
.unsafeSubscribe(observer);
}
} else {
// record that we are returning a short-circuited fallback
metrics.markShortCircuited();
// short-circuit and go directly to fallback (or throw an exception if no fallback implemented)
Exception shortCircuitException = new RuntimeException("Hystrix circuit short-circuited and is OPEN");
executionResult = executionResult.setExecutionException(shortCircuitException);
try {
getFallbackOrThrowException(HystrixEventType.SHORT_CIRCUITED, FailureType.SHORTCIRCUIT,
"short-circuited", new RuntimeException("Hystrix circuit short-circuited and is OPEN"))
"short-circuited", shortCircuitException)
.lift(new DeprecatedOnCompleteWithValueHookApplication(_this))
.unsafeSubscribe(observer);
} catch (Exception e) {
Expand Down Expand Up @@ -579,6 +583,7 @@ public void call() {
@Override
public Observable<R> call(Throwable t) {
Exception e = getExceptionFromThrowable(t);
executionResult = executionResult.setExecutionException(e);
if (e instanceof RejectedExecutionException) {
/**
* Rejection handling
Expand Down Expand Up @@ -1749,24 +1754,29 @@ public int getNumberOfPermitsUsed() {
protected static class ExecutionResult {
protected final List<HystrixEventType> events;
private final int executionTime;
private final Exception exception;
private final Exception failedExecutionException;
private final Exception executionException;
private final long commandRunStartTimeInNanos;
private final int numEmissions;
private final int numFallbackEmissions;

private ExecutionResult(HystrixEventType... events) {
this(Arrays.asList(events), -1, null, 0, 0);
this(Arrays.asList(events), -1, null, null, 0, 0);
}

public ExecutionResult setExecutionTime(int executionTime) {
return new ExecutionResult(events, executionTime, exception, numEmissions, numFallbackEmissions);
return new ExecutionResult(events, executionTime, failedExecutionException, executionException, numEmissions, numFallbackEmissions);
}

public ExecutionResult setException(Exception e) {
return new ExecutionResult(events, executionTime, e, numEmissions, numFallbackEmissions);
return new ExecutionResult(events, executionTime, e, executionException, numEmissions, numFallbackEmissions);
}

private ExecutionResult(List<HystrixEventType> events, int executionTime, Exception e, int numEmissions, int numFallbackEmissions) {
public ExecutionResult setExecutionException(Exception executionException) {
return new ExecutionResult(events, executionTime, failedExecutionException, executionException, numEmissions, numFallbackEmissions);
}

private ExecutionResult(List<HystrixEventType> events, int executionTime, Exception failedExecutionException, Exception executionException, int numEmissions, int numFallbackEmissions) {
// we are safe assigning the List reference instead of deep-copying
// because we control the original list in 'newEvent'
this.events = events;
Expand All @@ -1777,8 +1787,8 @@ private ExecutionResult(List<HystrixEventType> events, int executionTime, Except
else {
this.commandRunStartTimeInNanos = -1;
}
this.exception = e;

this.failedExecutionException = failedExecutionException;
this.executionException = executionException;
this.numEmissions = numEmissions;
this.numFallbackEmissions = numFallbackEmissions;
}
Expand All @@ -1793,7 +1803,7 @@ private ExecutionResult(List<HystrixEventType> events, int executionTime, Except
* @return new {@link com.netflix.hystrix.AbstractCommand.ExecutionResult} with events added
*/
public ExecutionResult addEvents(HystrixEventType... events) {
return new ExecutionResult(getUpdatedList(this.events, events), executionTime, exception, numEmissions, numFallbackEmissions);
return new ExecutionResult(getUpdatedList(this.events, events), executionTime, failedExecutionException, executionException, numEmissions, numFallbackEmissions);
}

private static List<HystrixEventType> getUpdatedList(List<HystrixEventType> currentList, HystrixEventType... newEvents) {
Expand All @@ -1808,10 +1818,12 @@ public int getExecutionTime() {
}
public long getCommandRunStartTimeInNanos() {return commandRunStartTimeInNanos; }



public Exception getException() {
return exception;
return failedExecutionException;
}

public Exception getExecutionException() {
return executionException;
}

/**
Expand All @@ -1823,14 +1835,14 @@ public Exception getException() {
public ExecutionResult addEmission(HystrixEventType eventType) {
switch (eventType) {
case EMIT: if (events.contains(HystrixEventType.EMIT)) {
return new ExecutionResult(events, executionTime, exception, numEmissions + 1, numFallbackEmissions);
return new ExecutionResult(events, executionTime, failedExecutionException, executionException, numEmissions + 1, numFallbackEmissions);
} else {
return new ExecutionResult(getUpdatedList(this.events, HystrixEventType.EMIT), executionTime, exception, numEmissions +1, numFallbackEmissions);
return new ExecutionResult(getUpdatedList(this.events, HystrixEventType.EMIT), executionTime, failedExecutionException, executionException, numEmissions +1, numFallbackEmissions);
}
case FALLBACK_EMIT: if (events.contains(HystrixEventType.FALLBACK_EMIT)) {
return new ExecutionResult(events, executionTime, exception, numEmissions, numFallbackEmissions + 1);
return new ExecutionResult(events, executionTime, failedExecutionException, executionException, numEmissions, numFallbackEmissions + 1);
} else {
return new ExecutionResult(getUpdatedList(this.events, HystrixEventType.FALLBACK_EMIT), executionTime, exception, numEmissions, numFallbackEmissions + 1);
return new ExecutionResult(getUpdatedList(this.events, HystrixEventType.FALLBACK_EMIT), executionTime, failedExecutionException, executionException, numEmissions, numFallbackEmissions + 1);
}
default: return this;
}
Expand Down Expand Up @@ -1940,6 +1952,26 @@ public Throwable getFailedExecutionException() {
return executionResult.getException();
}

/**
* Get the Throwable/Exception emitted by this command instance prior to checking the fallback.
* This exception instance may have been generated via a number of mechanisms:
* 1) failed execution (in this case, same result as {@link #getFailedExecutionException()}.
* 2) timeout
* 3) short-circuit
* 4) rejection
* 5) bad request
*
* If the command execution was successful, then this exception instance is null (there was no exception)
*
* Note that the caller of the command may not receive this exception, as fallbacks may be served as a response to
* the exception.
*
* @return Throwable or null
*/
public Throwable getExecutionException() {
return executionResult.getExecutionException();
}

/**
* Whether the response received from was the result of some type of failure
* and <code>getFallback()</code> being called.
Expand Down
Loading

0 comments on commit d8a1ed7

Please sign in to comment.