Search in sources :

Example 16 with StateInstance

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

the class TaskStateRouter method compensateRoute.

private Instruction compensateRoute(ProcessContext context, State compensationTriggerState) {
    // 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 != null && 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;
}
Also used : AbstractTaskState(io.seata.saga.statelang.domain.impl.AbstractTaskState) StateInstruction(io.seata.saga.engine.pcext.StateInstruction) StateMachine(io.seata.saga.statelang.domain.StateMachine) SubStateMachine(io.seata.saga.statelang.domain.SubStateMachine) CompensateSubStateMachineState(io.seata.saga.statelang.domain.CompensateSubStateMachineState) State(io.seata.saga.statelang.domain.State) AbstractTaskState(io.seata.saga.statelang.domain.impl.AbstractTaskState) HierarchicalProcessContext(io.seata.saga.proctrl.HierarchicalProcessContext) CompensateSubStateMachineState(io.seata.saga.statelang.domain.CompensateSubStateMachineState) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) StateInstance(io.seata.saga.statelang.domain.StateInstance) SubStateMachine(io.seata.saga.statelang.domain.SubStateMachine)

Example 17 with StateInstance

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

the class LoopTaskUtils method reloadLoopContext.

/**
 * reload loop counter context while forward
 *
 * @param context
 * @param forwardStateName
 */
public static void reloadLoopContext(ProcessContext context, String forwardStateName) {
    StateMachineInstance stateMachineInstance = (StateMachineInstance) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_INST);
    List<StateInstance> actList = stateMachineInstance.getStateList();
    List<StateInstance> forwardStateList = actList.stream().filter(e -> forwardStateName.equals(EngineUtils.getOriginStateName(e))).collect(Collectors.toList());
    LoopContextHolder loopContextHolder = LoopContextHolder.getCurrent(context, true);
    Collection collection = loopContextHolder.getCollection();
    LinkedList<Integer> list = new LinkedList<>();
    for (int i = 0; i < collection.size(); i++) {
        list.addFirst(i);
    }
    int executedNumber = 0;
    LinkedList<Integer> failEndList = new LinkedList<>();
    for (StateInstance stateInstance : forwardStateList) {
        if (!stateInstance.isIgnoreStatus()) {
            if (ExecutionStatus.SU.equals(stateInstance.getStatus())) {
                executedNumber += 1;
            } else {
                stateInstance.setIgnoreStatus(true);
                failEndList.addFirst(reloadLoopCounter(stateInstance.getName()));
            }
            list.remove(Integer.valueOf(reloadLoopCounter(stateInstance.getName())));
        }
    }
    loopContextHolder.getLoopCounterStack().addAll(list);
    loopContextHolder.getForwardCounterStack().addAll(failEndList);
    loopContextHolder.getNrOfInstances().set(collection.size());
    loopContextHolder.getNrOfCompletedInstances().set(executedNumber);
}
Also used : NumberUtils(io.seata.common.util.NumberUtils) ProcessContextImpl(io.seata.saga.proctrl.impl.ProcessContextImpl) LoggerFactory(org.slf4j.LoggerFactory) DomainConstants(io.seata.saga.statelang.domain.DomainConstants) ArrayList(java.util.ArrayList) ExpressionEvaluator(io.seata.saga.engine.evaluation.expression.ExpressionEvaluator) Map(java.util.Map) EvaluatorFactoryManager(io.seata.saga.engine.evaluation.EvaluatorFactoryManager) ExecutionStatus(io.seata.saga.statelang.domain.ExecutionStatus) LinkedList(java.util.LinkedList) ForwardInvalidException(io.seata.saga.engine.exception.ForwardInvalidException) ProcessContext(io.seata.saga.proctrl.ProcessContext) EmptyStackException(java.util.EmptyStackException) Logger(org.slf4j.Logger) CollectionUtils(io.seata.common.util.CollectionUtils) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) StateInstance(io.seata.saga.statelang.domain.StateInstance) StateInstruction(io.seata.saga.engine.pcext.StateInstruction) StateMachineInstance(io.seata.saga.statelang.domain.StateMachineInstance) StateMachine(io.seata.saga.statelang.domain.StateMachine) Collectors(java.util.stream.Collectors) FrameworkErrorCode(io.seata.common.exception.FrameworkErrorCode) State(io.seata.saga.statelang.domain.State) List(java.util.List) StateMachineConfig(io.seata.saga.engine.StateMachineConfig) Loop(io.seata.saga.statelang.domain.TaskState.Loop) StringUtils(io.seata.common.util.StringUtils) AbstractTaskState(io.seata.saga.statelang.domain.impl.AbstractTaskState) Collection(java.util.Collection) LinkedList(java.util.LinkedList) StateMachineInstance(io.seata.saga.statelang.domain.StateMachineInstance) StateInstance(io.seata.saga.statelang.domain.StateInstance)

Example 18 with StateInstance

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

the class ServiceTaskStateHandler method process.

@Override
public void process(ProcessContext context) throws EngineExecutionException {
    StateInstruction instruction = context.getInstruction(StateInstruction.class);
    ServiceTaskStateImpl state = (ServiceTaskStateImpl) instruction.getState(context);
    String serviceName = state.getServiceName();
    String methodName = state.getServiceMethod();
    StateInstance stateInstance = (StateInstance) context.getVariable(DomainConstants.VAR_NAME_STATE_INST);
    Object result;
    try {
        List<Object> input = (List<Object>) context.getVariable(DomainConstants.VAR_NAME_INPUT_PARAMS);
        // Set the current task execution status to RU (Running)
        stateInstance.setStatus(ExecutionStatus.RU);
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug(">>>>>>>>>>>>>>>>>>>>>> Start to execute State[{}], ServiceName[{}], Method[{}], Input:{}", state.getName(), serviceName, methodName, input);
        }
        if (state instanceof CompensateSubStateMachineState) {
            // If it is the compensation of the substate machine,
            // directly call the state machine's compensate method
            result = compensateSubStateMachine(context, state, input, stateInstance, (StateMachineEngine) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_ENGINE));
        } else {
            StateMachineConfig stateMachineConfig = (StateMachineConfig) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONFIG);
            ServiceInvoker serviceInvoker = stateMachineConfig.getServiceInvokerManager().getServiceInvoker(state.getServiceType());
            if (serviceInvoker == null) {
                throw new EngineExecutionException("No such ServiceInvoker[" + state.getServiceType() + "]", FrameworkErrorCode.ObjectNotExists);
            }
            if (serviceInvoker instanceof ApplicationContextAware) {
                ((ApplicationContextAware) serviceInvoker).setApplicationContext(stateMachineConfig.getApplicationContext());
            }
            result = serviceInvoker.invoke(state, input.toArray());
        }
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("<<<<<<<<<<<<<<<<<<<<<< State[{}], ServiceName[{}], Method[{}] Execute finish. result: {}", state.getName(), serviceName, methodName, result);
        }
        if (result != null) {
            stateInstance.setOutputParams(result);
            ((HierarchicalProcessContext) context).setVariableLocally(DomainConstants.VAR_NAME_OUTPUT_PARAMS, result);
        }
    } catch (Throwable e) {
        LOGGER.error("<<<<<<<<<<<<<<<<<<<<<< State[{}], ServiceName[{}], Method[{}] Execute failed.", state.getName(), serviceName, methodName, e);
        ((HierarchicalProcessContext) context).setVariableLocally(DomainConstants.VAR_NAME_CURRENT_EXCEPTION, e);
        EngineUtils.handleException(context, state, e);
    }
}
Also used : StateMachineEngine(io.seata.saga.engine.StateMachineEngine) ApplicationContextAware(org.springframework.context.ApplicationContextAware) StateInstruction(io.seata.saga.engine.pcext.StateInstruction) HierarchicalProcessContext(io.seata.saga.proctrl.HierarchicalProcessContext) CompensateSubStateMachineState(io.seata.saga.statelang.domain.CompensateSubStateMachineState) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) ServiceTaskStateImpl(io.seata.saga.statelang.domain.impl.ServiceTaskStateImpl) ArrayList(java.util.ArrayList) List(java.util.List) StateMachineConfig(io.seata.saga.engine.StateMachineConfig) ServiceInvoker(io.seata.saga.engine.invoker.ServiceInvoker) StateInstance(io.seata.saga.statelang.domain.StateInstance)

Example 19 with StateInstance

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

the class LoopTaskHandlerInterceptor method postProcess.

@Override
public void postProcess(ProcessContext context, Exception e) throws EngineExecutionException {
    if (context.hasVariable(DomainConstants.VAR_NAME_IS_LOOP_STATE)) {
        StateInstance stateInstance = (StateInstance) context.getVariable(DomainConstants.VAR_NAME_STATE_INST);
        if (null != stateInstance && !LoopContextHolder.getCurrent(context, true).isFailEnd()) {
            if (!ExecutionStatus.SU.equals(stateInstance.getStatus())) {
                LoopContextHolder.getCurrent(context, true).setFailEnd(true);
            }
        }
        Exception exp = (Exception) ((HierarchicalProcessContext) context).getVariableLocally(DomainConstants.VAR_NAME_CURRENT_EXCEPTION);
        if (exp == null) {
            exp = e;
        }
        if (null != e) {
            if (context.hasVariable(DomainConstants.LOOP_SEMAPHORE)) {
                Semaphore semaphore = (Semaphore) context.getVariable(DomainConstants.LOOP_SEMAPHORE);
                semaphore.release();
            }
        }
        if (null != exp) {
            LoopContextHolder.getCurrent(context, true).setFailEnd(true);
        } else {
            LoopContextHolder.getCurrent(context, true).getNrOfCompletedInstances().incrementAndGet();
        }
        LoopContextHolder.getCurrent(context, true).getNrOfActiveInstances().decrementAndGet();
    }
}
Also used : Semaphore(java.util.concurrent.Semaphore) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) StateInstance(io.seata.saga.statelang.domain.StateInstance)

Example 20 with StateInstance

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

the class DesignerJsonTransformer method generateTracingGraphJson.

/**
 * Generate tracing graph json
 * @param stateMachineInstance
 * @return
 */
public static String generateTracingGraphJson(StateMachineInstance stateMachineInstance, JsonParser jsonParser) {
    if (stateMachineInstance == null) {
        throw new FrameworkException("StateMachineInstance is not exits", FrameworkErrorCode.StateMachineInstanceNotExists);
    }
    String stateMachineJson = stateMachineInstance.getStateMachine().getContent();
    if (StringUtils.isEmpty(stateMachineJson)) {
        throw new FrameworkException("Cannot get StateMachine Json", FrameworkErrorCode.ObjectNotExists);
    }
    Map<String, Object> stateMachineJsonObj = jsonParser.parse(stateMachineJson, Map.class, true);
    if (!DesignerJsonTransformer.isDesignerJson(stateMachineJsonObj)) {
        throw new FrameworkException("StateMachine Json is not generated by Designer", FrameworkErrorCode.InvalidConfiguration);
    }
    Map<String, List<StateInstance>> stateInstanceMapGroupByName = new HashMap<>(stateMachineInstance.getStateMap().size());
    for (StateInstance stateInstance : stateMachineInstance.getStateMap().values()) {
        CollectionUtils.computeIfAbsent(stateInstanceMapGroupByName, stateInstance.getName(), key -> new ArrayList<>()).add(stateInstance);
    }
    List<Object> nodesArray = (List<Object>) stateMachineJsonObj.get("nodes");
    for (Object nodeObj : nodesArray) {
        Map<String, Object> node = (Map<String, Object>) nodeObj;
        String stateId = (String) node.get("stateId");
        String stateType = (String) node.get("stateType");
        if ("ServiceTask".equals(stateType) || "SubStateMachine".equals(stateType) || "Compensation".equals(stateType)) {
            node.remove("color");
        }
        List<StateInstance> stateInstanceList = stateInstanceMapGroupByName.get(stateId);
        if (CollectionUtils.isNotEmpty(stateInstanceList)) {
            StateInstance stateInstance = null;
            if (stateInstanceList.size() == 1) {
                stateInstance = stateInstanceList.get(0);
            } else {
                // find out latest stateInstance
                for (StateInstance stateInst : stateInstanceList) {
                    if (stateInstance == null || stateInst.getGmtStarted().after(stateInstance.getGmtStarted())) {
                        stateInstance = stateInst;
                    }
                }
            }
            node.put("stateInstanceId", stateInstance.getId());
            node.put("stateInstanceStatus", stateInstance.getStatus());
            if (ExecutionStatus.SU.equals(stateInstance.getStatus())) {
                node.put("color", "green");
                Map<String, Object> style = new LinkedHashMap<>();
                style.put("fill", "#00D73E");
                style.put("lineWidth", 2);
                node.put("style", style);
            } else {
                node.put("color", "red");
                Map<String, Object> style = new LinkedHashMap<>();
                style.put("fill", "#FF7777");
                style.put("lineWidth", 2);
                node.put("style", style);
            }
        }
    }
    if (stateMachineJsonObj != null) {
        return jsonParser.toJsonString(stateMachineJsonObj, true);
    }
    return "";
}
Also used : CollectionUtils(io.seata.common.util.CollectionUtils) StateInstance(io.seata.saga.statelang.domain.StateInstance) StateMachineInstance(io.seata.saga.statelang.domain.StateMachineInstance) HashMap(java.util.HashMap) FrameworkErrorCode(io.seata.common.exception.FrameworkErrorCode) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) List(java.util.List) Map(java.util.Map) JsonParser(io.seata.saga.statelang.parser.JsonParser) ExecutionStatus(io.seata.saga.statelang.domain.ExecutionStatus) FrameworkException(io.seata.common.exception.FrameworkException) StringUtils(org.springframework.util.StringUtils) FrameworkException(io.seata.common.exception.FrameworkException) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) 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