Search in sources :

Example 21 with StateInstance

use of io.seata.saga.statelang.domain.StateInstance in project seata by seata.

the class DefaultStatusDecisionStrategy method setMachineStatusBasedOnStateListAndException.

/**
 * set machine status based on state list
 *
 * @param stateMachineInstance
 * @param stateList
 * @return
 */
public static void setMachineStatusBasedOnStateListAndException(StateMachineInstance stateMachineInstance, List<StateInstance> stateList, Exception exp) {
    boolean hasSetStatus = false;
    boolean hasSuccessUpdateService = false;
    if (CollectionUtils.isNotEmpty(stateList)) {
        boolean hasUnsuccessService = false;
        for (int i = stateList.size() - 1; i >= 0; i--) {
            StateInstance stateInstance = stateList.get(i);
            if (stateInstance.isIgnoreStatus() || stateInstance.isForCompensation()) {
                continue;
            }
            if (ExecutionStatus.UN.equals(stateInstance.getStatus())) {
                stateMachineInstance.setStatus(ExecutionStatus.UN);
                hasSetStatus = true;
            } else if (ExecutionStatus.SU.equals(stateInstance.getStatus())) {
                if (DomainConstants.STATE_TYPE_SERVICE_TASK.equals(stateInstance.getType())) {
                    if (stateInstance.isForUpdate() && !stateInstance.isForCompensation()) {
                        hasSuccessUpdateService = true;
                    }
                }
            } else if (ExecutionStatus.SK.equals(stateInstance.getStatus())) {
            // ignore
            } else {
                hasUnsuccessService = true;
            }
        }
        if (!hasSetStatus && hasUnsuccessService) {
            if (hasSuccessUpdateService) {
                stateMachineInstance.setStatus(ExecutionStatus.UN);
            } else {
                stateMachineInstance.setStatus(ExecutionStatus.FA);
            }
            hasSetStatus = true;
        }
    }
    if (!hasSetStatus) {
        setMachineStatusBasedOnException(stateMachineInstance, exp, hasSuccessUpdateService);
    }
}
Also used : StateInstance(io.seata.saga.statelang.domain.StateInstance)

Example 22 with StateInstance

use of io.seata.saga.statelang.domain.StateInstance in project seata by seata.

the class DbAndReportTcStateLogStore method generateRetryStateInstanceId.

/**
 * generate retry state instance id based on original state instance id
 * ${originalStateInstanceId}.${retryCount}
 * @param stateInstance
 * @return
 */
private String generateRetryStateInstanceId(StateInstance stateInstance) {
    String originalStateInstId = stateInstance.getStateIdRetriedFor();
    int maxIndex = 1;
    Map<String, StateInstance> stateInstanceMap = stateInstance.getStateMachineInstance().getStateMap();
    StateInstance originalStateInst = stateInstanceMap.get(stateInstance.getStateIdRetriedFor());
    while (StringUtils.hasLength(originalStateInst.getStateIdRetriedFor())) {
        originalStateInst = stateInstanceMap.get(originalStateInst.getStateIdRetriedFor());
        int idIndex = getIdIndex(originalStateInst.getId(), ".");
        maxIndex = idIndex > maxIndex ? idIndex : maxIndex;
        maxIndex++;
    }
    if (originalStateInst != null) {
        originalStateInstId = originalStateInst.getId();
    }
    return originalStateInstId + "." + maxIndex;
}
Also used : StateInstance(io.seata.saga.statelang.domain.StateInstance)

Example 23 with StateInstance

use of io.seata.saga.statelang.domain.StateInstance in project seata by seata.

the class DbAndReportTcStateLogStore method getStateMachineInstance.

@Override
public StateMachineInstance getStateMachineInstance(String stateMachineInstanceId) {
    StateMachineInstance stateMachineInstance = selectOne(stateLogStoreSqls.getGetStateMachineInstanceByIdSql(dbType), RESULT_SET_TO_STATE_MACHINE_INSTANCE, stateMachineInstanceId);
    if (stateMachineInstance == null) {
        return null;
    }
    List<StateInstance> stateInstanceList = queryStateInstanceListByMachineInstanceId(stateMachineInstanceId);
    for (StateInstance stateInstance : stateInstanceList) {
        stateMachineInstance.putStateInstance(stateInstance.getId(), stateInstance);
    }
    deserializeParamsAndException(stateMachineInstance);
    return stateMachineInstance;
}
Also used : StateMachineInstance(io.seata.saga.statelang.domain.StateMachineInstance) StateInstance(io.seata.saga.statelang.domain.StateInstance)

Example 24 with StateInstance

use of io.seata.saga.statelang.domain.StateInstance in project seata by seata.

the class DbAndReportTcStateLogStore method branchReport.

protected void branchReport(StateInstance stateInstance, ProcessContext context) {
    if (sagaTransactionalTemplate != null) {
        StateMachineConfig stateMachineConfig = (StateMachineConfig) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONFIG);
        if (stateMachineConfig instanceof DbStateMachineConfig && !((DbStateMachineConfig) stateMachineConfig).isSagaBranchRegisterEnable()) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("sagaBranchRegisterEnable = false, skip branch report. state[" + stateInstance.getName() + "]");
            }
            return;
        }
        BranchStatus branchStatus = null;
        // find out the original state instance, only the original state instance is registered on the server, and its status should
        // be reported.
        StateInstance originalStateInst = null;
        if (StringUtils.hasLength(stateInstance.getStateIdRetriedFor())) {
            if (isUpdateMode(stateInstance, context)) {
                originalStateInst = stateInstance;
            } else {
                originalStateInst = findOutOriginalStateInstanceOfRetryState(stateInstance);
            }
            if (ExecutionStatus.SU.equals(stateInstance.getStatus())) {
                branchStatus = BranchStatus.PhaseTwo_Committed;
            } else if (ExecutionStatus.FA.equals(stateInstance.getStatus()) || ExecutionStatus.UN.equals(stateInstance.getStatus())) {
                branchStatus = BranchStatus.PhaseOne_Failed;
            } else {
                branchStatus = BranchStatus.Unknown;
            }
        } else if (StringUtils.hasLength(stateInstance.getStateIdCompensatedFor())) {
            if (isUpdateMode(stateInstance, context)) {
                originalStateInst = stateInstance.getStateMachineInstance().getStateMap().get(stateInstance.getStateIdCompensatedFor());
            } else {
                originalStateInst = findOutOriginalStateInstanceOfCompensateState(stateInstance);
            }
        }
        if (originalStateInst == null) {
            originalStateInst = stateInstance;
        }
        if (branchStatus == null) {
            if (ExecutionStatus.SU.equals(originalStateInst.getStatus()) && originalStateInst.getCompensationStatus() == null) {
                branchStatus = BranchStatus.PhaseTwo_Committed;
            } else if (ExecutionStatus.SU.equals(originalStateInst.getCompensationStatus())) {
                branchStatus = BranchStatus.PhaseTwo_Rollbacked;
            } else if (ExecutionStatus.FA.equals(originalStateInst.getCompensationStatus()) || ExecutionStatus.UN.equals(originalStateInst.getCompensationStatus())) {
                branchStatus = BranchStatus.PhaseTwo_RollbackFailed_Retryable;
            } else if ((ExecutionStatus.FA.equals(originalStateInst.getStatus()) || ExecutionStatus.UN.equals(originalStateInst.getStatus())) && originalStateInst.getCompensationStatus() == null) {
                branchStatus = BranchStatus.PhaseOne_Failed;
            } else {
                branchStatus = BranchStatus.Unknown;
            }
        }
        try {
            StateMachineInstance machineInstance = stateInstance.getStateMachineInstance();
            GlobalTransaction globalTransaction = getGlobalTransaction(machineInstance, context);
            if (globalTransaction == null) {
                throw new EngineExecutionException("Global transaction is not exists", FrameworkErrorCode.ObjectNotExists);
            }
            sagaTransactionalTemplate.branchReport(globalTransaction.getXid(), Long.parseLong(originalStateInst.getId()), branchStatus, null);
        } catch (TransactionException e) {
            LOGGER.error("Report branch status to server error: {}, StateMachine:{}, StateName:{}, XID: {}, branchId: {}, branchStatus:{}," + " Reason:{} ", e.getCode(), originalStateInst.getStateMachineInstance().getStateMachine().getName(), originalStateInst.getName(), originalStateInst.getStateMachineInstance().getId(), originalStateInst.getId(), branchStatus, e.getMessage(), e);
        } catch (ExecutionException e) {
            LOGGER.error("Report branch status to server error: {}, StateMachine:{}, StateName:{}, XID: {}, branchId: {}, branchStatus:{}," + " Reason:{} ", e.getCode(), originalStateInst.getStateMachineInstance().getStateMachine().getName(), originalStateInst.getName(), originalStateInst.getStateMachineInstance().getId(), originalStateInst.getId(), branchStatus, e.getMessage(), e);
        }
    }
}
Also used : TransactionException(io.seata.core.exception.TransactionException) GlobalTransaction(io.seata.tm.api.GlobalTransaction) DbStateMachineConfig(io.seata.saga.engine.config.DbStateMachineConfig) DefaultStateMachineConfig(io.seata.saga.engine.impl.DefaultStateMachineConfig) StateMachineConfig(io.seata.saga.engine.StateMachineConfig) BranchStatus(io.seata.core.model.BranchStatus) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) ExecutionException(io.seata.tm.api.TransactionalExecutor.ExecutionException) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) DbStateMachineConfig(io.seata.saga.engine.config.DbStateMachineConfig) StateInstance(io.seata.saga.statelang.domain.StateInstance) StateMachineInstance(io.seata.saga.statelang.domain.StateMachineInstance)

Example 25 with StateInstance

use of io.seata.saga.statelang.domain.StateInstance in project seata by seata.

the class DbAndReportTcStateLogStore method isUpdateMode.

private boolean isUpdateMode(StateInstance stateInstance, ProcessContext context) {
    DefaultStateMachineConfig stateMachineConfig = (DefaultStateMachineConfig) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONFIG);
    StateInstruction instruction = context.getInstruction(StateInstruction.class);
    ServiceTaskStateImpl state = (ServiceTaskStateImpl) instruction.getState(context);
    StateMachine stateMachine = stateInstance.getStateMachineInstance().getStateMachine();
    if (StringUtils.hasLength(stateInstance.getStateIdRetriedFor())) {
        if (null != state.isRetryPersistModeUpdate()) {
            return state.isRetryPersistModeUpdate();
        } else if (null != stateMachine.isRetryPersistModeUpdate()) {
            return stateMachine.isRetryPersistModeUpdate();
        }
        return stateMachineConfig.isSagaRetryPersistModeUpdate();
    } else if (StringUtils.hasLength(stateInstance.getStateIdCompensatedFor())) {
        // find if this compensate has been executed
        for (int i = 0; i < stateInstance.getStateMachineInstance().getStateList().size(); i++) {
            StateInstance aStateInstance = stateInstance.getStateMachineInstance().getStateList().get(i);
            if (aStateInstance.isForCompensation() && aStateInstance.getName().equals(stateInstance.getName())) {
                if (null != state.isCompensatePersistModeUpdate()) {
                    return state.isCompensatePersistModeUpdate();
                } else if (null != stateMachine.isCompensatePersistModeUpdate()) {
                    return stateMachine.isCompensatePersistModeUpdate();
                }
                return stateMachineConfig.isSagaCompensatePersistModeUpdate();
            }
        }
        return false;
    }
    return false;
}
Also used : StateInstruction(io.seata.saga.engine.pcext.StateInstruction) StateMachine(io.seata.saga.statelang.domain.StateMachine) DefaultStateMachineConfig(io.seata.saga.engine.impl.DefaultStateMachineConfig) ServiceTaskStateImpl(io.seata.saga.statelang.domain.impl.ServiceTaskStateImpl) StateInstance(io.seata.saga.statelang.domain.StateInstance)

Aggregations

StateInstance (io.seata.saga.statelang.domain.StateInstance)31 StateMachineInstance (io.seata.saga.statelang.domain.StateMachineInstance)16 EngineExecutionException (io.seata.saga.engine.exception.EngineExecutionException)12 StateInstruction (io.seata.saga.engine.pcext.StateInstruction)11 StateMachineConfig (io.seata.saga.engine.StateMachineConfig)9 ForwardInvalidException (io.seata.saga.engine.exception.ForwardInvalidException)7 Map (java.util.Map)7 StateMachine (io.seata.saga.statelang.domain.StateMachine)5 AbstractTaskState (io.seata.saga.statelang.domain.impl.AbstractTaskState)5 ServiceTaskStateImpl (io.seata.saga.statelang.domain.impl.ServiceTaskStateImpl)5 ArrayList (java.util.ArrayList)5 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)5 HierarchicalProcessContext (io.seata.saga.proctrl.HierarchicalProcessContext)4 ExecutionStatus (io.seata.saga.statelang.domain.ExecutionStatus)4 State (io.seata.saga.statelang.domain.State)4 HashMap (java.util.HashMap)4 List (java.util.List)4 ProcessContext (io.seata.saga.proctrl.ProcessContext)3 Loop (io.seata.saga.statelang.domain.TaskState.Loop)3 LinkedHashMap (java.util.LinkedHashMap)3