use of io.seata.saga.proctrl.HierarchicalProcessContext in project seata by seata.
the class ServiceTaskStateHandler method process.
@Override
public void process(ProcessContext context) throws EngineExecutionException {
StateInstruction instruction = context.getInstruction(StateInstruction.class);
ServiceTaskStateImpl state = (ServiceTaskStateImpl) instruction.getState(context);
String serviceName = state.getServiceName();
String methodName = state.getServiceMethod();
StateInstance stateInstance = (StateInstance) context.getVariable(DomainConstants.VAR_NAME_STATE_INST);
Object result;
try {
List<Object> input = (List<Object>) context.getVariable(DomainConstants.VAR_NAME_INPUT_PARAMS);
// Set the current task execution status to RU (Running)
stateInstance.setStatus(ExecutionStatus.RU);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(">>>>>>>>>>>>>>>>>>>>>> Start to execute State[{}], ServiceName[{}], Method[{}], Input:{}", state.getName(), serviceName, methodName, input);
}
if (state instanceof CompensateSubStateMachineState) {
// If it is the compensation of the substate machine,
// directly call the state machine's compensate method
result = compensateSubStateMachine(context, state, input, stateInstance, (StateMachineEngine) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_ENGINE));
} else {
StateMachineConfig stateMachineConfig = (StateMachineConfig) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONFIG);
ServiceInvoker serviceInvoker = stateMachineConfig.getServiceInvokerManager().getServiceInvoker(state.getServiceType());
if (serviceInvoker == null) {
throw new EngineExecutionException("No such ServiceInvoker[" + state.getServiceType() + "]", FrameworkErrorCode.ObjectNotExists);
}
if (serviceInvoker instanceof ApplicationContextAware) {
((ApplicationContextAware) serviceInvoker).setApplicationContext(stateMachineConfig.getApplicationContext());
}
result = serviceInvoker.invoke(state, input.toArray());
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("<<<<<<<<<<<<<<<<<<<<<< State[{}], ServiceName[{}], Method[{}] Execute finish. result: {}", state.getName(), serviceName, methodName, result);
}
if (result != null) {
stateInstance.setOutputParams(result);
((HierarchicalProcessContext) context).setVariableLocally(DomainConstants.VAR_NAME_OUTPUT_PARAMS, result);
}
} catch (Throwable e) {
LOGGER.error("<<<<<<<<<<<<<<<<<<<<<< State[{}], ServiceName[{}], Method[{}] Execute failed.", state.getName(), serviceName, methodName, e);
((HierarchicalProcessContext) context).setVariableLocally(DomainConstants.VAR_NAME_CURRENT_EXCEPTION, e);
EngineUtils.handleException(context, state, e);
}
}
use of io.seata.saga.proctrl.HierarchicalProcessContext in project seata by seata.
the class LoopStartStateHandler 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);
instruction.setTemporaryState(null);
Loop loop = LoopTaskUtils.getLoopConfig(context, instruction.getState(context));
LoopContextHolder loopContextHolder = LoopContextHolder.getCurrent(context, true);
Semaphore semaphore = null;
int maxInstances = 0;
List<ProcessContext> loopContextList = new ArrayList<>();
if (null != loop) {
if (!stateMachineConfig.isEnableAsync() || null == stateMachineConfig.getAsyncProcessCtrlEventPublisher()) {
throw new EngineExecutionException("Asynchronous start is disabled. Loop execution will run asynchronous, please set " + "StateMachineConfig.enableAsync=true first.", FrameworkErrorCode.AsynchronousStartDisabled);
}
int totalInstances;
if (DomainConstants.OPERATION_NAME_FORWARD.equals(context.getVariable(DomainConstants.VAR_NAME_OPERATION_NAME))) {
LoopTaskUtils.reloadLoopContext(context, instruction.getState(context).getName());
totalInstances = loopContextHolder.getNrOfInstances().get() - loopContextHolder.getNrOfCompletedInstances().get();
} else {
LoopTaskUtils.createLoopCounterContext(context);
totalInstances = loopContextHolder.getNrOfInstances().get();
}
maxInstances = Math.min(loop.getParallel(), totalInstances);
semaphore = new Semaphore(maxInstances);
context.setVariable(DomainConstants.LOOP_SEMAPHORE, semaphore);
context.setVariable(DomainConstants.VAR_NAME_IS_LOOP_STATE, true);
// publish loop tasks
for (int i = 0; i < totalInstances; i++) {
try {
semaphore.acquire();
ProcessContextImpl tempContext;
// fail end inst should be forward without completion condition check
if (!loopContextHolder.getForwardCounterStack().isEmpty()) {
int failEndLoopCounter = loopContextHolder.getForwardCounterStack().pop();
tempContext = (ProcessContextImpl) LoopTaskUtils.createLoopEventContext(context, failEndLoopCounter);
} else if (loopContextHolder.isFailEnd() || LoopTaskUtils.isCompletionConditionSatisfied(context)) {
semaphore.release();
break;
} else {
tempContext = (ProcessContextImpl) LoopTaskUtils.createLoopEventContext(context, -1);
}
if (DomainConstants.OPERATION_NAME_FORWARD.equals(context.getVariable(DomainConstants.VAR_NAME_OPERATION_NAME))) {
((HierarchicalProcessContext) context).setVariableLocally(DomainConstants.VAR_NAME_IS_FOR_SUB_STATMACHINE_FORWARD, LoopTaskUtils.isForSubStateMachineForward(tempContext));
}
stateMachineConfig.getAsyncProcessCtrlEventPublisher().publish(tempContext);
loopContextHolder.getNrOfActiveInstances().incrementAndGet();
loopContextList.add(tempContext);
} catch (InterruptedException e) {
LOGGER.error("try execute loop task for State: [{}] is interrupted, message: [{}]", instruction.getStateName(), e.getMessage());
throw new EngineExecutionException(e);
}
}
} else {
LOGGER.warn("Loop config of State [{}] is illegal, will execute as normal", instruction.getStateName());
instruction.setTemporaryState(instruction.getState(context));
}
try {
if (null != semaphore) {
boolean isFinished = false;
while (!isFinished) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("wait {}ms for loop state [{}] finish", AWAIT_TIMEOUT, instruction.getStateName());
}
isFinished = semaphore.tryAcquire(maxInstances, AWAIT_TIMEOUT, TimeUnit.MILLISECONDS);
}
if (loopContextList.size() > 0) {
LoopTaskUtils.putContextToParent(context, loopContextList, instruction.getState(context));
}
}
} catch (InterruptedException e) {
LOGGER.error("State: [{}] wait loop execution complete is interrupted, message: [{}]", instruction.getStateName(), e.getMessage());
throw new EngineExecutionException(e);
} finally {
context.removeVariable(DomainConstants.LOOP_SEMAPHORE);
context.removeVariable(DomainConstants.VAR_NAME_IS_LOOP_STATE);
LoopContextHolder.clearCurrent(context);
}
if (loopContextHolder.isFailEnd()) {
String currentExceptionRoute = LoopTaskUtils.decideCurrentExceptionRoute(loopContextList, stateMachineInstance.getStateMachine());
if (StringUtils.isNotBlank(currentExceptionRoute)) {
((HierarchicalProcessContext) context).setVariableLocally(DomainConstants.VAR_NAME_CURRENT_EXCEPTION_ROUTE, currentExceptionRoute);
} else {
for (ProcessContext processContext : loopContextList) {
if (processContext.hasVariable(DomainConstants.VAR_NAME_CURRENT_EXCEPTION)) {
Exception exception = (Exception) processContext.getVariable(DomainConstants.VAR_NAME_CURRENT_EXCEPTION);
EngineUtils.failStateMachine(context, exception);
break;
}
}
}
}
}
use of io.seata.saga.proctrl.HierarchicalProcessContext in project seata by seata.
the class ScriptTaskHandlerInterceptor method preProcess.
@Override
public void preProcess(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);
Map<String, Object> contextVariables = (Map<String, Object>) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONTEXT);
ScriptTaskStateImpl state = (ScriptTaskStateImpl) instruction.getState(context);
List<Object> serviceInputParams = null;
if (contextVariables != null) {
try {
serviceInputParams = ParameterUtils.createInputParams(stateMachineConfig.getExpressionFactoryManager(), null, state, contextVariables);
} catch (Exception e) {
String message = "Task [" + state.getName() + "] input parameters assign failed, please check 'Input' expression:" + e.getMessage();
EngineExecutionException exception = ExceptionUtils.createEngineExecutionException(e, FrameworkErrorCode.VariablesAssignError, message, stateMachineInstance, state.getName());
EngineUtils.failStateMachine(context, exception);
throw exception;
}
}
((HierarchicalProcessContext) context).setVariableLocally(DomainConstants.VAR_NAME_INPUT_PARAMS, serviceInputParams);
}
Aggregations