Search in sources :

Example 16 with EngineExecutionException

use of io.seata.saga.engine.exception.EngineExecutionException 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 17 with EngineExecutionException

use of io.seata.saga.engine.exception.EngineExecutionException 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);
    }
}
Also used : StateMachineEngine(io.seata.saga.engine.StateMachineEngine) ApplicationContextAware(org.springframework.context.ApplicationContextAware) StateInstruction(io.seata.saga.engine.pcext.StateInstruction) HierarchicalProcessContext(io.seata.saga.proctrl.HierarchicalProcessContext) CompensateSubStateMachineState(io.seata.saga.statelang.domain.CompensateSubStateMachineState) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) ServiceTaskStateImpl(io.seata.saga.statelang.domain.impl.ServiceTaskStateImpl) ArrayList(java.util.ArrayList) List(java.util.List) StateMachineConfig(io.seata.saga.engine.StateMachineConfig) ServiceInvoker(io.seata.saga.engine.invoker.ServiceInvoker) StateInstance(io.seata.saga.statelang.domain.StateInstance)

Example 18 with EngineExecutionException

use of io.seata.saga.engine.exception.EngineExecutionException in project seata by seata.

the class ServiceTaskStateHandler method compensateSubStateMachine.

private Object compensateSubStateMachine(ProcessContext context, ServiceTaskState state, Object input, StateInstance stateInstance, StateMachineEngine engine) {
    String subStateMachineParentId = (String) context.getVariable(state.getName() + DomainConstants.VAR_NAME_SUB_MACHINE_PARENT_ID);
    if (StringUtils.isEmpty(subStateMachineParentId)) {
        throw new EngineExecutionException("sub statemachine parentId is required", FrameworkErrorCode.ObjectNotExists);
    }
    StateMachineConfig stateMachineConfig = (StateMachineConfig) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONFIG);
    List<StateMachineInstance> subInst = stateMachineConfig.getStateLogStore().queryStateMachineInstanceByParentId(subStateMachineParentId);
    if (CollectionUtils.isEmpty(subInst)) {
        throw new EngineExecutionException("cannot find sub statemachine instance by parentId:" + subStateMachineParentId, FrameworkErrorCode.ObjectNotExists);
    }
    String subStateMachineInstId = subInst.get(0).getId();
    if (LOGGER.isDebugEnabled()) {
        LOGGER.debug(">>>>>>>>>>>>>>>>>>>>>> Start to compensate sub statemachine [id:{}]", subStateMachineInstId);
    }
    Map<String, Object> startParams = new HashMap<>(0);
    if (input instanceof List) {
        List<Object> listInputParams = (List<Object>) input;
        if (listInputParams.size() > 0) {
            startParams = (Map<String, Object>) listInputParams.get(0);
        }
    } else if (input instanceof Map) {
        startParams = (Map<String, Object>) input;
    }
    StateMachineInstance compensateInst = engine.compensate(subStateMachineInstId, startParams);
    stateInstance.setStatus(compensateInst.getCompensationStatus());
    if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("<<<<<<<<<<<<<<<<<<<<<< Compensate sub statemachine [id:{}] finished with status[{}], " + "compensateState[{}]", subStateMachineInstId, compensateInst.getStatus(), compensateInst.getCompensationStatus());
    }
    return compensateInst.getEndParams();
}
Also used : HashMap(java.util.HashMap) StateMachineConfig(io.seata.saga.engine.StateMachineConfig) ArrayList(java.util.ArrayList) List(java.util.List) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) HashMap(java.util.HashMap) Map(java.util.Map) StateMachineInstance(io.seata.saga.statelang.domain.StateMachineInstance)

Example 19 with EngineExecutionException

use of io.seata.saga.engine.exception.EngineExecutionException in project seata by seata.

the class LoopTaskHandlerInterceptor method postProcess.

@Override
public void postProcess(ProcessContext context, Exception e) throws EngineExecutionException {
    if (context.hasVariable(DomainConstants.VAR_NAME_IS_LOOP_STATE)) {
        StateInstance stateInstance = (StateInstance) context.getVariable(DomainConstants.VAR_NAME_STATE_INST);
        if (null != stateInstance && !LoopContextHolder.getCurrent(context, true).isFailEnd()) {
            if (!ExecutionStatus.SU.equals(stateInstance.getStatus())) {
                LoopContextHolder.getCurrent(context, true).setFailEnd(true);
            }
        }
        Exception exp = (Exception) ((HierarchicalProcessContext) context).getVariableLocally(DomainConstants.VAR_NAME_CURRENT_EXCEPTION);
        if (exp == null) {
            exp = e;
        }
        if (null != e) {
            if (context.hasVariable(DomainConstants.LOOP_SEMAPHORE)) {
                Semaphore semaphore = (Semaphore) context.getVariable(DomainConstants.LOOP_SEMAPHORE);
                semaphore.release();
            }
        }
        if (null != exp) {
            LoopContextHolder.getCurrent(context, true).setFailEnd(true);
        } else {
            LoopContextHolder.getCurrent(context, true).getNrOfCompletedInstances().incrementAndGet();
        }
        LoopContextHolder.getCurrent(context, true).getNrOfActiveInstances().decrementAndGet();
    }
}
Also used : Semaphore(java.util.concurrent.Semaphore) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) StateInstance(io.seata.saga.statelang.domain.StateInstance)

Example 20 with EngineExecutionException

use of io.seata.saga.engine.exception.EngineExecutionException in project seata by seata.

the class SagaResourceManager method branchRollback.

/**
 * SAGA branch rollback
 *
 * @param branchType      the branch type
 * @param xid             Transaction id.
 * @param branchId        Branch id.
 * @param resourceId      Resource id.
 * @param applicationData Application data bind with this branch.
 * @return
 * @throws TransactionException
 */
@Override
public BranchStatus branchRollback(BranchType branchType, String xid, long branchId, String resourceId, String applicationData) throws TransactionException {
    try {
        StateMachineInstance stateMachineInstance = StateMachineEngineHolder.getStateMachineEngine().reloadStateMachineInstance(xid);
        if (stateMachineInstance == null) {
            return BranchStatus.PhaseTwo_Rollbacked;
        }
        if (RecoverStrategy.Forward.equals(stateMachineInstance.getStateMachine().getRecoverStrategy()) && (GlobalStatus.TimeoutRollbacking.name().equals(applicationData) || GlobalStatus.TimeoutRollbackRetrying.name().equals(applicationData))) {
            LOGGER.warn("Retry by custom recover strategy [Forward] on timeout, SAGA global[{}]", xid);
            return BranchStatus.PhaseTwo_CommitFailed_Retryable;
        }
        stateMachineInstance = StateMachineEngineHolder.getStateMachineEngine().compensate(xid, null);
        if (ExecutionStatus.SU.equals(stateMachineInstance.getCompensationStatus())) {
            return BranchStatus.PhaseTwo_Rollbacked;
        }
    } catch (EngineExecutionException e) {
        LOGGER.error("StateMachine compensate failed, xid: " + xid, e);
        // if StateMachineInstanceNotExists stop retry
        if (FrameworkErrorCode.StateMachineInstanceNotExists.equals(e.getErrcode())) {
            return BranchStatus.PhaseTwo_Rollbacked;
        }
    } catch (Exception e) {
        LOGGER.error("StateMachine compensate failed, xid: " + xid, e);
    }
    return BranchStatus.PhaseTwo_RollbackFailed_Retryable;
}
Also used : EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) TransactionException(io.seata.core.exception.TransactionException) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) ForwardInvalidException(io.seata.saga.engine.exception.ForwardInvalidException) StateMachineInstance(io.seata.saga.statelang.domain.StateMachineInstance)

Aggregations

EngineExecutionException (io.seata.saga.engine.exception.EngineExecutionException)34 StateMachineInstance (io.seata.saga.statelang.domain.StateMachineInstance)20 StateMachineConfig (io.seata.saga.engine.StateMachineConfig)14 StateInstruction (io.seata.saga.engine.pcext.StateInstruction)14 StateInstance (io.seata.saga.statelang.domain.StateInstance)11 Map (java.util.Map)10 GlobalTransaction (io.seata.tm.api.GlobalTransaction)6 ArrayList (java.util.ArrayList)6 HierarchicalProcessContext (io.seata.saga.proctrl.HierarchicalProcessContext)5 ServiceTaskStateImpl (io.seata.saga.statelang.domain.impl.ServiceTaskStateImpl)5 Date (java.util.Date)5 List (java.util.List)5 TransactionException (io.seata.core.exception.TransactionException)4 ForwardInvalidException (io.seata.saga.engine.exception.ForwardInvalidException)4 ProcessContext (io.seata.saga.proctrl.ProcessContext)4 ExecutionStatus (io.seata.saga.statelang.domain.ExecutionStatus)4 State (io.seata.saga.statelang.domain.State)4 StateMachine (io.seata.saga.statelang.domain.StateMachine)4 ExecutionException (io.seata.tm.api.TransactionalExecutor.ExecutionException)4 HashMap (java.util.HashMap)4