Search in sources :

Example 6 with StateMachine

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

the class StateParserTests method testParser.

@Test
public void testParser() throws IOException {
    ClassPathResource resource = new ClassPathResource("statelang/simple_statemachine.json");
    String json = io.seata.saga.statelang.parser.utils.IOUtils.toString(resource.getInputStream(), "UTF-8");
    StateMachine stateMachine = StateMachineParserFactory.getStateMachineParser(null).parse(json);
    stateMachine.setGmtCreate(new Date());
    Assertions.assertNotNull(stateMachine);
    JsonParser jsonParser = JsonParserFactory.getJsonParser("jackson");
    String outputJson = jsonParser.toJsonString(stateMachine, true);
    System.out.println(outputJson);
    JsonParser fastjsonParser = JsonParserFactory.getJsonParser("fastjson");
    String fastjsonOutputJson = fastjsonParser.toJsonString(stateMachine, true);
    System.out.println(fastjsonOutputJson);
    Assertions.assertEquals(stateMachine.getName(), "simpleTestStateMachine");
    Assertions.assertTrue(stateMachine.getStates().size() > 0);
}
Also used : StateMachine(io.seata.saga.statelang.domain.StateMachine) ClassPathResource(org.springframework.core.io.ClassPathResource) Date(java.util.Date) Test(org.junit.jupiter.api.Test)

Example 7 with StateMachine

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

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

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

the class StateMachineRepositoryImpl method getStateMachineById.

@Override
public StateMachine getStateMachineById(String stateMachineId) {
    Item item = CollectionUtils.computeIfAbsent(stateMachineMapById, stateMachineId, key -> new Item());
    if (item.getValue() == null && stateLangStore != null) {
        synchronized (item) {
            if (item.getValue() == null && stateLangStore != null) {
                StateMachine stateMachine = stateLangStore.getStateMachineById(stateMachineId);
                if (stateMachine != null) {
                    StateMachine parsedStatMachine = StateMachineParserFactory.getStateMachineParser(jsonParserName).parse(stateMachine.getContent());
                    if (parsedStatMachine == null) {
                        throw new RuntimeException("Parse State Language failed, stateMachineId:" + stateMachine.getId() + ", name:" + stateMachine.getName());
                    }
                    stateMachine.setStartState(parsedStatMachine.getStartState());
                    stateMachine.getStates().putAll(parsedStatMachine.getStates());
                    item.setValue(stateMachine);
                    stateMachineMapById.put(stateMachine.getName() + "_" + stateMachine.getTenantId(), item);
                }
            }
        }
    }
    return item.getValue();
}
Also used : StateMachine(io.seata.saga.statelang.domain.StateMachine)

Example 10 with StateMachine

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

the class StateMachineRepositoryImpl method registryStateMachine.

@Override
public StateMachine registryStateMachine(StateMachine stateMachine) {
    String stateMachineName = stateMachine.getName();
    String tenantId = stateMachine.getTenantId();
    if (stateLangStore != null) {
        StateMachine oldStateMachine = stateLangStore.getLastVersionStateMachine(stateMachineName, tenantId);
        if (oldStateMachine != null) {
            byte[] oldBytesContent = null;
            byte[] bytesContent = null;
            try {
                oldBytesContent = oldStateMachine.getContent().getBytes(charset);
                bytesContent = stateMachine.getContent().getBytes(charset);
            } catch (UnsupportedEncodingException e) {
                LOGGER.error(e.getMessage(), e);
            }
            if (Arrays.equals(bytesContent, oldBytesContent) && stateMachine.getVersion() != null && stateMachine.getVersion().equals(oldStateMachine.getVersion())) {
                LOGGER.info("StateMachine[{}] is already exist a same version", stateMachineName);
                stateMachine.setId(oldStateMachine.getId());
                stateMachine.setGmtCreate(oldStateMachine.getGmtCreate());
                Item item = new Item(stateMachine);
                stateMachineMapByNameAndTenant.put(stateMachineName + "_" + tenantId, item);
                stateMachineMapById.put(stateMachine.getId(), item);
                return stateMachine;
            }
        }
        if (StringUtils.isBlank(stateMachine.getId())) {
            stateMachine.setId(seqGenerator.generate(DomainConstants.SEQ_ENTITY_STATE_MACHINE));
        }
        stateMachine.setGmtCreate(new Date());
        stateLangStore.storeStateMachine(stateMachine);
    }
    if (StringUtils.isBlank(stateMachine.getId())) {
        stateMachine.setId(seqGenerator.generate(DomainConstants.SEQ_ENTITY_STATE_MACHINE));
    }
    Item item = new Item(stateMachine);
    stateMachineMapByNameAndTenant.put(stateMachineName + "_" + tenantId, item);
    stateMachineMapById.put(stateMachine.getId(), item);
    return stateMachine;
}
Also used : StateMachine(io.seata.saga.statelang.domain.StateMachine) UnsupportedEncodingException(java.io.UnsupportedEncodingException) Date(java.util.Date)

Aggregations

StateMachine (io.seata.saga.statelang.domain.StateMachine)13 EngineExecutionException (io.seata.saga.engine.exception.EngineExecutionException)6 State (io.seata.saga.statelang.domain.State)5 StateInstance (io.seata.saga.statelang.domain.StateInstance)4 StateInstruction (io.seata.saga.engine.pcext.StateInstruction)3 AbstractTaskState (io.seata.saga.statelang.domain.impl.AbstractTaskState)3 Date (java.util.Date)3 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 FrameworkException (io.seata.common.exception.FrameworkException)1 DefaultStateMachineConfig (io.seata.saga.engine.impl.DefaultStateMachineConfig)1 EndStateRouter (io.seata.saga.engine.pcext.routers.EndStateRouter)1 TaskStateRouter (io.seata.saga.engine.pcext.routers.TaskStateRouter)1 HierarchicalProcessContext (io.seata.saga.proctrl.HierarchicalProcessContext)1 Instruction (io.seata.saga.proctrl.Instruction)1 LoopStartStateImpl (io.seata.saga.statelang.domain.impl.LoopStartStateImpl)1 ServiceTaskStateImpl (io.seata.saga.statelang.domain.impl.ServiceTaskStateImpl)1 StateMachineInstanceImpl (io.seata.saga.statelang.domain.impl.StateMachineInstanceImpl)1