Skip to content

Commit

Permalink
feature: support to set propagation of global transaction (apache#2206)
Browse files Browse the repository at this point in the history
  • Loading branch information
booogu committed Feb 27, 2020
1 parent 46f0b03 commit ec1df96
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package io.seata.spring.annotation;

import io.seata.tm.api.transaction.Propagation;
import io.seata.tm.api.transaction.TransactionInfo;

import java.lang.annotation.ElementType;
Expand Down Expand Up @@ -69,5 +70,9 @@
*/
String[] noRollbackForClassName() default {};


/**
* the propagation of the global transaction
* @return
*/
Propagation propagation() default Propagation.REQUIRED;
}
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ public TransactionInfo getTransactionInfo() {
TransactionInfo transactionInfo = new TransactionInfo();
transactionInfo.setTimeOut(globalTrxAnno.timeoutMills());
transactionInfo.setName(name());
transactionInfo.setPropagation(globalTrxAnno.propagation());
Set<RollbackRule> rollbackRules = new LinkedHashSet<>();
for (Class<?> rbRule : globalTrxAnno.rollbackFor()) {
rollbackRules.add(new RollbackRule(rbRule));
Expand Down
30 changes: 14 additions & 16 deletions tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
package io.seata.tm.api;

import io.seata.common.exception.ShouldNeverHappenException;
import io.seata.config.ConfigurationFactory;
import io.seata.core.constants.ConfigurationKeys;
import io.seata.core.context.RootContext;
Expand Down Expand Up @@ -90,15 +89,13 @@ public void begin(int timeout) throws TransactionException {
@Override
public void begin(int timeout, String name) throws TransactionException {
if (role != GlobalTransactionRole.Launcher) {
check();
assertXIDNotNull();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Ignore Begin(): just involved in global transaction [{}]", xid);
}
return;
}
if (xid != null) {
throw new IllegalStateException();
}
assertXIDNull();
if (RootContext.getXID() != null) {
throw new IllegalStateException();
}
Expand All @@ -120,9 +117,7 @@ public void commit() throws TransactionException {
}
return;
}
if (xid == null) {
throw new IllegalStateException();
}
assertXIDNotNull();
int retry = COMMIT_RETRY_COUNT;
try {
while (retry > 0) {
Expand Down Expand Up @@ -157,9 +152,7 @@ public void rollback() throws TransactionException {
}
return;
}
if (xid == null) {
throw new IllegalStateException();
}
assertXIDNotNull();

int retry = ROLLBACK_RETRY_COUNT;
try {
Expand Down Expand Up @@ -201,9 +194,8 @@ public String getXid() {

@Override
public void globalReport(GlobalStatus globalStatus) throws TransactionException {
if (xid == null) {
throw new IllegalStateException();
}
assertXIDNotNull();

if (globalStatus == null) {
throw new IllegalStateException();
}
Expand All @@ -218,10 +210,16 @@ public void globalReport(GlobalStatus globalStatus) throws TransactionException
}
}

private void check() {
private void assertXIDNotNull() {
if (xid == null) {
throw new ShouldNeverHappenException();
throw new IllegalStateException();
}
}

private void assertXIDNull() {
if (xid != null) {
throw new IllegalStateException();
}
}

}
73 changes: 51 additions & 22 deletions tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,17 @@


import io.seata.common.exception.ShouldNeverHappenException;
import io.seata.common.util.StringUtils;
import io.seata.core.context.RootContext;
import io.seata.core.exception.TransactionException;
import io.seata.tm.api.transaction.Propagation;
import io.seata.tm.api.transaction.TransactionHook;
import io.seata.tm.api.transaction.TransactionHookManager;
import io.seata.tm.api.transaction.TransactionInfo;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
* Template of executing business logic with a global transaction.
*
Expand All @@ -44,41 +46,68 @@ public class TransactionalTemplate {
* @throws TransactionalExecutor.ExecutionException the execution exception
*/
public Object execute(TransactionalExecutor business) throws Throwable {
// 1. get or create a transaction
GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate();

// 1.1 get transactionInfo
// 1 get transactionInfo
TransactionInfo txInfo = business.getTransactionInfo();
if (txInfo == null) {
throw new ShouldNeverHappenException("transactionInfo does not exist");
}
Propagation propagation = txInfo.getPropagation();
String previousXid = null;
try {
switch (propagation) {
case NOT_SUPPORTED:
previousXid = RootContext.unbind();
return business.execute();
case REQUIRES_NEW:
previousXid = RootContext.unbind();
break;
case SUPPORTS:
if (StringUtils.isEmpty(RootContext.getXID())) {
return business.execute();
}
break;
case REQUIRED:
break;
default:
throw new ShouldNeverHappenException("Not Supported Propagation:" + propagation);
}

// 2. begin transaction
beginTransaction(txInfo, tx);
// 1.1 get or create a transaction
GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate();

Object rs = null;
try {

// Do Your Business
rs = business.execute();
// 2. begin transaction
beginTransaction(txInfo, tx);

} catch (Throwable ex) {
Object rs = null;
try {

// 3.the needed business exception to rollback.
completeTransactionAfterThrowing(txInfo,tx,ex);
throw ex;
}
// Do Your Business
rs = business.execute();

// 4. everything is fine, commit.
commitTransaction(tx);
} 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;
return rs;
} finally {
//5. clear
triggerAfterCompletion();
cleanUp();
}
} finally {
//5. clear
triggerAfterCompletion();
cleanUp();
if (previousXid != null) {
RootContext.bind(previousXid);
}
}

}

private void completeTransactionAfterThrowing(TransactionInfo txInfo, GlobalTransaction tx, Throwable ex) throws TransactionalExecutor.ExecutionException {
Expand Down
44 changes: 44 additions & 0 deletions tm/src/main/java/io/seata/tm/api/transaction/Propagation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.seata.tm.api.transaction;

/**
* Propagation level of global transactions.
*
* @author haozhibei
*/
public enum Propagation {
/**
* The REQUIRED.
*/
REQUIRED,

/**
* The REQUIRES_NEW.
*/
REQUIRES_NEW,

/**
* The NOT_SUPPORTED
*/
NOT_SUPPORTED,

/**
* The SUPPORTS
*/
SUPPORTS
}

14 changes: 14 additions & 0 deletions tm/src/main/java/io/seata/tm/api/transaction/TransactionInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public final class TransactionInfo implements Serializable {

private Set<RollbackRule> rollbackRules;

private Propagation propagation;

public int getTimeOut() {
return timeOut;
}
Expand Down Expand Up @@ -75,4 +77,16 @@ public boolean rollbackOn(Throwable ex) {

return !(winner instanceof NoRollbackRule);
}

public Propagation getPropagation() {
if (this.propagation != null) {
return this.propagation;
}
//default propagation
return Propagation.REQUIRED;
}

public void setPropagation(Propagation propagation) {
this.propagation = propagation;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class TransactionInfoTest {
private static final String IO_EXCEPTION_SHORT_NAME = "IOException";
private static final String NAME = "test";
private static final int TIME_OUT = 30000;
private static final String PROPAGATION = Propagation.REQUIRED.name();


/**
Expand All @@ -41,6 +42,7 @@ public class TransactionInfoTest {
public void testFieldGetSetFromJson() {
String fromJson = "{\n" +
"\t\"name\":\""+ NAME +"\",\n" +
"\t\"propagation\":\""+ PROPAGATION +"\",\n"+
"\t\"rollbackRules\":[{\n" +
"\t\t\"exceptionName\":\""+ IllegalStateException.class.getName() +"\"\n" +
"\t},{\n" +
Expand Down

0 comments on commit ec1df96

Please sign in to comment.