-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
21 changed files
with
841 additions
and
96 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
nflow-engine/src/main/java/io/nflow/engine/exception/DispatcherExceptionAnalyzer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package io.nflow.engine.exception; | ||
|
||
import static org.slf4j.LoggerFactory.getLogger; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.event.Level; | ||
import org.springframework.stereotype.Component; | ||
|
||
import io.nflow.engine.exception.DispatcherExceptionHandling.Builder; | ||
import io.nflow.engine.internal.dao.PollingBatchException; | ||
import io.nflow.engine.internal.dao.PollingRaceConditionException; | ||
|
||
/** | ||
* Dispatcher exception analyzer analyzes exceptions thrown by the workflow dispatcher and determines how the exception is | ||
* handled. | ||
*/ | ||
@Component | ||
public class DispatcherExceptionAnalyzer { | ||
|
||
private static final Logger logger = getLogger(DispatcherExceptionAnalyzer.class); | ||
|
||
/** | ||
* Analyze the exception. | ||
* | ||
* @param e | ||
* The exception to be analyzed. | ||
* @return How the exception should be handled. | ||
*/ | ||
public final DispatcherExceptionHandling analyzeSafely(Exception e) { | ||
try { | ||
return analyze(e); | ||
} catch (Exception analyzerException) { | ||
logger.error("Failed to analyze exception, using default handling.", analyzerException); | ||
} | ||
return getDefultHandling(e); | ||
} | ||
|
||
/** | ||
* Override this to provide custom handling. | ||
* | ||
* @param e | ||
* The exception to be analyzed. | ||
* @return How the exception should be handled. | ||
*/ | ||
protected DispatcherExceptionHandling analyze(Exception e) { | ||
return getDefultHandling(e); | ||
} | ||
|
||
private DispatcherExceptionHandling getDefultHandling(Exception e) { | ||
Builder builder = new DispatcherExceptionHandling.Builder(); | ||
if (e instanceof PollingRaceConditionException) { | ||
builder.setLogLevel(Level.DEBUG).setLogStackTrace(false).setRandomizeSleep(true); | ||
} else if (e instanceof PollingBatchException) { | ||
builder.setLogLevel(Level.WARN).setLogStackTrace(false).setSleep(false); | ||
} else if (e instanceof InterruptedException) { | ||
builder.setLog(false).setSleep(false); | ||
} | ||
return builder.build(); | ||
} | ||
} |
89 changes: 89 additions & 0 deletions
89
nflow-engine/src/main/java/io/nflow/engine/exception/DispatcherExceptionHandling.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package io.nflow.engine.exception; | ||
|
||
/** | ||
* Controls how an exception should be handled by the dispatcher. | ||
*/ | ||
public class DispatcherExceptionHandling extends ExceptionHandling { | ||
/** | ||
* True when dispatcher should log the exception. | ||
*/ | ||
public final boolean log; | ||
/** | ||
* True when dispatcher should sleep a while after exception. | ||
*/ | ||
public final boolean sleep; | ||
/** | ||
* True when the sleep time should be randomized. | ||
*/ | ||
public final boolean randomizeSleep; | ||
|
||
DispatcherExceptionHandling(Builder builder) { | ||
super(builder); | ||
this.log = builder.log; | ||
this.sleep = builder.sleep; | ||
this.randomizeSleep = builder.randomizeSleep; | ||
} | ||
|
||
/** | ||
* Builder for exception handling settings. | ||
*/ | ||
public static class Builder extends ExceptionHandling.Builder<Builder> { | ||
boolean log = true; | ||
boolean sleep = true; | ||
boolean randomizeSleep = false; | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
@Override | ||
public Builder getThis() { | ||
return this; | ||
} | ||
|
||
/** | ||
* Set if dispatcher should log the exception or not. Default is true. | ||
* | ||
* @param log | ||
* True if dispatcher should log the exception. | ||
* @return This. | ||
*/ | ||
public Builder setLog(boolean log) { | ||
this.log = log; | ||
return this; | ||
} | ||
|
||
/** | ||
* Set if dispatcher should sleep a while after exception or not. Default is true. | ||
* | ||
* @param sleep | ||
* True if dispatcher should sleep a while after exception. | ||
* @return This. | ||
*/ | ||
public Builder setSleep(boolean sleep) { | ||
this.sleep = sleep; | ||
return this; | ||
} | ||
|
||
/** | ||
* Set if sleep time should be randomized or not. Default is false. | ||
* | ||
* @param randomizeSleep | ||
* True if sleep time should be randomized. | ||
* @return This. | ||
*/ | ||
public Builder setRandomizeSleep(boolean randomizeSleep) { | ||
this.randomizeSleep = randomizeSleep; | ||
return this; | ||
} | ||
|
||
/** | ||
* Create the dispatcher exception handling object. | ||
* | ||
* @return Dispatcher exception handling. | ||
*/ | ||
@Override | ||
public DispatcherExceptionHandling build() { | ||
return new DispatcherExceptionHandling(this); | ||
} | ||
} | ||
} |
72 changes: 72 additions & 0 deletions
72
nflow-engine/src/main/java/io/nflow/engine/exception/ExceptionHandling.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package io.nflow.engine.exception; | ||
|
||
import static org.slf4j.event.Level.ERROR; | ||
|
||
import org.slf4j.event.Level; | ||
|
||
/** | ||
* Controls how an exception should be handled. | ||
*/ | ||
public class ExceptionHandling { | ||
/** | ||
* The log entry level for logging the exception. | ||
*/ | ||
public final Level logLevel; | ||
/** | ||
* True when the exception stack trace should be logged. | ||
*/ | ||
public final boolean logStackTrace; | ||
|
||
ExceptionHandling(Builder<?> builder) { | ||
this.logLevel = builder.logLevel; | ||
this.logStackTrace = builder.logStackTrace; | ||
} | ||
|
||
/** | ||
* Builder for exception handling settings. | ||
*/ | ||
public abstract static class Builder<T extends Builder<T>> { | ||
Level logLevel = ERROR; | ||
boolean logStackTrace = true; | ||
|
||
/** | ||
* Return this. | ||
* | ||
* @return This. | ||
*/ | ||
public abstract T getThis(); | ||
|
||
/** | ||
* Set the log entry level. Default is ERROR. | ||
* | ||
* @param logLevel | ||
* The log entry level. | ||
* @return This. | ||
*/ | ||
public T setLogLevel(Level logLevel) { | ||
this.logLevel = logLevel; | ||
return getThis(); | ||
} | ||
|
||
/** | ||
* Set if exception stack trace should be logged or not. Default is true. | ||
* | ||
* @param logStackTrace | ||
* True to log the exception stack trace, false to log the exception message only. | ||
* @return This. | ||
*/ | ||
public T setLogStackTrace(boolean logStackTrace) { | ||
this.logStackTrace = logStackTrace; | ||
return getThis(); | ||
} | ||
|
||
/** | ||
* Create the exception handling object. | ||
* | ||
* @return Exception handling. | ||
*/ | ||
public ExceptionHandling build() { | ||
return new ExceptionHandling(getThis()); | ||
} | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
nflow-engine/src/main/java/io/nflow/engine/exception/StateProcessExceptionHandling.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package io.nflow.engine.exception; | ||
|
||
/** | ||
* Controls how an exception thrown by a state method should be handled by the workflow state processor. | ||
*/ | ||
public class StateProcessExceptionHandling extends ExceptionHandling { | ||
/** | ||
* True when the state method processing should be retried. | ||
*/ | ||
public final boolean isRetryable; | ||
|
||
StateProcessExceptionHandling(Builder builder) { | ||
super(builder); | ||
this.isRetryable = builder.isRetryable; | ||
} | ||
|
||
/** | ||
* Builder for exception handling settings. | ||
*/ | ||
public static class Builder extends ExceptionHandling.Builder<Builder> { | ||
boolean isRetryable = true; | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
@Override | ||
public Builder getThis() { | ||
return this; | ||
} | ||
|
||
/** | ||
* Set if state method processing is retryable or not. | ||
* | ||
* @param isRetryable | ||
* True if state method processing should be retried. | ||
* @return This. | ||
*/ | ||
public Builder setRetryable(boolean isRetryable) { | ||
this.isRetryable = isRetryable; | ||
return this; | ||
} | ||
|
||
/** | ||
* Create the exception handling object. | ||
* | ||
* @return State process exception handling. | ||
*/ | ||
@Override | ||
public StateProcessExceptionHandling build() { | ||
return new StateProcessExceptionHandling(this); | ||
} | ||
} | ||
} |
66 changes: 66 additions & 0 deletions
66
nflow-engine/src/main/java/io/nflow/engine/exception/StateSaveExceptionAnalyzer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package io.nflow.engine.exception; | ||
|
||
import static org.joda.time.Duration.standardSeconds; | ||
import static org.slf4j.LoggerFactory.getLogger; | ||
|
||
import javax.inject.Inject; | ||
|
||
import org.joda.time.Duration; | ||
import org.slf4j.Logger; | ||
import org.springframework.core.env.Environment; | ||
import org.springframework.stereotype.Component; | ||
|
||
/** | ||
* State save exception analyzer analyzes exceptions thrown while trying to save workflow state and determines how the exception | ||
* is handled. | ||
*/ | ||
@Component | ||
public class StateSaveExceptionAnalyzer { | ||
|
||
private static final Logger logger = getLogger(StateSaveExceptionAnalyzer.class); | ||
|
||
private final StateSaveExceptionHandling handling; | ||
|
||
/** | ||
* Create state save exception analyzer. | ||
* | ||
* @param env | ||
* The Spring environment. | ||
*/ | ||
@Inject | ||
public StateSaveExceptionAnalyzer(Environment env) { | ||
Duration retryDelay = standardSeconds(env.getRequiredProperty("nflow.executor.stateSaveRetryDelay.seconds", Long.class)); | ||
handling = new StateSaveExceptionHandling.Builder().setRetryDelay(retryDelay).build(); | ||
} | ||
|
||
/** | ||
* Analyze the exception. | ||
* | ||
* @param e | ||
* The exception to be analyzed. | ||
* @param saveRetryCount | ||
* How many times the saving has been attempted before this attempt. | ||
* @return How the exception should be handled. | ||
*/ | ||
public final StateSaveExceptionHandling analyzeSafely(Exception e, int saveRetryCount) { | ||
try { | ||
return analyze(e, saveRetryCount); | ||
} catch (Exception analyzerException) { | ||
logger.error("Failed to analyze exception, using default handling.", analyzerException); | ||
} | ||
return handling; | ||
} | ||
|
||
/** | ||
* Override this to provide custom handling. | ||
* | ||
* @param e | ||
* The exception to be analyzed. | ||
* @param saveRetryCount | ||
* How many times the saving has been attempted before this attempt. | ||
* @return How the exception should be handled. | ||
*/ | ||
protected StateSaveExceptionHandling analyze(Exception e, int saveRetryCount) { | ||
return handling; | ||
} | ||
} |
Oops, something went wrong.