This is an automated email from the ASF dual-hosted git repository. ningjiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-saga.git
commit 82f591682aae43d2a1eb6dbdd2bf3adb745c0bcc Author: seanyinx <[email protected]> AuthorDate: Fri Dec 29 10:03:39 2017 +0800 SCB-98 sent tx aborted on transaction failure Signed-off-by: seanyinx <[email protected]> --- .../src/main/resources/schema-mysql.sql | 1 + .../spring/TransactionInterceptionTest.java | 24 ++++++++++++++++++ .../spring/TransactionalUserService.java | 4 +++ .../transaction/FailedTransactionInterceptor.java} | 29 ++++++++++------------ .../saga/omega/transaction/TransactionAspect.java | 23 ++++++++++++++--- .../saga/omega/transaction/TxAbortedEvent.java} | 26 +++---------------- 6 files changed, 66 insertions(+), 41 deletions(-) diff --git a/alpha/alpha-server/src/main/resources/schema-mysql.sql b/alpha/alpha-server/src/main/resources/schema-mysql.sql index c3175ed..2940804 100644 --- a/alpha/alpha-server/src/main/resources/schema-mysql.sql +++ b/alpha/alpha-server/src/main/resources/schema-mysql.sql @@ -5,6 +5,7 @@ CREATE TABLE IF NOT EXISTS `tx_event_envelope` ( `local_tx_id` varchar(36) NOT NULL, `parent_tx_id` varchar(36) DEFAULT NULL, `type` varchar(50) NOT NULL, + `compensation_method` varchar(256) NOT NULL, `payloads` varbinary(10240), PRIMARY KEY (`surrogate_id`), INDEX `running_sagas_index` (`global_tx_id`, `local_tx_id`, `type`) diff --git a/omega/omega-spring-tx/src/test/java/io/servicecomb/saga/omega/transaction/spring/TransactionInterceptionTest.java b/omega/omega-spring-tx/src/test/java/io/servicecomb/saga/omega/transaction/spring/TransactionInterceptionTest.java index e110713..4ffd546 100644 --- a/omega/omega-spring-tx/src/test/java/io/servicecomb/saga/omega/transaction/spring/TransactionInterceptionTest.java +++ b/omega/omega-spring-tx/src/test/java/io/servicecomb/saga/omega/transaction/spring/TransactionInterceptionTest.java @@ -17,7 +17,9 @@ package io.servicecomb.saga.omega.transaction.spring; +import static com.seanyinx.github.unit.scaffolding.AssertUtils.expectFailing; import static com.seanyinx.github.unit.scaffolding.Randomness.uniquify; +import static io.servicecomb.saga.omega.transaction.spring.TransactionalUserService.ILLEGAL_USER; import static java.util.Arrays.asList; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.core.Is.is; @@ -104,6 +106,24 @@ public class TransactionInterceptionTest { } @Test + public void sendsAbortEvent_OnSubTransactionFailure() throws Exception { + try { + userService.add(new User(ILLEGAL_USER, email)); + expectFailing(IllegalArgumentException.class); + } catch (IllegalArgumentException ignored) { + } + + String compensationMethod = TransactionalUserService.class.getDeclaredMethod("delete", User.class).toString(); + + assertEquals( + asList( + txStartedEvent(globalTxId, localTxId, parentTxId, compensationMethod, ILLEGAL_USER, email), + txAbortedEvent(globalTxId, localTxId, parentTxId, compensationMethod)), + toString(messages) + ); + } + + @Test public void compensateOnTransactionException() throws Exception { User user = userService.add(new User(username, email)); @@ -179,4 +199,8 @@ public class TransactionInterceptionTest { private static String txEndedEvent(String globalTxId, String localTxId, String parentTxId, String compensationMethod) { return globalTxId + ":" + localTxId + ":" + parentTxId + ":" + compensationMethod + ":" + TX_ENDED_EVENT; } + + private static String txAbortedEvent(String globalTxId, String localTxId, String parentTxId, String compensationMethod) { + return globalTxId + ":" + localTxId + ":" + parentTxId + ":" + compensationMethod + ":" + TX_ENDED_EVENT; + } } diff --git a/omega/omega-spring-tx/src/test/java/io/servicecomb/saga/omega/transaction/spring/TransactionalUserService.java b/omega/omega-spring-tx/src/test/java/io/servicecomb/saga/omega/transaction/spring/TransactionalUserService.java index 74cb59e..7538253 100644 --- a/omega/omega-spring-tx/src/test/java/io/servicecomb/saga/omega/transaction/spring/TransactionalUserService.java +++ b/omega/omega-spring-tx/src/test/java/io/servicecomb/saga/omega/transaction/spring/TransactionalUserService.java @@ -24,6 +24,7 @@ import io.servicecomb.saga.omega.transaction.annotations.Compensable; @Component class TransactionalUserService { + static final String ILLEGAL_USER = "Illegal User"; private final UserRepository userRepository; @Autowired @@ -33,6 +34,9 @@ class TransactionalUserService { @Compensable(compensationMethod = "delete") User add(User user) { + if (ILLEGAL_USER.equals(user.username())) { + throw new IllegalArgumentException("User is illegal"); + } return userRepository.save(user); } diff --git a/omega/omega-spring-tx/src/test/java/io/servicecomb/saga/omega/transaction/spring/TransactionalUserService.java b/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/FailedTransactionInterceptor.java similarity index 55% copy from omega/omega-spring-tx/src/test/java/io/servicecomb/saga/omega/transaction/spring/TransactionalUserService.java copy to omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/FailedTransactionInterceptor.java index 74cb59e..6cbd8af 100644 --- a/omega/omega-spring-tx/src/test/java/io/servicecomb/saga/omega/transaction/spring/TransactionalUserService.java +++ b/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/FailedTransactionInterceptor.java @@ -15,28 +15,25 @@ * limitations under the License. */ -package io.servicecomb.saga.omega.transaction.spring; +package io.servicecomb.saga.omega.transaction; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; +import java.io.PrintWriter; +import java.io.StringWriter; -import io.servicecomb.saga.omega.transaction.annotations.Compensable; +class FailedTransactionInterceptor { + private final MessageSender sender; -@Component -class TransactionalUserService { - private final UserRepository userRepository; - - @Autowired - TransactionalUserService(UserRepository userRepository) { - this.userRepository = userRepository; + FailedTransactionInterceptor(MessageSender sender) { + this.sender = sender; } - @Compensable(compensationMethod = "delete") - User add(User user) { - return userRepository.save(user); + void intercept(String globalTxId, String localTxId, String parentTxId, String compensationMethod, Throwable throwable) { + sender.send(new TxAbortedEvent(globalTxId, localTxId, parentTxId, compensationMethod, stackTrace(throwable))); } - void delete(User user) { - userRepository.delete(user.id()); + private String stackTrace(Throwable e) { + StringWriter writer = new StringWriter(); + e.printStackTrace(new PrintWriter(writer)); + return writer.toString(); } } diff --git a/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/TransactionAspect.java b/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/TransactionAspect.java index 674d1a7..6390bc7 100644 --- a/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/TransactionAspect.java +++ b/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/TransactionAspect.java @@ -35,12 +35,14 @@ public class TransactionAspect { private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private final PreTransactionInterceptor preTransactionInterceptor; private final PostTransactionInterceptor postTransactionInterceptor; + private final FailedTransactionInterceptor failedTransactionInterceptor; private final OmegaContext context; public TransactionAspect(MessageSender sender, OmegaContext context) { this.context = context; this.preTransactionInterceptor = new PreTransactionInterceptor(sender); this.postTransactionInterceptor = new PostTransactionInterceptor(sender); + this.failedTransactionInterceptor = new FailedTransactionInterceptor(sender); } @Around("execution(@io.servicecomb.saga.omega.transaction.annotations.Compensable * *(..)) && @annotation(compensable)") @@ -51,10 +53,16 @@ public class TransactionAspect { String signature = compensationMethodSignature(joinPoint, compensable, method); preIntercept(joinPoint, signature); - Object result = joinPoint.proceed(); - postIntercept(signature); - return result; + try { + Object result = joinPoint.proceed(); + postIntercept(signature); + + return result; + } catch (Throwable throwable) { + interceptException(signature, throwable); + throw throwable; + } } private String compensationMethodSignature(ProceedingJoinPoint joinPoint, Compensable compensable, Method method) @@ -82,4 +90,13 @@ public class TransactionAspect { context.parentTxId(), signature); } + + private void interceptException(String signature, Throwable throwable) { + failedTransactionInterceptor.intercept( + context.globalTxId(), + context.localTxId(), + context.parentTxId(), + signature, + throwable); + } } diff --git a/omega/omega-spring-tx/src/test/java/io/servicecomb/saga/omega/transaction/spring/TransactionalUserService.java b/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/TxAbortedEvent.java similarity index 56% copy from omega/omega-spring-tx/src/test/java/io/servicecomb/saga/omega/transaction/spring/TransactionalUserService.java copy to omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/TxAbortedEvent.java index 74cb59e..2d04a7d 100644 --- a/omega/omega-spring-tx/src/test/java/io/servicecomb/saga/omega/transaction/spring/TransactionalUserService.java +++ b/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/TxAbortedEvent.java @@ -15,28 +15,10 @@ * limitations under the License. */ -package io.servicecomb.saga.omega.transaction.spring; +package io.servicecomb.saga.omega.transaction; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import io.servicecomb.saga.omega.transaction.annotations.Compensable; - -@Component -class TransactionalUserService { - private final UserRepository userRepository; - - @Autowired - TransactionalUserService(UserRepository userRepository) { - this.userRepository = userRepository; - } - - @Compensable(compensationMethod = "delete") - User add(User user) { - return userRepository.save(user); - } - - void delete(User user) { - userRepository.delete(user.id()); +class TxAbortedEvent extends TxEvent { + TxAbortedEvent(String globalTxId, String localTxId, String parentTxId, String compensationMethod, String stackTrace) { + super(globalTxId, localTxId, parentTxId, compensationMethod, stackTrace); } } -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
