Thanks for the suggestion, Feng.

Did you mean Alpha check if the compensation method finished by
periodically query @Status method?

If I'm not misunderstanding the code, Alpha doesn't wait for the
TxCompensatedEvent after
CompensateCommand sent. That means, the
CompensateCommand-TxCompensatedEvent
communication is already async in nature.

So we can take advantage of this async nature and no need to add more event
types and statuses.
I think we can add an attribute to indicate compensation method is async on
@Compensable like this:

@Compensale(compensationMethod="rollbackBar", compensationAsync=true)
public void bar(arg1, arg2, arg3) {
   // ...
}

public void rollbackBar(arg1, arg2, arg3, TransactionContextWithParent
localTx) {
  rollbackAsync()
    .onsuccess(() -> {
       omega.txCompensated(localTx);
  })
}

Zheng Feng <zh.f...@gmail.com> 于2019年7月22日周一 下午5:14写道:

> In term of the compensation method, I think I had discussed with Willem
> before that it could introduce the @Status annotation for the alpha server
> to query the compensation status. When the compensation method is async
> which means it can not response immediately, it would return the
> COMPENSATING result and the alpha server could query the @Status method to
> check the compensation status, if this method returns COMPENSATE_OK, the
> alpha server will mark the local transaction is compensated otherwise will
> mark it with compensate_failed.
>
> Daniel Qian <chanjars...@gmail.com> 于2019年7月21日周日 下午8:37写道:
>
> > I rethink the idea I proposed, yes, provide low level apis is a bad idea,
> > and I also don't suggest that let user code use omega-xxx-transport api.
> >
> > I think the essential issues are three:
> >
> >    1. How to pass tx context info across threads
> >    2. How to asynchronously tell Alpha that Saga is ended or aborted,
> which
> >    means not triggered on @SagaStart method returns.
> >    3. How to asynchronously tell Alpha that LocalTx is ended or aborted,
> >    which means not triggered on @Compensable method returns.
> >
> > I think we can keep using @SagaStart @Compensable for the
> XXXStartedEvent,
> > and provide a helper to manually end/abort Saga/LocalTx. Thanks for PR
> #506
> > (SCB-1385) we can use TransactionContext to achieve that. Below is a code
> > sample:
> >
> >
> > @SagaStart(async=true)
> > public void foo() {
> >    TransactionContext txContext = OmegaContext.getTransactionContext();
> >    someAsyncCall()
> >      .onSuccess(Callback() {
> >         omega.endSaga(txContext);
> >      })
> >      .onException(Callback() {
> >         omega.abortSaga(txContext);
> >      })
> > }
> >
> > @Compensable(async=true, compensationMethod="rollbackBar")
> > public void bar() {
> >    TransactionContext txContext = OmegaContext.getTransactionContext();
> >    someAsyncCall()
> >      .onSuccess(Callback() {
> >         omega.endTx(txContext);
> >      })
> >      .onException(Callback() {
> >         omega.abortTx(txContext);
> >      })
> > }
> >
> > The async attribute on @SagaStart and @Compensable prevents Saga/LocalTx
> > ended when method returns.
> > TransactionContext object can be passed around safely because it's
> > immutable.
> > What I have not considered clearly is that how to deal with compensation
> > method if it's also async.
> >
> >
> > Willem Jiang <willem.ji...@gmail.com> 于2019年7月20日周六 下午10:30写道:
> > >
> > > Yeah, I agree we need provide some low level API for the user to pass.
> > > In the recent change of SCB-1386, I introduce the TransactionContext
> > > object which holds the reference of GID and LID, we may add some other
> > > transaction context information there too.
> > > If the sub transaction is happened in other JVM, we need to pass the
> > > TxContext across the JVM with help of omega-xxx-transport.
> > >
> > > We already have some internal API to send the message from Omega to
> > > Alpha, I prefer to use annotation instead of expose low level API to
> > > the user.
> > >
> > > Willem Jiang
> > >
> > > Twitter: willemjiang
> > > Weibo: 姜宁willem
> > >
> > > On Sat, Jul 20, 2019 at 9:50 PM Daniel Qian <chanjars...@gmail.com>
> > wrote:
> > > >
> > > > 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
> >
>


-- 
Daniel Qian

博客:https://segmentfault.com/u/chanjarster
github:https://github.com/chanjarster

Reply via email to