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
