Hi, Willem Do you mean by sending a TxAsyncStartEvent to Alpha before executing the asynchronous method?
Conversation: Omega: Hi, Alpha an asynchronous method is about to start, please wait until you received sub-transaction events Alpha: Ok, I will wait until I receive a TxStartedEvent and a TxEndedEvent or a TxAbortedEvent before ending the transaction. Lei Zhang > 在 2019年7月30日,上午8:49,Willem Jiang <[email protected]> 写道: > > To send out the TxAasyncStart, we have to intercept the async > invocation to send out the event. It's could be a challenge for us to > list all the async invocation. > > Willem Jiang > > Twitter: willemjiang > Weibo: 姜宁willem > > On Tue, Jul 30, 2019 at 8:40 AM Willem Jiang <[email protected]> wrote: >> >> According to the feedback for PR, I think we need to rethink about the >> SagaEnd implementation in the Async invocation scenario. Normally it's >> harmless we close the Saga transaction later, but we need to make sure >> all the ongoing local transaction are finished. >> >> In the old way, Alpha can know nothing about the start of Async >> Componseable transaction if the TxStartedEvent is not sent, so my >> propose that we introduce a new event TxAsyncStart to tell Alpha there >> is new Async invocation, so Alpha can keep tracking this Async >> invocation event the Componseable transaction is not started yet. In >> this way we could block the Async invocation if the Saga transaction >> is timeout or close the Saga transaction if all the TxAsyncStart >> transaction is finished. >> >> Any thoughts? >> >> Willem Jiang >> >> Twitter: willemjiang >> Weibo: 姜宁willem >> >> On Mon, Jul 29, 2019 at 5:32 PM Willem Jiang <[email protected]> wrote: >>> >>> Export the low level API could introduce some error if the user >>> doesn't use the API rightly. >>> My suggestion is we just >>> BTW, I submit a PR[1] to address this issue in a simple way (But we >>> still need to tell user what's the right way to configure the >>> annotation attribute). >>> >>> [1]https://github.com/apache/servicecomb-pack/pull/517 >>> >>> Willem Jiang >>> >>> Twitter: willemjiang >>> Weibo: 姜宁willem >>> >>> On Thu, Jul 25, 2019 at 8:44 PM Daniel Qian <[email protected]> wrote: >>>> >>>> Hi Zhang Lei, >>>> >>>> What I'm trying to say is to provide a way for user to send >>>> TxEndedEvent, TxAbortedEvent, TxCompensatedEvent, SagaEndedEvent ... >>>> explicitly on Omega side. >>>> Because current implementation doesn't support following situation(async): >>>> >>>> @Compensable(compensationMethod="rollbackFoo") >>>> public void foo() { >>>> new Thread(() -> /* local tx goes here */).start(); >>>> // TxEndedEvent sent when returns, it's too early >>>> } >>>> >>>> public void rollbackFoo() { >>>> new Thread(() -> /* compensation goes here*/).start(); >>>> // TxCompensatedEvent sent when returns, it's too early >>>> } >>>> >>>> @SagaStart >>>> public void bar() { >>>> new Thread(() -> /* call other service goes here */).start(); >>>> // SagaEndedEvent sent when returns, it's too early >>>> } >>>> >>>> I suggest providing a helper class, called omega or something else, >>>> user can use it to send TxEndedEvent, TxAbortedEvent, >>>> TxCompensatedEvent, SagaEndedEvent, etc. So the code goes like this: >>>> >>>> @Compensable(async=true, compensationMethod="rollbackFoo", >>>> compensationAsync=true) >>>> public void foo() { >>>> TransactionContext txContext = omegaContext.getTransactionContext(); >>>> new Thread(() -> { >>>> try { >>>> /* local tx goes here */ >>>> omega.txEnded(txContext); >>>> } catch(Exception e) { >>>> omega.txAborted(txContext); >>>> } >>>> }).start(); >>>> } >>>> >>>> public void rollbackFoo() { >>>> TransactionContext txContext = omegaContext.getTransactionContext(); >>>> new Thread(() -> { >>>> /*compensation goes here*/ >>>> omega.txCompensated() >>>> }).start(); >>>> } >>>> >>>> @SagaStart(async=true) >>>> public void bar() { >>>> TransactionContext txContext = omegaContext.getTransactionContext(); >>>> new Thread(() -> { >>>> /* call other service goes here */ >>>> try { >>>> omega.sagaEnded(txContext); >>>> } catch (Exception e) { >>>> omega.sagaAborted(txContext); >>>> } >>>> }).start(); >>>> } >>>> >>>> >>>> Zhang Lei <[email protected]> 于2019年7月25日周四 下午4:46写道: >>>> >>>> >>>> Zhang Lei <[email protected]> 于2019年7月25日周四 下午4:46写道: >>>>> >>>>> Hi, Daniel Qian >>>>> >>>>> Are you talking about the asynchronous problem with the @SagaStart and >>>>> @Compensable methods on the Omega side? I think this is a typical long >>>>> transaction scene. >>>>> >>>>> Alpha based on Actor model has implemented asynchronous processing of >>>>> Omega and Alpha, The event sent to Alpha needs to ensure that all child >>>>> transactions have been executed before sending SagaEndedEvent or >>>>> SagaAbortedEvent. >>>>> >>>>> Lei Zhang >>>>> >>>>>> 在 2019年7月20日,下午9:49,Daniel Qian <[email protected]> 写道: >>>>>> >>>>>> After look into SCB-163, SCB-1385 and SCB-1386 I have some thoughts on >>>>>> Saga >>>>>> involved in async invocation. >>>>>> Current implementation is basically based on sync invocation, there are >>>>>> some assumption: >>>>>> >>>>>> 1. When @SagaStart method returns, the Saga finished. >>>>>> 2. When @Compensable method returns/throws exception, the Local Tx >>>>>> succeeds/failed. >>>>>> 3. When compensationMethod returns, the Local Tx is compensated. >>>>>> >>>>>> Even if considering what SCB-100 provided: >>>>>> >>>>>> 1. Add @OmegaContextAware annotation enabling >>>>>> java.util.concurrent.Executor inject OmegaConext into threads it >>>>>> manages/spawns >>>>>> 2. Make OmegaContext use InheritableThreadLocal field let child thread >>>>>> inherit parent thread's Local Tx info >>>>>> >>>>>> There are still some limitations: >>>>>> >>>>>> 1. @OmegaContextAware is only viable if you use spring framework >>>>>> 2. @OmegaContextAware and OmegaContext's InheritableThreadLocal field >>>>>> assuming that the calling thread or initator thread has Local Tx info. >>>>>> >>>>>> >>>>>> What if user code use producer-consumer pattern in which >>>>>> InheritableThreadLocal can't work? >>>>>> What if user code use a thread scheduling library which we cannot use >>>>>> @OmegaContextAware,RxJava and Reactor, for example? >>>>>> I think we could provide some low-level APIs that user code can manualy >>>>>> starts/ends Saga and Local Tx, something like below: >>>>>> >>>>>> TxContext context = omega.startSaga(); >>>>>> TxContext subTxContext = omega.startTx(TxContext parentTxContext); >>>>>> omega.endTx(TxContext); >>>>>> omega.abortTx(TxContext); >>>>>> omega.abortSaga(TxContext); >>>>>> omega.endSaga(TxContext); >>>>>> >>>>>> TxContext is just a immutable dto like this: >>>>>> >>>>>> public class TxContext { >>>>>> private final String globalTxId; >>>>>> private final String localTxId; >>>>>> } >>>>>> >>>>>> Above is a just a rough idea. So any thoughts? >>>>>> -- >>>>>> Daniel Qian >>>>>> >>>>>> 博客:https://segmentfault.com/u/chanjarster >>>>>> github:https://github.com/chanjarster >>>>> >>>> >>>> >>>> -- >>>> Daniel Qian >>>> >>>> 博客:https://segmentfault.com/u/chanjarster >>>> github:https://github.com/chanjarster
