Search in sources :

Example 11 with BranchStatus

use of io.seata.core.model.BranchStatus in project seata by seata.

the class AbstractBranchEndResponseCodec method encode.

@Override
public <T> void encode(T t, ByteBuf out) {
    super.encode(t, out);
    AbstractBranchEndResponse abstractBranchEndResponse = (AbstractBranchEndResponse) t;
    String xid = abstractBranchEndResponse.getXid();
    long branchId = abstractBranchEndResponse.getBranchId();
    BranchStatus branchStatus = abstractBranchEndResponse.getBranchStatus();
    if (xid != null) {
        byte[] bs = xid.getBytes(UTF8);
        out.writeShort((short) bs.length);
        if (bs.length > 0) {
            out.writeBytes(bs);
        }
    } else {
        out.writeShort((short) 0);
    }
    out.writeLong(branchId);
    out.writeByte(branchStatus.getCode());
}
Also used : AbstractBranchEndResponse(io.seata.core.protocol.transaction.AbstractBranchEndResponse) BranchStatus(io.seata.core.model.BranchStatus)

Example 12 with BranchStatus

use of io.seata.core.model.BranchStatus in project seata by seata.

the class SagaCore method doGlobalCommit.

@Override
public boolean doGlobalCommit(GlobalSession globalSession, boolean retrying) throws TransactionException {
    try {
        BranchStatus branchStatus = branchCommit(globalSession, SessionHelper.newBranch(BranchType.SAGA, globalSession.getXid(), -1, getSagaResourceId(globalSession), globalSession.getStatus().name()));
        switch(branchStatus) {
            case PhaseTwo_Committed:
                removeAllBranches(globalSession);
                LOGGER.info("Successfully committed SAGA global[" + globalSession.getXid() + "]");
                break;
            case PhaseTwo_Rollbacked:
                LOGGER.info("Successfully rollbacked SAGA global[" + globalSession.getXid() + "]");
                removeAllBranches(globalSession);
                SessionHelper.endRollbacked(globalSession);
                return false;
            case PhaseTwo_RollbackFailed_Retryable:
                LOGGER.error("By [{}], failed to rollback SAGA global [{}], will retry later.", branchStatus, globalSession.getXid());
                SessionHolder.getRetryCommittingSessionManager().removeGlobalSession(globalSession);
                globalSession.queueToRetryRollback();
                return false;
            case PhaseOne_Failed:
                LOGGER.error("By [{}], finish SAGA global [{}]", branchStatus, globalSession.getXid());
                removeAllBranches(globalSession);
                globalSession.changeStatus(GlobalStatus.Finished);
                globalSession.end();
                return false;
            case PhaseTwo_CommitFailed_Unretryable:
                if (globalSession.canBeCommittedAsync()) {
                    LOGGER.error("By [{}], failed to commit SAGA global [{}]", branchStatus, globalSession.getXid());
                    break;
                } else {
                    SessionHelper.endCommitFailed(globalSession);
                    LOGGER.error("Finally, failed to commit SAGA global[{}]", globalSession.getXid());
                    return false;
                }
            default:
                if (!retrying) {
                    globalSession.queueToRetryCommit();
                    return false;
                } else {
                    LOGGER.error("Failed to commit SAGA global[{}], will retry later.", globalSession.getXid());
                    return false;
                }
        }
    } catch (Exception ex) {
        LOGGER.error("Failed to commit global[" + globalSession.getXid() + "]", ex);
        if (!retrying) {
            globalSession.queueToRetryRollback();
        }
        throw new TransactionException(ex);
    }
    return true;
}
Also used : TransactionException(io.seata.core.exception.TransactionException) GlobalTransactionException(io.seata.core.exception.GlobalTransactionException) BranchStatus(io.seata.core.model.BranchStatus) TransactionException(io.seata.core.exception.TransactionException) TimeoutException(java.util.concurrent.TimeoutException) IOException(java.io.IOException) GlobalTransactionException(io.seata.core.exception.GlobalTransactionException)

Example 13 with BranchStatus

use of io.seata.core.model.BranchStatus in project seata by seata.

the class SagaCore method doGlobalRollback.

@Override
public boolean doGlobalRollback(GlobalSession globalSession, boolean retrying) throws TransactionException {
    try {
        BranchStatus branchStatus = branchRollback(globalSession, SessionHelper.newBranch(BranchType.SAGA, globalSession.getXid(), -1, getSagaResourceId(globalSession), globalSession.getStatus().name()));
        switch(branchStatus) {
            case PhaseTwo_Rollbacked:
                removeAllBranches(globalSession);
                LOGGER.info("Successfully rollbacked SAGA global[{}]", globalSession.getXid());
                break;
            case PhaseTwo_RollbackFailed_Unretryable:
                SessionHelper.endRollbackFailed(globalSession);
                LOGGER.error("Failed to rollback SAGA global[{}]", globalSession.getXid());
                return false;
            case PhaseTwo_CommitFailed_Retryable:
                SessionHolder.getRetryRollbackingSessionManager().removeGlobalSession(globalSession);
                globalSession.queueToRetryCommit();
                LOGGER.warn("Retry by custom recover strategy [Forward] on timeout, SAGA global[{}]", globalSession.getXid());
                return false;
            default:
                LOGGER.error("Failed to rollback SAGA global[{}]", globalSession.getXid());
                if (!retrying) {
                    globalSession.queueToRetryRollback();
                }
                return false;
        }
    } catch (Exception ex) {
        LOGGER.error("Failed to rollback global[{}]", globalSession.getXid(), ex);
        if (!retrying) {
            globalSession.queueToRetryRollback();
        }
        throw new TransactionException(ex);
    }
    return true;
}
Also used : TransactionException(io.seata.core.exception.TransactionException) GlobalTransactionException(io.seata.core.exception.GlobalTransactionException) BranchStatus(io.seata.core.model.BranchStatus) TransactionException(io.seata.core.exception.TransactionException) TimeoutException(java.util.concurrent.TimeoutException) IOException(java.io.IOException) GlobalTransactionException(io.seata.core.exception.GlobalTransactionException)

Example 14 with BranchStatus

use of io.seata.core.model.BranchStatus in project seata by seata.

the class DefaultCore method doGlobalCommit.

@Override
public boolean doGlobalCommit(GlobalSession globalSession, boolean retrying) throws TransactionException {
    boolean success = true;
    // start committing event
    eventBus.post(new GlobalTransactionEvent(globalSession.getTransactionId(), GlobalTransactionEvent.ROLE_TC, globalSession.getTransactionName(), globalSession.getApplicationId(), globalSession.getTransactionServiceGroup(), globalSession.getBeginTime(), null, globalSession.getStatus()));
    if (globalSession.isSaga()) {
        success = getCore(BranchType.SAGA).doGlobalCommit(globalSession, retrying);
    } else {
        Boolean result = SessionHelper.forEach(globalSession.getSortedBranches(), branchSession -> {
            // if not retrying, skip the canBeCommittedAsync branches
            if (!retrying && branchSession.canBeCommittedAsync()) {
                return CONTINUE;
            }
            BranchStatus currentStatus = branchSession.getStatus();
            if (currentStatus == BranchStatus.PhaseOne_Failed) {
                globalSession.removeBranch(branchSession);
                return CONTINUE;
            }
            try {
                BranchStatus branchStatus = getCore(branchSession.getBranchType()).branchCommit(globalSession, branchSession);
                switch(branchStatus) {
                    case PhaseTwo_Committed:
                        globalSession.removeBranch(branchSession);
                        return CONTINUE;
                    case PhaseTwo_CommitFailed_Unretryable:
                        if (globalSession.canBeCommittedAsync()) {
                            LOGGER.error("Committing branch transaction[{}], status: PhaseTwo_CommitFailed_Unretryable, please check the business log.", branchSession.getBranchId());
                            return CONTINUE;
                        } else {
                            SessionHelper.endCommitFailed(globalSession);
                            LOGGER.error("Committing global transaction[{}] finally failed, caused by branch transaction[{}] commit failed.", globalSession.getXid(), branchSession.getBranchId());
                            return false;
                        }
                    default:
                        if (!retrying) {
                            globalSession.queueToRetryCommit();
                            return false;
                        }
                        if (globalSession.canBeCommittedAsync()) {
                            LOGGER.error("Committing branch transaction[{}], status:{} and will retry later", branchSession.getBranchId(), branchStatus);
                            return CONTINUE;
                        } else {
                            LOGGER.error("Committing global transaction[{}] failed, caused by branch transaction[{}] commit failed, will retry later.", globalSession.getXid(), branchSession.getBranchId());
                            return false;
                        }
                }
            } catch (Exception ex) {
                StackTraceLogger.error(LOGGER, ex, "Committing branch transaction exception: {}", new String[] { branchSession.toString() });
                if (!retrying) {
                    globalSession.queueToRetryCommit();
                    throw new TransactionException(ex);
                }
            }
            return CONTINUE;
        });
        // Return if the result is not null
        if (result != null) {
            return result;
        }
        // do print log and return false
        if (globalSession.hasBranch() && !globalSession.canBeCommittedAsync()) {
            LOGGER.info("Committing global transaction is NOT done, xid = {}.", globalSession.getXid());
            return false;
        }
    }
    // If success and there is no branch, end the global transaction.
    if (success && globalSession.getBranchSessions().isEmpty()) {
        SessionHelper.endCommitted(globalSession);
        // committed event
        eventBus.post(new GlobalTransactionEvent(globalSession.getTransactionId(), GlobalTransactionEvent.ROLE_TC, globalSession.getTransactionName(), globalSession.getApplicationId(), globalSession.getTransactionServiceGroup(), globalSession.getBeginTime(), System.currentTimeMillis(), globalSession.getStatus()));
        LOGGER.info("Committing global transaction is successfully done, xid = {}.", globalSession.getXid());
    }
    return success;
}
Also used : TransactionException(io.seata.core.exception.TransactionException) BranchStatus(io.seata.core.model.BranchStatus) GlobalTransactionEvent(io.seata.core.event.GlobalTransactionEvent) TransactionException(io.seata.core.exception.TransactionException) NotSupportYetException(io.seata.common.exception.NotSupportYetException)

Example 15 with BranchStatus

use of io.seata.core.model.BranchStatus 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)

Aggregations

BranchStatus (io.seata.core.model.BranchStatus)19 TransactionException (io.seata.core.exception.TransactionException)14 GlobalSession (io.seata.server.session.GlobalSession)6 IOException (java.io.IOException)5 NotSupportYetException (io.seata.common.exception.NotSupportYetException)4 GlobalTransactionEvent (io.seata.core.event.GlobalTransactionEvent)4 GlobalTransactionException (io.seata.core.exception.GlobalTransactionException)4 BranchSession (io.seata.server.session.BranchSession)4 TimeoutException (java.util.concurrent.TimeoutException)4 BranchType (io.seata.core.model.BranchType)2 GlobalStatus (io.seata.core.model.GlobalStatus)2 SessionCondition (io.seata.server.session.SessionCondition)2 SessionManager (io.seata.server.session.SessionManager)2 FileTransactionStoreManager (io.seata.server.storage.file.store.FileTransactionStoreManager)2 TransactionStoreManager (io.seata.server.store.TransactionStoreManager)2 ArrayList (java.util.ArrayList)2 Collection (java.util.Collection)2 List (java.util.List)2 Test (org.junit.jupiter.api.Test)2 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)2