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 <willem.ji...@gmail.com> 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 <willem.ji...@gmail.com> 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 <chanjars...@gmail.com> 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 <zhang_...@boco.com.cn> 于2019年7月25日周四 下午4:46写道:
> > >
> > >
> > > Zhang Lei <zhang_...@boco.com.cn> 于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 <chanjars...@gmail.com> 写道:
> > > > >
> > > > > 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

Reply via email to