in saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/interceptors/ServiceTaskHandlerInterceptor.java [297:408]
private void decideExecutionStatus(ProcessContext context, StateInstance stateInstance, ServiceTaskStateImpl state,
Exception exp) {
Map<String, String> statusMatchList = state.getStatus();
if (CollectionUtils.isNotEmpty(statusMatchList)) {
if (state.isAsync()) {
if (LOGGER.isWarnEnabled()) {
LOGGER.warn(
"Service[{}.{}] is execute asynchronously, null return value collected, so user defined "
+ "Status Matching skipped. stateName: {}, branchId: {}", state.getServiceName(),
state.getServiceMethod(), state.getName(), stateInstance.getId());
}
} else {
StateMachineConfig stateMachineConfig = (StateMachineConfig)context.getVariable(
DomainConstants.VAR_NAME_STATEMACHINE_CONFIG);
ExpressionResolver resolver = stateMachineConfig.getExpressionResolver();
Map<Object, String> statusEvaluators = state.getStatusEvaluators();
if (statusEvaluators == null) {
synchronized (state) {
statusEvaluators = state.getStatusEvaluators();
if (statusEvaluators == null) {
statusEvaluators = new LinkedHashMap<>(statusMatchList.size());
String expressionStr, statusVal;
Expression evaluator;
for (Map.Entry<String, String> entry : statusMatchList.entrySet()) {
expressionStr = entry.getKey();
statusVal = entry.getValue();
evaluator = resolver.getExpression(expressionStr);
if (evaluator != null) {
statusEvaluators.put(evaluator, statusVal);
}
}
}
state.setStatusEvaluators(statusEvaluators);
}
}
for (Object evaluatorObj : statusEvaluators.keySet()) {
Expression evaluator = (Expression) evaluatorObj;
String statusVal = statusEvaluators.get(evaluator);
Object elContext;
Class<? extends Expression> expressionClass = evaluator.getClass();
if (ExceptionMatchExpression.class.isAssignableFrom(expressionClass)) {
elContext = context.getVariable(DomainConstants.VAR_NAME_CURRENT_EXCEPTION);
} else if (ELExpression.class.isAssignableFrom(expressionClass)) {
elContext = context.getVariable(DomainConstants.VAR_NAME_OUTPUT_PARAMS);
} else {
elContext = context.getVariables();
}
if (Boolean.TRUE.equals(evaluator.getValue(elContext))) {
stateInstance.setStatus(ExecutionStatus.valueOf(statusVal));
break;
}
}
if (exp == null && (stateInstance.getStatus() == null || ExecutionStatus.RU.equals(
stateInstance.getStatus()))) {
if (state.isForUpdate()) {
stateInstance.setStatus(ExecutionStatus.UN);
} else {
stateInstance.setStatus(ExecutionStatus.FA);
}
stateInstance.setGmtEnd(new Date());
StateMachineInstance stateMachineInstance = stateInstance.getStateMachineInstance();
if (stateMachineInstance.getStateMachine().isPersist() && state.isPersist()
&& stateMachineConfig.getStateLogStore() != null) {
stateMachineConfig.getStateLogStore().recordStateFinished(stateInstance, context);
}
EngineExecutionException exception = new EngineExecutionException("State [" + state.getName()
+ "] execute finished, but cannot matching status, please check its status manually",
FrameworkErrorCode.NoMatchedStatus);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("State[{}] execute finish with status[{}]", state.getName(),
stateInstance.getStatus());
}
EngineUtils.failStateMachine(context, exception);
throw exception;
}
}
}
if (stateInstance.getStatus() == null || ExecutionStatus.RU.equals(stateInstance.getStatus())) {
if (exp == null) {
stateInstance.setStatus(ExecutionStatus.SU);
} else {
if (state.isForUpdate() || state.isForCompensation()) {
stateInstance.setStatus(ExecutionStatus.UN);
ExceptionUtils.NetExceptionType t = ExceptionUtils.getNetExceptionType(exp);
if (t.equals(ExceptionUtils.NetExceptionType.CONNECT_EXCEPTION)) {
stateInstance.setStatus(ExecutionStatus.FA);
} else if (t.equals(ExceptionUtils.NetExceptionType.READ_TIMEOUT_EXCEPTION)) {
stateInstance.setStatus(ExecutionStatus.UN);
}
} else {
stateInstance.setStatus(ExecutionStatus.FA);
}
}
}
if (LOGGER.isInfoEnabled()) {
LOGGER.info("State[{}] finish with status[{}]", state.getName(), stateInstance.getStatus());
}
}