private Instruction compensateRoute()

in saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/routers/TaskStateRouter.java [114:193]


    private Instruction compensateRoute(ProcessContext context, State compensationTriggerState) {

        //If there is already a compensation state that has been executed,
        // it is judged whether it is wrong or unsuccessful,
        // and the compensation process is interrupted.
        if (Boolean.TRUE.equals(context.getVariable(DomainConstants.VAR_NAME_FIRST_COMPENSATION_STATE_STARTED))) {

            Exception exception = (Exception)context.getVariable(DomainConstants.VAR_NAME_CURRENT_EXCEPTION);
            if (exception != null) {
                EngineUtils.endStateMachine(context);
                return null;
            }

            StateInstance stateInstance = (StateInstance)context.getVariable(DomainConstants.VAR_NAME_STATE_INST);
            if (stateInstance != null && (!ExecutionStatus.SU.equals(stateInstance.getStatus()))) {
                EngineUtils.endStateMachine(context);
                return null;
            }
        }

        Stack<StateInstance> stateStackToBeCompensated = CompensationHolder.getCurrent(context, true)
            .getStateStackNeedCompensation();
        if (!stateStackToBeCompensated.isEmpty()) {

            StateInstance stateToBeCompensated = stateStackToBeCompensated.pop();

            StateMachine stateMachine = (StateMachine)context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE);
            State state = stateMachine.getState(EngineUtils.getOriginStateName(stateToBeCompensated));
            if (state instanceof AbstractTaskState) {

                AbstractTaskState taskState = (AbstractTaskState)state;

                StateInstruction instruction = context.getInstruction(StateInstruction.class);

                State compensateState = null;
                String compensateStateName = taskState.getCompensateState();
                if (StringUtils.hasLength(compensateStateName)) {
                    compensateState = stateMachine.getState(compensateStateName);
                }

                if (compensateState == null && (taskState instanceof SubStateMachine)) {
                    compensateState = ((SubStateMachine)taskState).getCompensateStateObject();
                    instruction.setTemporaryState(compensateState);
                }

                if (compensateState == null) {
                    EngineUtils.endStateMachine(context);
                    return null;
                }

                instruction.setStateName(compensateState.getName());

                CompensationHolder.getCurrent(context, true).addToBeCompensatedState(compensateState.getName(),
                    stateToBeCompensated);

                ((HierarchicalProcessContext)context).setVariableLocally(
                    DomainConstants.VAR_NAME_FIRST_COMPENSATION_STATE_STARTED, true);

                if (compensateState instanceof CompensateSubStateMachineState) {
                    ((HierarchicalProcessContext)context).setVariableLocally(
                        compensateState.getName() + DomainConstants.VAR_NAME_SUB_MACHINE_PARENT_ID,
                        EngineUtils.generateParentId(stateToBeCompensated));
                }

                return instruction;
            }
        }

        context.removeVariable(DomainConstants.VAR_NAME_CURRENT_COMPEN_TRIGGER_STATE);

        String compensationTriggerStateNext = compensationTriggerState.getNext();
        if (StringUtils.isEmpty(compensationTriggerStateNext)) {
            EngineUtils.endStateMachine(context);
            return null;
        }

        StateInstruction instruction = context.getInstruction(StateInstruction.class);
        instruction.setStateName(compensationTriggerStateNext);
        return instruction;
    }