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 <[email protected]> 于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 <[email protected]> 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

Reply via email to