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);
}
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;
}
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;
}
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();
}
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;
}
Aggregations