use of io.seata.saga.engine.StateMachineConfig 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;
}
use of io.seata.saga.engine.StateMachineConfig in project seata by seata.
the class CompensationTriggerStateHandler method process.
@Override
public void process(ProcessContext context) throws EngineExecutionException {
StateInstruction instruction = context.getInstruction(StateInstruction.class);
StateMachineInstance stateMachineInstance = (StateMachineInstance) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_INST);
StateMachineConfig stateMachineConfig = (StateMachineConfig) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONFIG);
List<StateInstance> stateInstanceList = stateMachineInstance.getStateList();
if (CollectionUtils.isEmpty(stateInstanceList)) {
stateInstanceList = stateMachineConfig.getStateLogStore().queryStateInstanceListByMachineInstanceId(stateMachineInstance.getId());
}
List<StateInstance> stateListToBeCompensated = CompensationHolder.findStateInstListToBeCompensated(context, stateInstanceList);
if (CollectionUtils.isNotEmpty(stateListToBeCompensated)) {
// Clear exceptions that occur during forward execution
Exception e = (Exception) context.removeVariable(DomainConstants.VAR_NAME_CURRENT_EXCEPTION);
if (e != null) {
stateMachineInstance.setException(e);
}
Stack<StateInstance> stateStackToBeCompensated = CompensationHolder.getCurrent(context, true).getStateStackNeedCompensation();
stateStackToBeCompensated.addAll(stateListToBeCompensated);
// and the forward state should not be modified.
if (stateMachineInstance.getStatus() == null || ExecutionStatus.RU.equals(stateMachineInstance.getStatus())) {
stateMachineInstance.setStatus(ExecutionStatus.UN);
}
// Record the status of the state machine as "compensating", and the subsequent routing logic will route
// to the compensation state
stateMachineInstance.setCompensationStatus(ExecutionStatus.RU);
context.setVariable(DomainConstants.VAR_NAME_CURRENT_COMPEN_TRIGGER_STATE, instruction.getState(context));
} else {
EngineUtils.endStateMachine(context);
}
}
use of io.seata.saga.engine.StateMachineConfig in project seata by seata.
the class ScriptTaskStateHandler method process.
@Override
public void process(ProcessContext context) throws EngineExecutionException {
StateInstruction instruction = context.getInstruction(StateInstruction.class);
ScriptTaskStateImpl state = (ScriptTaskStateImpl) instruction.getState(context);
String scriptType = state.getScriptType();
String scriptContent = state.getScriptContent();
Object result;
try {
List<Object> input = (List<Object>) context.getVariable(DomainConstants.VAR_NAME_INPUT_PARAMS);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(">>>>>>>>>>>>>>>>>>>>>> Start to execute ScriptTaskState[{}], ScriptType[{}], Input:{}", state.getName(), scriptType, input);
}
StateMachineConfig stateMachineConfig = (StateMachineConfig) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONFIG);
ScriptEngine scriptEngine = getScriptEngineFromCache(scriptType, stateMachineConfig.getScriptEngineManager());
if (scriptEngine == null) {
throw new EngineExecutionException("No such ScriptType[" + scriptType + "]", FrameworkErrorCode.ObjectNotExists);
}
Bindings bindings = null;
Map<String, Object> inputMap = null;
if (CollectionUtils.isNotEmpty(input) && input.get(0) instanceof Map) {
inputMap = (Map<String, Object>) input.get(0);
}
List<Object> inputExps = state.getInput();
if (CollectionUtils.isNotEmpty(inputExps) && inputExps.get(0) instanceof Map) {
Map<String, Object> inputExpMap = (Map<String, Object>) inputExps.get(0);
if (inputExpMap.size() > 0) {
bindings = new SimpleBindings();
for (String property : inputExpMap.keySet()) {
if (inputMap != null && inputMap.containsKey(property)) {
bindings.put(property, inputMap.get(property));
} else {
// if we do not bind the null value property, groovy will throw MissingPropertyException
bindings.put(property, null);
}
}
}
}
if (bindings != null) {
result = scriptEngine.eval(scriptContent, bindings);
} else {
result = scriptEngine.eval(scriptContent);
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("<<<<<<<<<<<<<<<<<<<<<< ScriptTaskState[{}], ScriptType[{}], Execute finish. result: {}", state.getName(), scriptType, result);
}
if (result != null) {
((HierarchicalProcessContext) context).setVariableLocally(DomainConstants.VAR_NAME_OUTPUT_PARAMS, result);
}
} catch (Throwable e) {
LOGGER.error("<<<<<<<<<<<<<<<<<<<<<< ScriptTaskState[{}], ScriptTaskState[{}] Execute failed.", state.getName(), scriptType, e);
((HierarchicalProcessContext) context).setVariableLocally(DomainConstants.VAR_NAME_CURRENT_EXCEPTION, e);
EngineUtils.handleException(context, state, e);
}
}
use of io.seata.saga.engine.StateMachineConfig in project seata by seata.
the class DbAndReportTcStateLogStore method beginTransaction.
protected void beginTransaction(StateMachineInstance machineInstance, ProcessContext context) {
if (sagaTransactionalTemplate != null) {
StateMachineConfig stateMachineConfig = (StateMachineConfig) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONFIG);
TransactionInfo transactionInfo = new TransactionInfo();
transactionInfo.setTimeOut(stateMachineConfig.getTransOperationTimeout());
transactionInfo.setName(Constants.SAGA_TRANS_NAME_PREFIX + machineInstance.getStateMachine().getName());
try {
GlobalTransaction globalTransaction = sagaTransactionalTemplate.beginTransaction(transactionInfo);
machineInstance.setId(globalTransaction.getXid());
context.setVariable(DomainConstants.VAR_NAME_GLOBAL_TX, globalTransaction);
Map<String, Object> machineContext = machineInstance.getContext();
if (machineContext != null) {
machineContext.put(DomainConstants.VAR_NAME_GLOBAL_TX, globalTransaction);
}
} catch (ExecutionException e) {
String xid = null;
if (e.getTransaction() != null) {
xid = e.getTransaction().getXid();
}
throw new EngineExecutionException(e, e.getCode() + ", TransName:" + transactionInfo.getName() + ", XID: " + xid + ", Reason: " + e.getMessage(), FrameworkErrorCode.TransactionManagerError);
} finally {
if (Boolean.TRUE.equals(context.getVariable(DomainConstants.VAR_NAME_IS_ASYNC_EXECUTION))) {
RootContext.unbind();
RootContext.unbindBranchType();
}
}
}
}
use of io.seata.saga.engine.StateMachineConfig in project seata by seata.
the class DbAndReportTcStateLogStore method recordStateFinished.
@Override
public void recordStateFinished(StateInstance stateInstance, ProcessContext context) {
if (stateInstance != null) {
stateInstance.setSerializedOutputParams(paramsSerializer.serialize(stateInstance.getOutputParams()));
stateInstance.setSerializedException(exceptionSerializer.serialize(stateInstance.getException()));
executeUpdate(stateLogStoreSqls.getRecordStateFinishedSql(dbType), STATE_INSTANCE_TO_STATEMENT_FOR_UPDATE, stateInstance);
// A switch to skip branch report on branch success, in order to optimize performance
StateMachineConfig stateMachineConfig = (StateMachineConfig) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONFIG);
if (!(stateMachineConfig instanceof DbStateMachineConfig && !((DbStateMachineConfig) stateMachineConfig).isRmReportSuccessEnable() && ExecutionStatus.SU.equals(stateInstance.getStatus()))) {
branchReport(stateInstance, context);
}
}
}
Aggregations