use of io.seata.saga.engine.pcext.StateInstruction in project seata by seata.
the class FailEndStateHandler method process.
@Override
public void process(ProcessContext context) throws EngineExecutionException {
context.setVariable(DomainConstants.VAR_NAME_FAIL_END_STATE_FLAG, true);
StateInstruction instruction = context.getInstruction(StateInstruction.class);
FailEndState state = (FailEndState) instruction.getState(context);
Map<String, Object> contextVariables = (Map<String, Object>) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONTEXT);
contextVariables.put(DomainConstants.VAR_NAME_STATEMACHINE_ERROR_CODE, state.getErrorCode());
contextVariables.put(DomainConstants.VAR_NAME_STATEMACHINE_ERROR_MSG, state.getMessage());
}
use of io.seata.saga.engine.pcext.StateInstruction 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.pcext.StateInstruction in project seata by seata.
the class ProcessCtrlStateMachineEngine method compensateInternal.
public StateMachineInstance compensateInternal(String stateMachineInstId, Map<String, Object> replaceParams, boolean async, AsyncCallback callback) throws EngineExecutionException {
StateMachineInstance stateMachineInstance = reloadStateMachineInstance(stateMachineInstId);
if (stateMachineInstance == null) {
throw new EngineExecutionException("StateMachineInstance is not exits", FrameworkErrorCode.StateMachineInstanceNotExists);
}
if (ExecutionStatus.SU.equals(stateMachineInstance.getCompensationStatus())) {
return stateMachineInstance;
}
if (stateMachineInstance.getCompensationStatus() != null) {
ExecutionStatus[] denyStatus = new ExecutionStatus[] { ExecutionStatus.SU };
checkStatus(stateMachineInstance, null, denyStatus, null, stateMachineInstance.getCompensationStatus(), "compensate");
}
if (replaceParams != null) {
stateMachineInstance.getEndParams().putAll(replaceParams);
}
ProcessContextBuilder contextBuilder = ProcessContextBuilder.create().withProcessType(ProcessType.STATE_LANG).withOperationName(DomainConstants.OPERATION_NAME_COMPENSATE).withAsyncCallback(callback).withStateMachineInstance(stateMachineInstance).withStateMachineConfig(getStateMachineConfig()).withStateMachineEngine(this);
contextBuilder.withIsAsyncExecution(async);
ProcessContext context = contextBuilder.build();
Map<String, Object> contextVariables = getStateMachineContextVariables(stateMachineInstance);
if (replaceParams != null) {
contextVariables.putAll(replaceParams);
}
putBusinesskeyToContextariables(stateMachineInstance, contextVariables);
ConcurrentHashMap<String, Object> concurrentContextVariables = new ConcurrentHashMap<>(contextVariables.size());
nullSafeCopy(contextVariables, concurrentContextVariables);
context.setVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONTEXT, concurrentContextVariables);
stateMachineInstance.setContext(concurrentContextVariables);
CompensationTriggerStateImpl tempCompensationTriggerState = new CompensationTriggerStateImpl();
tempCompensationTriggerState.setStateMachine(stateMachineInstance.getStateMachine());
stateMachineInstance.setRunning(true);
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Operation [compensate] start. stateMachineInstance[id:" + stateMachineInstance.getId() + "]");
}
if (stateMachineInstance.getStateMachine().isPersist()) {
stateMachineConfig.getStateLogStore().recordStateMachineRestarted(stateMachineInstance, context);
}
try {
StateInstruction inst = new StateInstruction();
inst.setTenantId(stateMachineInstance.getTenantId());
inst.setStateMachineName(stateMachineInstance.getStateMachine().getName());
inst.setTemporaryState(tempCompensationTriggerState);
context.setInstruction(inst);
if (async) {
stateMachineConfig.getAsyncProcessCtrlEventPublisher().publish(context);
} else {
stateMachineConfig.getProcessCtrlEventPublisher().publish(context);
}
} catch (EngineExecutionException e) {
LOGGER.error("Operation [compensate] failed", e);
throw e;
}
return stateMachineInstance;
}
use of io.seata.saga.engine.pcext.StateInstruction in project seata by seata.
the class SubStateMachineHandler method process.
@Override
public void process(ProcessContext context) throws EngineExecutionException {
StateInstruction instruction = context.getInstruction(StateInstruction.class);
SubStateMachineImpl subStateMachine = (SubStateMachineImpl) instruction.getState(context);
StateMachineEngine engine = (StateMachineEngine) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_ENGINE);
StateMachineInstance stateMachineInstance = (StateMachineInstance) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_INST);
StateInstance stateInstance = (StateInstance) context.getVariable(DomainConstants.VAR_NAME_STATE_INST);
Object inputParamsObj = context.getVariable(DomainConstants.VAR_NAME_INPUT_PARAMS);
Map<String, Object> startParams = new HashMap<>(0);
if (inputParamsObj instanceof List) {
List<Object> listInputParams = (List<Object>) inputParamsObj;
if (listInputParams.size() > 0) {
startParams = (Map<String, Object>) listInputParams.get(0);
}
} else if (inputParamsObj instanceof Map) {
startParams = (Map<String, Object>) inputParamsObj;
}
startParams.put(DomainConstants.VAR_NAME_PARENT_ID, EngineUtils.generateParentId(stateInstance));
try {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(">>>>>>>>>>>>>>>>>>>>>> Start to execute SubStateMachine [{}] by state[{}]", subStateMachine.getStateMachineName(), subStateMachine.getName());
}
StateMachineInstance subStateMachineInstance = callSubStateMachine(startParams, engine, context, stateInstance, subStateMachine);
Map<String, Object> outputParams = subStateMachineInstance.getEndParams();
boolean isForward = DomainConstants.OPERATION_NAME_FORWARD.equals(context.getVariable(DomainConstants.VAR_NAME_OPERATION_NAME));
ExecutionStatus callSubMachineStatus = decideStatus(subStateMachineInstance, isForward);
stateInstance.setStatus(callSubMachineStatus);
outputParams.put(DomainConstants.VAR_NAME_SUB_STATEMACHINE_EXEC_STATUE, callSubMachineStatus.toString());
context.setVariable(DomainConstants.VAR_NAME_OUTPUT_PARAMS, outputParams);
stateInstance.setOutputParams(outputParams);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("<<<<<<<<<<<<<<<<<<<<<< SubStateMachine[{}] execute finish with status[{}], compensateStatus[{}]", subStateMachine.getStateMachineName(), subStateMachineInstance.getStatus(), subStateMachineInstance.getCompensationStatus());
}
} catch (Exception e) {
LOGGER.error("SubStateMachine[{}] execute failed by state[name:{}]", subStateMachine.getStateMachineName(), subStateMachine.getName(), e);
if (e instanceof ForwardInvalidException) {
String retriedId = stateInstance.getStateIdRetriedFor();
StateInstance stateToBeRetried = null;
for (StateInstance stateInst : stateMachineInstance.getStateList()) {
if (retriedId.equals(stateInst.getId())) {
stateToBeRetried = stateInst;
break;
}
}
if (stateToBeRetried != null) {
stateInstance.setStatus(stateToBeRetried.getStatus());
}
}
context.setVariable(DomainConstants.VAR_NAME_CURRENT_EXCEPTION, e);
EngineUtils.handleException(context, subStateMachine, e);
}
}
use of io.seata.saga.engine.pcext.StateInstruction in project seata by seata.
the class LoopTaskHandlerInterceptor method preProcess.
@Override
public void preProcess(ProcessContext context) throws EngineExecutionException {
if (context.hasVariable(DomainConstants.VAR_NAME_IS_LOOP_STATE)) {
StateInstruction instruction = context.getInstruction(StateInstruction.class);
AbstractTaskState currentState = (AbstractTaskState) instruction.getState(context);
int loopCounter;
Loop loop;
// get loop config
if (context.hasVariable(DomainConstants.VAR_NAME_CURRENT_COMPEN_TRIGGER_STATE)) {
// compensate condition should get stateToBeCompensated 's config
CompensationHolder compensationHolder = CompensationHolder.getCurrent(context, true);
StateInstance stateToBeCompensated = compensationHolder.getStatesNeedCompensation().get(currentState.getName());
AbstractTaskState compensateState = (AbstractTaskState) stateToBeCompensated.getStateMachineInstance().getStateMachine().getState(EngineUtils.getOriginStateName(stateToBeCompensated));
loop = compensateState.getLoop();
loopCounter = LoopTaskUtils.reloadLoopCounter(stateToBeCompensated.getName());
} else {
loop = currentState.getLoop();
loopCounter = (int) context.getVariable(DomainConstants.LOOP_COUNTER);
}
Collection collection = LoopContextHolder.getCurrent(context, true).getCollection();
Map<String, Object> contextVariables = (Map<String, Object>) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONTEXT);
Map<String, Object> copyContextVariables = new ConcurrentHashMap<>(contextVariables);
copyContextVariables.put(loop.getElementIndexName(), loopCounter);
copyContextVariables.put(loop.getElementVariableName(), iterator(collection, loopCounter));
((HierarchicalProcessContext) context).setVariableLocally(DomainConstants.VAR_NAME_STATEMACHINE_CONTEXT, copyContextVariables);
}
}
Aggregations