Search in sources :

Example 1 with SuspendedResourcesHolder

use of io.seata.tm.api.transaction.SuspendedResourcesHolder in project seata by seata.

the class TransactionalTemplate method execute.

/**
 * Execute object.
 *
 * @param business the business
 * @return the object
 * @throws TransactionalExecutor.ExecutionException the execution exception
 */
public Object execute(TransactionalExecutor business) throws Throwable {
    // 1. Get transactionInfo
    TransactionInfo txInfo = business.getTransactionInfo();
    if (txInfo == null) {
        throw new ShouldNeverHappenException("transactionInfo does not exist");
    }
    // 1.1 Get current transaction, if not null, the tx role is 'GlobalTransactionRole.Participant'.
    GlobalTransaction tx = GlobalTransactionContext.getCurrent();
    // 1.2 Handle the transaction propagation.
    Propagation propagation = txInfo.getPropagation();
    SuspendedResourcesHolder suspendedResourcesHolder = null;
    try {
        switch(propagation) {
            case NOT_SUPPORTED:
                // If transaction is existing, suspend it.
                if (existingTransaction(tx)) {
                    suspendedResourcesHolder = tx.suspend();
                }
                // Execute without transaction and return.
                return business.execute();
            case REQUIRES_NEW:
                // If transaction is existing, suspend it, and then begin new transaction.
                if (existingTransaction(tx)) {
                    suspendedResourcesHolder = tx.suspend();
                    tx = GlobalTransactionContext.createNew();
                }
                // Continue and execute with new transaction
                break;
            case SUPPORTS:
                // If transaction is not existing, execute without transaction.
                if (notExistingTransaction(tx)) {
                    return business.execute();
                }
                // Continue and execute with new transaction
                break;
            case REQUIRED:
                // else continue and execute with new transaction.
                break;
            case NEVER:
                // If transaction is existing, throw exception.
                if (existingTransaction(tx)) {
                    throw new TransactionException(String.format("Existing transaction found for transaction marked with propagation 'never', xid = %s", tx.getXid()));
                } else {
                    // Execute without transaction and return.
                    return business.execute();
                }
            case MANDATORY:
                // If transaction is not existing, throw exception.
                if (notExistingTransaction(tx)) {
                    throw new TransactionException("No existing transaction found for transaction marked with propagation 'mandatory'");
                }
                // Continue and execute with current transaction.
                break;
            default:
                throw new TransactionException("Not Supported Propagation:" + propagation);
        }
        // 1.3 If null, create new transaction with role 'GlobalTransactionRole.Launcher'.
        if (tx == null) {
            tx = GlobalTransactionContext.createNew();
        }
        // set current tx config to holder
        GlobalLockConfig previousConfig = replaceGlobalLockConfig(txInfo);
        try {
            // 2. If the tx role is 'GlobalTransactionRole.Launcher', send the request of beginTransaction to TC,
            // else do nothing. Of course, the hooks will still be triggered.
            beginTransaction(txInfo, tx);
            Object rs;
            try {
                // Do Your Business
                rs = business.execute();
            } catch (Throwable ex) {
                // 3. The needed business exception to rollback.
                completeTransactionAfterThrowing(txInfo, tx, ex);
                throw ex;
            }
            // 4. everything is fine, commit.
            commitTransaction(tx);
            return rs;
        } finally {
            // 5. clear
            resumeGlobalLockConfig(previousConfig);
            triggerAfterCompletion();
            cleanUp();
        }
    } finally {
        // If the transaction is suspended, resume it.
        if (suspendedResourcesHolder != null) {
            tx.resume(suspendedResourcesHolder);
        }
    }
}
Also used : GlobalLockConfig(io.seata.core.model.GlobalLockConfig) TransactionException(io.seata.core.exception.TransactionException) Propagation(io.seata.tm.api.transaction.Propagation) SuspendedResourcesHolder(io.seata.tm.api.transaction.SuspendedResourcesHolder) ShouldNeverHappenException(io.seata.common.exception.ShouldNeverHappenException) TransactionInfo(io.seata.tm.api.transaction.TransactionInfo)

Aggregations

ShouldNeverHappenException (io.seata.common.exception.ShouldNeverHappenException)1 TransactionException (io.seata.core.exception.TransactionException)1 GlobalLockConfig (io.seata.core.model.GlobalLockConfig)1 Propagation (io.seata.tm.api.transaction.Propagation)1 SuspendedResourcesHolder (io.seata.tm.api.transaction.SuspendedResourcesHolder)1 TransactionInfo (io.seata.tm.api.transaction.TransactionInfo)1