Search in sources :

Example 6 with StateInstance

use of io.seata.saga.statelang.domain.StateInstance in project seata by seata.

the class ProcessCtrlStateMachineEngine method reloadStateMachineInstance.

/**
 * override state machine instance
 *
 * @param instId
 * @return
 */
@Override
public StateMachineInstance reloadStateMachineInstance(String instId) {
    StateMachineInstance inst = stateMachineConfig.getStateLogStore().getStateMachineInstance(instId);
    if (inst != null) {
        StateMachine stateMachine = inst.getStateMachine();
        if (stateMachine == null) {
            stateMachine = stateMachineConfig.getStateMachineRepository().getStateMachineById(inst.getMachineId());
            inst.setStateMachine(stateMachine);
        }
        if (stateMachine == null) {
            throw new EngineExecutionException("StateMachine[id:" + inst.getMachineId() + "] not exist.", FrameworkErrorCode.ObjectNotExists);
        }
        List<StateInstance> stateList = inst.getStateList();
        if (CollectionUtils.isEmpty(stateList)) {
            stateList = stateMachineConfig.getStateLogStore().queryStateInstanceListByMachineInstanceId(instId);
            if (CollectionUtils.isNotEmpty(stateList)) {
                for (StateInstance tmpStateInstance : stateList) {
                    inst.putStateInstance(tmpStateInstance.getId(), tmpStateInstance);
                }
            }
        }
        if (CollectionUtils.isEmpty(inst.getEndParams())) {
            inst.setEndParams(replayContextVariables(inst));
        }
    }
    return inst;
}
Also used : StateMachine(io.seata.saga.statelang.domain.StateMachine) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) StateMachineInstance(io.seata.saga.statelang.domain.StateMachineInstance) StateInstance(io.seata.saga.statelang.domain.StateInstance)

Example 7 with StateInstance

use of io.seata.saga.statelang.domain.StateInstance in project seata by seata.

the class ProcessCtrlStateMachineEngine method findOutLastForwardStateInstance.

/**
 * Find the last instance of the forward execution state
 *
 * @param stateInstanceList
 * @return
 */
public StateInstance findOutLastForwardStateInstance(List<StateInstance> stateInstanceList) {
    StateInstance lastForwardStateInstance = null;
    for (int i = stateInstanceList.size() - 1; i >= 0; i--) {
        StateInstance stateInstance = stateInstanceList.get(i);
        if (!stateInstance.isForCompensation()) {
            if (ExecutionStatus.SU.equals(stateInstance.getCompensationStatus())) {
                continue;
            }
            if (DomainConstants.STATE_TYPE_SUB_STATE_MACHINE.equals(stateInstance.getType())) {
                StateInstance finalState = stateInstance;
                while (StringUtils.hasText(finalState.getStateIdRetriedFor())) {
                    finalState = stateMachineConfig.getStateLogStore().getStateInstance(finalState.getStateIdRetriedFor(), finalState.getMachineInstanceId());
                }
                List<StateMachineInstance> subInst = stateMachineConfig.getStateLogStore().queryStateMachineInstanceByParentId(EngineUtils.generateParentId(finalState));
                if (CollectionUtils.isNotEmpty(subInst)) {
                    if (ExecutionStatus.SU.equals(subInst.get(0).getCompensationStatus())) {
                        continue;
                    }
                    if (ExecutionStatus.UN.equals(subInst.get(0).getCompensationStatus())) {
                        throw new ForwardInvalidException("Last forward execution state instance is SubStateMachine and compensation status is " + "[UN], Operation[forward] denied, stateInstanceId:" + stateInstance.getId(), FrameworkErrorCode.OperationDenied);
                    }
                }
            } else if (ExecutionStatus.UN.equals(stateInstance.getCompensationStatus())) {
                throw new ForwardInvalidException("Last forward execution state instance compensation status is [UN], Operation[forward] " + "denied, stateInstanceId:" + stateInstance.getId(), FrameworkErrorCode.OperationDenied);
            }
            lastForwardStateInstance = stateInstance;
            break;
        }
    }
    return lastForwardStateInstance;
}
Also used : ForwardInvalidException(io.seata.saga.engine.exception.ForwardInvalidException) StateInstance(io.seata.saga.statelang.domain.StateInstance) StateMachineInstance(io.seata.saga.statelang.domain.StateMachineInstance)

Example 8 with StateInstance

use of io.seata.saga.statelang.domain.StateInstance in project seata by seata.

the class SubStateMachineHandler method process.

@Override
public void process(ProcessContext context) throws EngineExecutionException {
    StateInstruction instruction = context.getInstruction(StateInstruction.class);
    SubStateMachineImpl subStateMachine = (SubStateMachineImpl) instruction.getState(context);
    StateMachineEngine engine = (StateMachineEngine) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_ENGINE);
    StateMachineInstance stateMachineInstance = (StateMachineInstance) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_INST);
    StateInstance stateInstance = (StateInstance) context.getVariable(DomainConstants.VAR_NAME_STATE_INST);
    Object inputParamsObj = context.getVariable(DomainConstants.VAR_NAME_INPUT_PARAMS);
    Map<String, Object> startParams = new HashMap<>(0);
    if (inputParamsObj instanceof List) {
        List<Object> listInputParams = (List<Object>) inputParamsObj;
        if (listInputParams.size() > 0) {
            startParams = (Map<String, Object>) listInputParams.get(0);
        }
    } else if (inputParamsObj instanceof Map) {
        startParams = (Map<String, Object>) inputParamsObj;
    }
    startParams.put(DomainConstants.VAR_NAME_PARENT_ID, EngineUtils.generateParentId(stateInstance));
    try {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug(">>>>>>>>>>>>>>>>>>>>>> Start to execute SubStateMachine [{}] by state[{}]", subStateMachine.getStateMachineName(), subStateMachine.getName());
        }
        StateMachineInstance subStateMachineInstance = callSubStateMachine(startParams, engine, context, stateInstance, subStateMachine);
        Map<String, Object> outputParams = subStateMachineInstance.getEndParams();
        boolean isForward = DomainConstants.OPERATION_NAME_FORWARD.equals(context.getVariable(DomainConstants.VAR_NAME_OPERATION_NAME));
        ExecutionStatus callSubMachineStatus = decideStatus(subStateMachineInstance, isForward);
        stateInstance.setStatus(callSubMachineStatus);
        outputParams.put(DomainConstants.VAR_NAME_SUB_STATEMACHINE_EXEC_STATUE, callSubMachineStatus.toString());
        context.setVariable(DomainConstants.VAR_NAME_OUTPUT_PARAMS, outputParams);
        stateInstance.setOutputParams(outputParams);
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("<<<<<<<<<<<<<<<<<<<<<< SubStateMachine[{}] execute finish with status[{}], compensateStatus[{}]", subStateMachine.getStateMachineName(), subStateMachineInstance.getStatus(), subStateMachineInstance.getCompensationStatus());
        }
    } catch (Exception e) {
        LOGGER.error("SubStateMachine[{}] execute failed by state[name:{}]", subStateMachine.getStateMachineName(), subStateMachine.getName(), e);
        if (e instanceof ForwardInvalidException) {
            String retriedId = stateInstance.getStateIdRetriedFor();
            StateInstance stateToBeRetried = null;
            for (StateInstance stateInst : stateMachineInstance.getStateList()) {
                if (retriedId.equals(stateInst.getId())) {
                    stateToBeRetried = stateInst;
                    break;
                }
            }
            if (stateToBeRetried != null) {
                stateInstance.setStatus(stateToBeRetried.getStatus());
            }
        }
        context.setVariable(DomainConstants.VAR_NAME_CURRENT_EXCEPTION, e);
        EngineUtils.handleException(context, subStateMachine, e);
    }
}
Also used : StateMachineEngine(io.seata.saga.engine.StateMachineEngine) StateInstruction(io.seata.saga.engine.pcext.StateInstruction) HashMap(java.util.HashMap) ForwardInvalidException(io.seata.saga.engine.exception.ForwardInvalidException) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) ForwardInvalidException(io.seata.saga.engine.exception.ForwardInvalidException) StateMachineInstance(io.seata.saga.statelang.domain.StateMachineInstance) ExecutionStatus(io.seata.saga.statelang.domain.ExecutionStatus) ArrayList(java.util.ArrayList) List(java.util.List) SubStateMachineImpl(io.seata.saga.statelang.domain.impl.SubStateMachineImpl) HashMap(java.util.HashMap) Map(java.util.Map) StateInstance(io.seata.saga.statelang.domain.StateInstance)

Example 9 with StateInstance

use of io.seata.saga.statelang.domain.StateInstance in project seata by seata.

the class CompensationHolder method findStateInstListToBeCompensated.

public static List<StateInstance> findStateInstListToBeCompensated(ProcessContext context, List<StateInstance> stateInstanceList) {
    List<StateInstance> stateListToBeCompensated = null;
    if (CollectionUtils.isNotEmpty(stateInstanceList)) {
        stateListToBeCompensated = new ArrayList<>(stateInstanceList.size());
        StateMachine stateMachine = (StateMachine) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE);
        StateMachineInstance stateMachineInstance = (StateMachineInstance) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_INST);
        for (StateInstance stateInstance : stateInstanceList) {
            if (stateNeedToCompensate(stateInstance)) {
                State state = stateMachine.getState(EngineUtils.getOriginStateName(stateInstance));
                AbstractTaskState taskState = null;
                if (state instanceof AbstractTaskState) {
                    taskState = (AbstractTaskState) state;
                }
                // The state machine needs to exit directly without compensation.
                if (stateInstance.isForUpdate() && taskState != null && StringUtils.isBlank(taskState.getCompensateState())) {
                    String message = "StateMachineInstance[" + stateMachineInstance.getId() + ":" + stateMachine.getName() + "] have a state [" + stateInstance.getName() + "] is a service for update data, but no compensateState found.";
                    EngineExecutionException exception = ExceptionUtils.createEngineExecutionException(FrameworkErrorCode.CompensationStateNotFound, message, stateMachineInstance, stateInstance);
                    EngineUtils.failStateMachine(context, exception);
                    throw exception;
                }
                if (taskState != null && StringUtils.isNotBlank(taskState.getCompensateState())) {
                    stateListToBeCompensated.add(stateInstance);
                }
            }
        }
    }
    return stateListToBeCompensated;
}
Also used : AbstractTaskState(io.seata.saga.statelang.domain.impl.AbstractTaskState) StateMachine(io.seata.saga.statelang.domain.StateMachine) State(io.seata.saga.statelang.domain.State) AbstractTaskState(io.seata.saga.statelang.domain.impl.AbstractTaskState) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) StateInstance(io.seata.saga.statelang.domain.StateInstance) StateMachineInstance(io.seata.saga.statelang.domain.StateMachineInstance)

Example 10 with StateInstance

use of io.seata.saga.statelang.domain.StateInstance in project seata by seata.

the class LoopTaskHandlerInterceptor method preProcess.

@Override
public void preProcess(ProcessContext context) throws EngineExecutionException {
    if (context.hasVariable(DomainConstants.VAR_NAME_IS_LOOP_STATE)) {
        StateInstruction instruction = context.getInstruction(StateInstruction.class);
        AbstractTaskState currentState = (AbstractTaskState) instruction.getState(context);
        int loopCounter;
        Loop loop;
        // get loop config
        if (context.hasVariable(DomainConstants.VAR_NAME_CURRENT_COMPEN_TRIGGER_STATE)) {
            // compensate condition should get stateToBeCompensated 's config
            CompensationHolder compensationHolder = CompensationHolder.getCurrent(context, true);
            StateInstance stateToBeCompensated = compensationHolder.getStatesNeedCompensation().get(currentState.getName());
            AbstractTaskState compensateState = (AbstractTaskState) stateToBeCompensated.getStateMachineInstance().getStateMachine().getState(EngineUtils.getOriginStateName(stateToBeCompensated));
            loop = compensateState.getLoop();
            loopCounter = LoopTaskUtils.reloadLoopCounter(stateToBeCompensated.getName());
        } else {
            loop = currentState.getLoop();
            loopCounter = (int) context.getVariable(DomainConstants.LOOP_COUNTER);
        }
        Collection collection = LoopContextHolder.getCurrent(context, true).getCollection();
        Map<String, Object> contextVariables = (Map<String, Object>) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONTEXT);
        Map<String, Object> copyContextVariables = new ConcurrentHashMap<>(contextVariables);
        copyContextVariables.put(loop.getElementIndexName(), loopCounter);
        copyContextVariables.put(loop.getElementVariableName(), iterator(collection, loopCounter));
        ((HierarchicalProcessContext) context).setVariableLocally(DomainConstants.VAR_NAME_STATEMACHINE_CONTEXT, copyContextVariables);
    }
}
Also used : Loop(io.seata.saga.statelang.domain.TaskState.Loop) CompensationHolder(io.seata.saga.engine.pcext.utils.CompensationHolder) StateInstruction(io.seata.saga.engine.pcext.StateInstruction) HierarchicalProcessContext(io.seata.saga.proctrl.HierarchicalProcessContext) AbstractTaskState(io.seata.saga.statelang.domain.impl.AbstractTaskState) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Map(java.util.Map) StateInstance(io.seata.saga.statelang.domain.StateInstance)

Aggregations

StateInstance (io.seata.saga.statelang.domain.StateInstance)31 StateMachineInstance (io.seata.saga.statelang.domain.StateMachineInstance)16 EngineExecutionException (io.seata.saga.engine.exception.EngineExecutionException)12 StateInstruction (io.seata.saga.engine.pcext.StateInstruction)11 StateMachineConfig (io.seata.saga.engine.StateMachineConfig)9 ForwardInvalidException (io.seata.saga.engine.exception.ForwardInvalidException)7 Map (java.util.Map)7 StateMachine (io.seata.saga.statelang.domain.StateMachine)5 AbstractTaskState (io.seata.saga.statelang.domain.impl.AbstractTaskState)5 ServiceTaskStateImpl (io.seata.saga.statelang.domain.impl.ServiceTaskStateImpl)5 ArrayList (java.util.ArrayList)5 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)5 HierarchicalProcessContext (io.seata.saga.proctrl.HierarchicalProcessContext)4 ExecutionStatus (io.seata.saga.statelang.domain.ExecutionStatus)4 State (io.seata.saga.statelang.domain.State)4 HashMap (java.util.HashMap)4 List (java.util.List)4 ProcessContext (io.seata.saga.proctrl.ProcessContext)3 Loop (io.seata.saga.statelang.domain.TaskState.Loop)3 LinkedHashMap (java.util.LinkedHashMap)3