This is an automated email from the ASF dual-hosted git repository. ningjiang pushed a commit to branch SCB-1385 in repository https://gitbox.apache.org/repos/asf/servicecomb-pack.git
commit 5beee85a70117a1dec6ef9563e62e966f9b47c60 Author: Willem Jiang <[email protected]> AuthorDate: Fri Jul 19 19:37:22 2019 +0800 SCB-1385 provide a common way to pass the GID and LID --- .../pack/omega/context/OmegaContext.java | 4 ++ .../pack/omega/context/TransactionContext.java | 46 +++++++++++++++++++ .../omega/context/TransactionContextWrapper.java | 25 +++++++++++ .../pack/omega/transaction/TransactionAspect.java | 22 +++++++++ .../omega/transaction/TransactionAspectTest.java | 52 ++++++++++++++++++++++ 5 files changed, 149 insertions(+) diff --git a/omega/omega-context/src/main/java/org/apache/servicecomb/pack/omega/context/OmegaContext.java b/omega/omega-context/src/main/java/org/apache/servicecomb/pack/omega/context/OmegaContext.java index 96e54bd..660b923 100644 --- a/omega/omega-context/src/main/java/org/apache/servicecomb/pack/omega/context/OmegaContext.java +++ b/omega/omega-context/src/main/java/org/apache/servicecomb/pack/omega/context/OmegaContext.java @@ -71,6 +71,10 @@ public class OmegaContext { return alphaFeatureAkkaEnabled; } + public TransactionContext getTransactionContext() { + return new TransactionContext(globalTxId(), localTxId()); + } + public void clear() { globalTxId.remove(); localTxId.remove(); diff --git a/omega/omega-context/src/main/java/org/apache/servicecomb/pack/omega/context/TransactionContext.java b/omega/omega-context/src/main/java/org/apache/servicecomb/pack/omega/context/TransactionContext.java new file mode 100644 index 0000000..48bd370 --- /dev/null +++ b/omega/omega-context/src/main/java/org/apache/servicecomb/pack/omega/context/TransactionContext.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.servicecomb.pack.omega.context; + +/** + * This class is holding the Transaction related context which could be use in customer code + */ +public class TransactionContext { + private String globalTxId; + private String localTxId; + + public TransactionContext(String globalTxId, String localTxId) { + this.globalTxId = globalTxId; + this.localTxId = localTxId; + } + + public String globalTxId() { + return globalTxId; + } + + public void setGlobalTxId(String globalTxId) { + this.globalTxId = globalTxId; + } + + public String localTxId() { + return localTxId; + } + + public void setLocalTxId(String localTxId) { + this.localTxId = localTxId; + } +} diff --git a/omega/omega-context/src/main/java/org/apache/servicecomb/pack/omega/context/TransactionContextWrapper.java b/omega/omega-context/src/main/java/org/apache/servicecomb/pack/omega/context/TransactionContextWrapper.java new file mode 100644 index 0000000..ccfe099 --- /dev/null +++ b/omega/omega-context/src/main/java/org/apache/servicecomb/pack/omega/context/TransactionContextWrapper.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.servicecomb.pack.omega.context; + +/** + * Once the user business class implement this TransactionContextWrapper, Omega could extract the TransactionContext instance + * out of the business class, and set up the OmegaContext before calling sub transaction method. + */ +public interface TransactionContextWrapper { + TransactionContext getTransactionContext(); +} diff --git a/omega/omega-transaction/src/main/java/org/apache/servicecomb/pack/omega/transaction/TransactionAspect.java b/omega/omega-transaction/src/main/java/org/apache/servicecomb/pack/omega/transaction/TransactionAspect.java index 5e57ee7..fa7bbf4 100644 --- a/omega/omega-transaction/src/main/java/org/apache/servicecomb/pack/omega/transaction/TransactionAspect.java +++ b/omega/omega-transaction/src/main/java/org/apache/servicecomb/pack/omega/transaction/TransactionAspect.java @@ -21,6 +21,8 @@ import java.lang.invoke.MethodHandles; import java.lang.reflect.Method; import org.apache.servicecomb.pack.omega.context.OmegaContext; +import org.apache.servicecomb.pack.omega.context.TransactionContext; +import org.apache.servicecomb.pack.omega.context.TransactionContextWrapper; import org.apache.servicecomb.pack.omega.transaction.annotations.Compensable; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; @@ -46,6 +48,15 @@ public class TransactionAspect { @Around("execution(@org.apache.servicecomb.pack.omega.transaction.annotations.Compensable * *(..)) && @annotation(compensable)") Object advise(ProceedingJoinPoint joinPoint, Compensable compensable) throws Throwable { Method method = ((MethodSignature) joinPoint.getSignature()).getMethod(); + // just check if we need to setup the transaction context information first + TransactionContext transactionContext = getTransactionContextFromArgs(joinPoint.getArgs()); + if (transactionContext != null) { + LOG.debug("Updated context {} for globalTxId:{} and localTxId:{}", context, + transactionContext.globalTxId(), transactionContext.localTxId()); + context.setGlobalTxId(transactionContext.globalTxId()); + context.setLocalTxId(transactionContext.localTxId()); + } + String localTxId = context.localTxId(); context.newLocalTxId(); LOG.debug("Updated context {} for compensable method {} ", context, method.toString()); @@ -59,4 +70,15 @@ public class TransactionAspect { LOG.debug("Restored context back to {}", context); } } + + TransactionContext getTransactionContextFromArgs(Object[] args) { + if (args != null) { + for (Object arg : args) { + if (arg instanceof TransactionContextWrapper) { + return ((TransactionContextWrapper) arg).getTransactionContext(); + } + } + } + return null; + } } diff --git a/omega/omega-transaction/src/test/java/org/apache/servicecomb/pack/omega/transaction/TransactionAspectTest.java b/omega/omega-transaction/src/test/java/org/apache/servicecomb/pack/omega/transaction/TransactionAspectTest.java index eb82080..17a5aa3 100644 --- a/omega/omega-transaction/src/test/java/org/apache/servicecomb/pack/omega/transaction/TransactionAspectTest.java +++ b/omega/omega-transaction/src/test/java/org/apache/servicecomb/pack/omega/transaction/TransactionAspectTest.java @@ -21,7 +21,9 @@ import static com.seanyinx.github.unit.scaffolding.AssertUtils.expectFailing; import static org.hamcrest.core.AnyOf.anyOf; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsInstanceOf.instanceOf; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -37,6 +39,8 @@ import java.util.UUID; import org.apache.servicecomb.pack.common.EventType; import org.apache.servicecomb.pack.omega.context.IdGenerator; import org.apache.servicecomb.pack.omega.context.OmegaContext; +import org.apache.servicecomb.pack.omega.context.TransactionContext; +import org.apache.servicecomb.pack.omega.context.TransactionContextWrapper; import org.apache.servicecomb.pack.omega.transaction.annotations.Compensable; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.reflect.MethodSignature; @@ -52,6 +56,9 @@ public class TransactionAspectTest { private final String localTxId = UUID.randomUUID().toString(); private final String newLocalTxId = UUID.randomUUID().toString(); + private final String transactionGloablTxId = UUID.randomUUID().toString(); + private final String transactionLocalTxId = UUID.randomUUID().toString(); + private final SagaMessageSender sender = new SagaMessageSender() { @Override public void onConnected() { @@ -86,6 +93,9 @@ public class TransactionAspectTest { private final OmegaContext omegaContext = new OmegaContext(idGenerator); private final TransactionAspect aspect = new TransactionAspect(sender, omegaContext); + private final TransactionContext tx = mock(TransactionContext.class); + private final TransactionContextWrapper wrapper = mock(TransactionContextWrapper.class); + @Before public void setUp() throws Exception { when(idGenerator.nextId()).thenReturn(newLocalTxId); @@ -98,6 +108,48 @@ public class TransactionAspectTest { omegaContext.setGlobalTxId(globalTxId); omegaContext.setLocalTxId(localTxId); + + when(wrapper.getTransactionContext()).thenReturn(tx); + when(tx.globalTxId()).thenReturn(transactionGloablTxId); + when(tx.localTxId()).thenReturn(transactionLocalTxId); + } + + @Test + public void testGetTransactionContextFromArgs() throws Throwable { + + TransactionContext result = aspect.getTransactionContextFromArgs(new Object[]{tx,wrapper}); + assertThat(result, is(tx)); + + result = aspect.getTransactionContextFromArgs(new Object[]{}); + assertNull(result); + + result = aspect.getTransactionContextFromArgs(new Object[]{tx}); + assertNull(result); + } + + @Test + public void setNewLocalTxIdCompensableWithTransactionContext() throws Throwable { + // setup the argument class + when(joinPoint.getArgs()).thenReturn(new Object[]{wrapper}); + aspect.advise(joinPoint, compensable); + TxEvent startedEvent = messages.get(0); + + assertThat(startedEvent.globalTxId(), is(transactionGloablTxId)); + assertThat(startedEvent.localTxId(), is(newLocalTxId)); + assertThat(startedEvent.parentTxId(), is(transactionLocalTxId)); + assertThat(startedEvent.type(), is(EventType.TxStartedEvent)); + assertThat(startedEvent.retries(), is(0)); + assertThat(startedEvent.retryMethod().isEmpty(), is(true)); + + TxEvent endedEvent = messages.get(1); + + assertThat(endedEvent.globalTxId(), is(transactionGloablTxId)); + assertThat(endedEvent.localTxId(), is(newLocalTxId)); + assertThat(endedEvent.parentTxId(), is(transactionLocalTxId)); + assertThat(endedEvent.type(), is(EventType.TxEndedEvent)); + + assertThat(omegaContext.globalTxId(), is(transactionGloablTxId)); + assertThat(omegaContext.localTxId(), is(transactionLocalTxId)); } @Test
