Search in sources :

Example 1 with State

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

the class StateInstruction method getState.

public State getState(ProcessContext context) {
    if (getTemporaryState() != null) {
        return temporaryState;
    }
    String stateName = getStateName();
    String stateMachineName = getStateMachineName();
    String tenantId = getTenantId();
    if (StringUtils.isEmpty(stateMachineName)) {
        throw new EngineExecutionException("StateMachineName is required", FrameworkErrorCode.ParameterRequired);
    }
    StateMachineConfig stateMachineConfig = (StateMachineConfig) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONFIG);
    StateMachine stateMachine = stateMachineConfig.getStateMachineRepository().getStateMachine(stateMachineName, tenantId);
    if (stateMachine == null) {
        throw new EngineExecutionException("StateMachine[" + stateMachineName + "] is not exist", FrameworkErrorCode.ObjectNotExists);
    }
    if (StringUtils.isEmpty(stateName)) {
        stateName = stateMachine.getStartState();
        setStateName(stateName);
    }
    State state = stateMachine.getStates().get(stateName);
    if (state == null) {
        throw new EngineExecutionException("State[" + stateName + "] is not exist", FrameworkErrorCode.ObjectNotExists);
    }
    return state;
}
Also used : StateMachine(io.seata.saga.statelang.domain.StateMachine) State(io.seata.saga.statelang.domain.State) StateMachineConfig(io.seata.saga.engine.StateMachineConfig) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException)

Example 2 with State

use of io.seata.saga.statelang.domain.State 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 3 with State

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

the class TaskStateRouter method route.

@Override
public Instruction route(ProcessContext context, State state) throws EngineExecutionException {
    StateInstruction stateInstruction = context.getInstruction(StateInstruction.class);
    if (stateInstruction.isEnd()) {
        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("StateInstruction is ended, Stop the StateMachine executing. StateMachine[{}] Current State[{}]", stateInstruction.getStateMachineName(), state.getName());
        }
        return null;
    }
    // check if in loop async condition
    if (Boolean.TRUE.equals(context.getVariable(DomainConstants.VAR_NAME_IS_LOOP_STATE))) {
        return null;
    }
    // The current CompensationTriggerState can mark the compensation process is started and perform compensation
    // route processing.
    State compensationTriggerState = (State) context.getVariable(DomainConstants.VAR_NAME_CURRENT_COMPEN_TRIGGER_STATE);
    if (compensationTriggerState != null) {
        return compensateRoute(context, compensationTriggerState);
    }
    // There is an exception route, indicating that an exception is thrown, and the exception route is prioritized.
    String next = (String) context.getVariable(DomainConstants.VAR_NAME_CURRENT_EXCEPTION_ROUTE);
    if (StringUtils.hasLength(next)) {
        context.removeVariable(DomainConstants.VAR_NAME_CURRENT_EXCEPTION_ROUTE);
    } else {
        next = state.getNext();
    }
    // If next is empty, the state selected by the Choice state was taken.
    if (!StringUtils.hasLength(next) && context.hasVariable(DomainConstants.VAR_NAME_CURRENT_CHOICE)) {
        next = (String) context.getVariable(DomainConstants.VAR_NAME_CURRENT_CHOICE);
        context.removeVariable(DomainConstants.VAR_NAME_CURRENT_CHOICE);
    }
    if (!StringUtils.hasLength(next)) {
        return null;
    }
    StateMachine stateMachine = state.getStateMachine();
    State nextState = stateMachine.getState(next);
    if (nextState == null) {
        throw new EngineExecutionException("Next state[" + next + "] is not exits", FrameworkErrorCode.ObjectNotExists);
    }
    stateInstruction.setStateName(next);
    if (null != LoopTaskUtils.getLoopConfig(context, nextState)) {
        stateInstruction.setTemporaryState(new LoopStartStateImpl());
    }
    return stateInstruction;
}
Also used : LoopStartStateImpl(io.seata.saga.statelang.domain.impl.LoopStartStateImpl) StateInstruction(io.seata.saga.engine.pcext.StateInstruction) CompensateSubStateMachineState(io.seata.saga.statelang.domain.CompensateSubStateMachineState) State(io.seata.saga.statelang.domain.State) AbstractTaskState(io.seata.saga.statelang.domain.impl.AbstractTaskState) StateMachine(io.seata.saga.statelang.domain.StateMachine) SubStateMachine(io.seata.saga.statelang.domain.SubStateMachine) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException)

Example 4 with State

use of io.seata.saga.statelang.domain.State 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 5 with State

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

the class StateMachineParserImpl method parse.

@Override
public StateMachine parse(String json) {
    JsonParser jsonParser = JsonParserFactory.getJsonParser(jsonParserName);
    if (jsonParser == null) {
        throw new RuntimeException("Cannot find JsonParer by name: " + jsonParserName);
    }
    Map<String, Object> node = jsonParser.parse(json, Map.class, true);
    if (DesignerJsonTransformer.isDesignerJson(node)) {
        node = DesignerJsonTransformer.toStandardJson(node);
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("===== Transformed standard state language:\n{}", jsonParser.toJsonString(node, true));
        }
    }
    StateMachineImpl stateMachine = new StateMachineImpl();
    stateMachine.setName((String) node.get("Name"));
    stateMachine.setComment((String) node.get("Comment"));
    stateMachine.setVersion((String) node.get("Version"));
    stateMachine.setStartState((String) node.get("StartState"));
    String recoverStrategy = (String) node.get("RecoverStrategy");
    if (StringUtils.isNotBlank(recoverStrategy)) {
        stateMachine.setRecoverStrategy(RecoverStrategy.valueOf(recoverStrategy));
    }
    Object isPersist = node.get("IsPersist");
    if (Boolean.FALSE.equals(isPersist)) {
        stateMachine.setPersist(false);
    }
    // customize if update origin or append new retryStateInstLog
    Object isRetryPersistModeUpdate = node.get("IsRetryPersistModeUpdate");
    if (isRetryPersistModeUpdate instanceof Boolean) {
        stateMachine.setRetryPersistModeUpdate(Boolean.TRUE.equals(isRetryPersistModeUpdate));
    }
    // customize if update last or append new compensateStateInstLog
    Object isCompensatePersistModeUpdate = node.get("IsCompensatePersistModeUpdate");
    if (isCompensatePersistModeUpdate instanceof Boolean) {
        stateMachine.setCompensatePersistModeUpdate(Boolean.TRUE.equals(isCompensatePersistModeUpdate));
    }
    Map<String, Object> statesNode = (Map<String, Object>) node.get("States");
    statesNode.forEach((stateName, value) -> {
        Map<String, Object> stateNode = (Map<String, Object>) value;
        String stateType = (String) stateNode.get("Type");
        StateParser<?> stateParser = StateParserFactory.getStateParser(stateType);
        if (stateParser == null) {
            throw new IllegalArgumentException("State Type [" + stateType + "] is not support");
        }
        State state = stateParser.parse(stateNode);
        if (state instanceof BaseState) {
            ((BaseState) state).setName(stateName);
        }
        if (stateMachine.getState(stateName) != null) {
            throw new IllegalArgumentException("State[name:" + stateName + "] is already exists");
        }
        stateMachine.putState(stateName, state);
    });
    Map<String, State> stateMap = stateMachine.getStates();
    for (State state : stateMap.values()) {
        if (state instanceof AbstractTaskState) {
            AbstractTaskState taskState = (AbstractTaskState) state;
            if (StringUtils.isNotBlank(taskState.getCompensateState())) {
                taskState.setForUpdate(true);
                State compState = stateMap.get(taskState.getCompensateState());
                if (compState instanceof AbstractTaskState) {
                    ((AbstractTaskState) compState).setForCompensation(true);
                }
            }
        }
    }
    return stateMachine;
}
Also used : BaseState(io.seata.saga.statelang.domain.impl.BaseState) StateMachineImpl(io.seata.saga.statelang.domain.impl.StateMachineImpl) AbstractTaskState(io.seata.saga.statelang.domain.impl.AbstractTaskState) State(io.seata.saga.statelang.domain.State) BaseState(io.seata.saga.statelang.domain.impl.BaseState) AbstractTaskState(io.seata.saga.statelang.domain.impl.AbstractTaskState) Map(java.util.Map) JsonParser(io.seata.saga.statelang.parser.JsonParser)

Aggregations

State (io.seata.saga.statelang.domain.State)8 EngineExecutionException (io.seata.saga.engine.exception.EngineExecutionException)5 StateMachine (io.seata.saga.statelang.domain.StateMachine)5 AbstractTaskState (io.seata.saga.statelang.domain.impl.AbstractTaskState)5 StateInstruction (io.seata.saga.engine.pcext.StateInstruction)3 StateInstance (io.seata.saga.statelang.domain.StateInstance)3 FrameworkException (io.seata.common.exception.FrameworkException)2 StateMachineConfig (io.seata.saga.engine.StateMachineConfig)2 CompensateSubStateMachineState (io.seata.saga.statelang.domain.CompensateSubStateMachineState)2 StateMachineInstance (io.seata.saga.statelang.domain.StateMachineInstance)2 SubStateMachine (io.seata.saga.statelang.domain.SubStateMachine)2 LoopStartStateImpl (io.seata.saga.statelang.domain.impl.LoopStartStateImpl)2 ForwardInvalidException (io.seata.saga.engine.exception.ForwardInvalidException)1 ChoiceStateHandler (io.seata.saga.engine.pcext.handlers.ChoiceStateHandler)1 CompensationTriggerStateHandler (io.seata.saga.engine.pcext.handlers.CompensationTriggerStateHandler)1 FailEndStateHandler (io.seata.saga.engine.pcext.handlers.FailEndStateHandler)1 LoopStartStateHandler (io.seata.saga.engine.pcext.handlers.LoopStartStateHandler)1 ScriptTaskStateHandler (io.seata.saga.engine.pcext.handlers.ScriptTaskStateHandler)1 ServiceTaskStateHandler (io.seata.saga.engine.pcext.handlers.ServiceTaskStateHandler)1 SucceedEndStateHandler (io.seata.saga.engine.pcext.handlers.SucceedEndStateHandler)1