private void decideExecutionStatus()

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());
        }
    }