You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ni...@apache.org on 2017/12/29 06:41:01 UTC

[incubator-servicecomb-saga] 05/05: SCB-98 sent tx aborted on transaction failure

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 <se...@huawei.com>
AuthorDate: Fri Dec 29 10:03:39 2017 +0800

    SCB-98 sent tx aborted on transaction failure
    
    Signed-off-by: seanyinx <se...@huawei.com>
---
 .../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
"commits@servicecomb.apache.org" <co...@servicecomb.apache.org>.