I'm assuming one scenario for service invoke chain: OrderService -> ProductService -> UserService. Three services will share one global tx. Maybe I'm wrong, but it seems this is impossible to achieve with current AT mode ^?
The follow func will start a new global tx (providing ctx doesn't hold any global tx information), and directly commit or rollback this new global tx. No chances are left to pass this newly created global tx to downstream services (product service, user service).
Global tx XID can be passed from init order service to downstream user service, and when this service invoke chain has finished, the init order service can decide whether commit or rollback this global tx.
Something like this
func main() {
client.InitPath("../../conf/seatago.yml")
db = util.GetAtMySqlDb()
orderCtx := context.Background()
defer func() {
// isSuccess is determined by the returned result from product service and
// user service. If all goes well, isSuccess = true, otherwise isSuccess = false.
tm.CommitOrRollback(orderCtx, isSuccess)
}()
// order service needs an insert
orderServiceInsert(orderCtx)
// order service sends rpc call to product service
time.Sleep(2 * time.Second)
// product service has received this rpc request.
// This request has included order service's global tx's XID, so product service can
// implement its actions within the same global tx.
productCtx := context.Background()
tm.SetXID(productCtx, "{XID received from order service}")
productServiceInsert(productCtx)
// product service sends rpc call to user service.
time.Sleep(2 * time.Second)
// user service has received this rpc request.
// This request has included product service's global tx's XID, so user service can
// implement its actions within the same global tx.
userCtx := context.Background()
tm.SetXID(userCtx, "{XID received from product service}")
userServiceInsert(userCtx)
<-make(chan struct{})
}
func orderServiceInsert(ctx context.Context) {
tm.WithGlobalTx(ctx, &tm.GtxConfig{
Name: "ATSampleLocalGlobalTx_Insert",
Timeout: time.Second * 30,
}, insertData)
}
func productServiceInsert(ctx context.Context) {
tm.WithGlobalTx(ctx, &tm.GtxConfig{
Name: "ATSampleLocalGlobalTx_Insert",
// This action must be under a global tx scope.
// For example, it must be invoked from order service's rpc request
Propagation: tm.Mandatory,
Timeout: time.Second * 30,
}, insertData)
}
func userServiceInsert(ctx context.Context) {
tm.WithGlobalTx(ctx, &tm.GtxConfig{
Name: "ATSampleLocalGlobalTx_Insert",
// This action must be under a global tx scope.
// For example, it must be invoked from product service's rpc request
Propagation: tm.Mandatory,
Timeout: time.Second * 30,
}, insertData)
}
How to reproduce it (as minimally and precisely as possible):
What happened:
I'm assuming one scenario for service invoke chain: OrderService -> ProductService -> UserService. Three services will share one global tx. Maybe I'm wrong, but it seems this is impossible to achieve with current AT mode ^?
The follow func will start a new global tx (providing
ctx
doesn't hold any global tx information), and directly commit or rollback this new global tx. No chances are left to pass this newly created global tx to downstream services (product service, user service).commitOrRollback is within
tm.WithGlobalTx
already.What you expected to happen:
Global tx XID can be passed from init order service to downstream user service, and when this service invoke chain has finished, the init order service can decide whether commit or rollback this global tx.
Something like this
How to reproduce it (as minimally and precisely as possible):
Anything else we need to know?: