clear failure

This commit is contained in:
yedf2 2021-08-03 16:19:31 +08:00
parent a94761d7f6
commit b20d18ecbb
12 changed files with 42 additions and 98 deletions

View File

@ -59,6 +59,6 @@ func (s *Msg) Submit() error {
} }
// SubmitExt 高级submit更多的选项和更详细的返回值 // SubmitExt 高级submit更多的选项和更详细的返回值
func (s *Msg) SubmitExt(opt *TransOptions) (TransStatus, error) { func (s *Msg) SubmitExt(opt *TransOptions) error {
return CallDtm(s.Server, &s.MsgData, "submit", opt) return CallDtm(s.Server, &s.MsgData, "submit", opt)
} }

View File

@ -50,11 +50,10 @@ func (s *Saga) Add(action string, compensate string, postData interface{}) *Saga
// Submit submit the saga trans // Submit submit the saga trans
func (s *Saga) Submit() error { func (s *Saga) Submit() error {
_, err := s.SubmitExt(&TransOptions{}) return s.SubmitExt(&TransOptions{})
return err
} }
// SubmitExt 高级submit更多的选项和更详细的返回值 // SubmitExt 高级submit更多的选项和更详细的返回值
func (s *Saga) SubmitExt(opt *TransOptions) (TransStatus, error) { func (s *Saga) SubmitExt(opt *TransOptions) error {
return CallDtm(s.Server, &s.SagaData, "submit", opt) return CallDtm(s.Server, &s.SagaData, "submit", opt)
} }

View File

@ -22,22 +22,22 @@ type TccGlobalFunc func(tcc *Tcc) (*resty.Response, error)
// dtm dtm服务器地址 // dtm dtm服务器地址
// gid 全局事务id // gid 全局事务id
// tccFunc tcc事务函数里面会定义全局事务的分支 // tccFunc tcc事务函数里面会定义全局事务的分支
func TccGlobalTransaction(dtm string, gid string, tccFunc TccGlobalFunc) (status TransStatus, rerr error) { func TccGlobalTransaction(dtm string, gid string, tccFunc TccGlobalFunc) (rerr error) {
data := &M{ data := &M{
"gid": gid, "gid": gid,
"trans_type": "tcc", "trans_type": "tcc",
} }
tcc := &Tcc{Dtm: dtm, Gid: gid} tcc := &Tcc{Dtm: dtm, Gid: gid}
status, rerr = CallDtm(dtm, data, "prepare", &TransOptions{}) rerr = CallDtm(dtm, data, "prepare", &TransOptions{})
if rerr != nil { if rerr != nil {
return status, rerr return rerr
} }
// 小概率情况下prepare成功了但是由于网络状况导致上面Failure那么不执行下面defer的内容等待超时后再回滚标记事务失败也没有问题 // 小概率情况下prepare成功了但是由于网络状况导致上面Failure那么不执行下面defer的内容等待超时后再回滚标记事务失败也没有问题
defer func() { defer func() {
x := recover() x := recover()
var err error var err error
operation := common.If(x == nil && rerr == nil, "submit", "abort").(string) operation := common.If(x == nil && rerr == nil, "submit", "abort").(string)
status, err = CallDtm(dtm, data, operation, &TransOptions{}) err = CallDtm(dtm, data, operation, &TransOptions{})
if rerr == nil { if rerr == nil {
rerr = err rerr = err
} }
@ -67,7 +67,7 @@ func TccFromReq(c *gin.Context) (*Tcc, error) {
// 函数首先注册子事务的所有分支成功后调用try分支返回try分支的调用结果 // 函数首先注册子事务的所有分支成功后调用try分支返回try分支的调用结果
func (t *Tcc) CallBranch(body interface{}, tryURL string, confirmURL string, cancelURL string) (*resty.Response, error) { func (t *Tcc) CallBranch(body interface{}, tryURL string, confirmURL string, cancelURL string) (*resty.Response, error) {
branchID := t.NewBranchID() branchID := t.NewBranchID()
_, err := CallDtm(t.Dtm, &M{ err := CallDtm(t.Dtm, &M{
"gid": t.Gid, "gid": t.Gid,
"branch_id": branchID, "branch_id": branchID,
"trans_type": "tcc", "trans_type": "tcc",

View File

@ -19,21 +19,6 @@ func MustGenGid(server string) string {
return res["gid"] return res["gid"]
} }
// IsFailure 如果err非空或者ret是http的响应且包含FAILURE那么返回true。此时认为业务调用失败
func IsFailure(res interface{}, err error) bool {
resp, ok := res.(*resty.Response)
return err != nil || // 包含错误
ok && (resp.IsError() || strings.Contains(resp.String(), "FAILURE")) || // resp包含failure
!ok && res != nil && strings.Contains(common.MustMarshalString(res), "FAILURE") // 结果中包含failure
}
// PanicIfFailure 如果err非空或者ret是http的响应且包含FAILURE那么Panic。此时认为业务调用失败
func PanicIfFailure(res interface{}, err error) {
if IsFailure(res, err) {
panic(fmt.Errorf("dtm failure ret: %v err %v", res, err))
}
}
// CheckResponse 检查Response返回错误 // CheckResponse 检查Response返回错误
func CheckResponse(resp *resty.Response, err error) error { func CheckResponse(resp *resty.Response, err error) error {
if err == nil && resp != nil { if err == nil && resp != nil {
@ -58,17 +43,6 @@ func CheckResult(res interface{}, err error) error {
return err return err
} }
// CheckDtmResponse check the response of dtm, if not ok ,generate error
func CheckDtmResponse(resp *resty.Response, err error) error {
if err != nil {
return err
}
if !strings.Contains(resp.String(), "SUCCESS") || resp.IsError() {
return fmt.Errorf("dtm response failed: %s", resp.String())
}
return nil
}
// IDGenerator used to generate a branch id // IDGenerator used to generate a branch id
type IDGenerator struct { type IDGenerator struct {
parentID string parentID string
@ -87,28 +61,6 @@ func (g *IDGenerator) NewBranchID() string {
return g.parentID + fmt.Sprintf("%02d", g.branchID) return g.parentID + fmt.Sprintf("%02d", g.branchID)
} }
// TransStatus 全局事务状态采用string
type TransStatus string
const (
// TransEmpty 空值
TransEmpty TransStatus = ""
// TransSubmitted 已提交给DTM
TransSubmitted TransStatus = "submitted"
// TransAborting 正在回滚中有两种情况会出现一是用户侧发起abort请求而是发起submit同步请求但是dtm进行回滚中出现错误
TransAborting TransStatus = "aborting"
// TransSucceed 事务已完成
TransSucceed TransStatus = "succeed"
// TransFailed 事务已回滚
TransFailed TransStatus = "failed"
// TransErrorPrepare prepare调用报错
TransErrorPrepare TransStatus = "error_parepare"
// TransErrorSubmit submit调用报错
TransErrorSubmit TransStatus = "error_submit"
// TransErrorAbort abort调用报错
TransErrorAbort TransStatus = "error_abort"
)
// TransOptions 提交/终止事务的选项 // TransOptions 提交/终止事务的选项
type TransOptions struct { type TransOptions struct {
// WaitResult 是否等待全局事务的最终结果 // WaitResult 是否等待全局事务的最终结果
@ -118,28 +70,26 @@ type TransOptions struct {
// TransResult dtm 返回的结果 // TransResult dtm 返回的结果
type TransResult struct { type TransResult struct {
DtmResult string `json:"dtm_result"` DtmResult string `json:"dtm_result"`
Status TransStatus
Message string Message string
} }
func CallDtm(dtm string, body interface{}, operation string, opt *TransOptions) (TransStatus, error) { // CallDtm 调用dtm服务器返回事务的状态
func CallDtm(dtm string, body interface{}, operation string, opt *TransOptions) error {
resp, err := common.RestyClient.R().SetQueryParams(common.MS{ resp, err := common.RestyClient.R().SetQueryParams(common.MS{
"wait_result": common.If(opt.WaitResult, "1", "").(string), "wait_result": common.If(opt.WaitResult, "1", "").(string),
}).SetResult(&TransResult{}).SetBody(body).Post(fmt.Sprintf("%s/%s", dtm, operation)) }).SetResult(&TransResult{}).SetBody(body).Post(fmt.Sprintf("%s/%s", dtm, operation))
errStatus := TransStatus("error_" + operation)
if err != nil { if err != nil {
return errStatus, err return err
} }
tr := resp.Result().(*TransResult) tr := resp.Result().(*TransResult)
if tr.DtmResult == "FAILURE" { if tr.DtmResult == "FAILURE" {
return errStatus, errors.New(tr.Message) return errors.New("FAILURE: " + tr.Message)
} }
return tr.Status, nil return nil
} }
func callDtmSimple(dtm string, body interface{}, operation string) error { func callDtmSimple(dtm string, body interface{}, operation string) error {
_, err := CallDtm(dtm, body, operation, &TransOptions{}) return CallDtm(dtm, body, operation, &TransOptions{})
return err
} }
// ErrFailure 表示返回失败,要求回滚 // ErrFailure 表示返回失败,要求回滚

View File

@ -1,7 +1,6 @@
package dtmcli package dtmcli
import ( import (
"fmt"
"net/url" "net/url"
"testing" "testing"
@ -22,8 +21,4 @@ func TestTypes(t *testing.T) {
assert.Error(t, err) assert.Error(t, err)
_, err = TransInfoFromQuery(url.Values{}) _, err = TransInfoFromQuery(url.Values{})
assert.Error(t, err) assert.Error(t, err)
err2 := fmt.Errorf("an error")
err3 := CheckDtmResponse(nil, err2)
assert.Error(t, err2, err3)
} }

View File

@ -99,18 +99,18 @@ func (xc *XaClient) XaLocalTransaction(c *gin.Context, xaFunc XaLocalFunc) (ret
if rerr != nil { if rerr != nil {
return return
} }
_, rerr = CallDtm(xc.Server, &M{"gid": xa.Gid, "branch_id": branchID, "trans_type": "xa", "status": "prepared", "url": xc.CallbackURL}, "registerXaBranch", &TransOptions{}) rerr = CallDtm(xc.Server, &M{"gid": xa.Gid, "branch_id": branchID, "trans_type": "xa", "status": "prepared", "url": xc.CallbackURL}, "registerXaBranch", &TransOptions{})
return return
} }
// XaGlobalTransaction start a xa global transaction // XaGlobalTransaction start a xa global transaction
func (xc *XaClient) XaGlobalTransaction(gid string, xaFunc XaGlobalFunc) (status TransStatus, rerr error) { func (xc *XaClient) XaGlobalTransaction(gid string, xaFunc XaGlobalFunc) (rerr error) {
xa := Xa{IDGenerator: IDGenerator{}, Gid: gid} xa := Xa{IDGenerator: IDGenerator{}, Gid: gid}
data := &M{ data := &M{
"gid": gid, "gid": gid,
"trans_type": "xa", "trans_type": "xa",
} }
status, rerr = CallDtm(xc.Server, data, "prepare", &TransOptions{}) rerr = CallDtm(xc.Server, data, "prepare", &TransOptions{})
if rerr != nil { if rerr != nil {
return return
} }
@ -118,9 +118,8 @@ func (xc *XaClient) XaGlobalTransaction(gid string, xaFunc XaGlobalFunc) (status
// 小概率情况下prepare成功了但是由于网络状况导致上面Failure那么不执行下面defer的内容等待超时后再回滚标记事务失败也没有问题 // 小概率情况下prepare成功了但是由于网络状况导致上面Failure那么不执行下面defer的内容等待超时后再回滚标记事务失败也没有问题
defer func() { defer func() {
x := recover() x := recover()
operation := common.If(x != nil || IsFailure(resp, rerr), "abort", "submit").(string) operation := common.If(x != nil || rerr != nil, "abort", "submit").(string)
var err error err := CallDtm(xc.Server, data, operation, &TransOptions{})
status, err = CallDtm(xc.Server, data, operation, &TransOptions{})
if rerr == nil { // 如果用户函数没有返回错误那么返回dtm的 if rerr == nil { // 如果用户函数没有返回错误那么返回dtm的
rerr = err rerr = err
} }
@ -129,6 +128,7 @@ func (xc *XaClient) XaGlobalTransaction(gid string, xaFunc XaGlobalFunc) (status
} }
}() }()
resp, rerr = xaFunc(&xa) resp, rerr = xaFunc(&xa)
rerr = CheckResponse(resp, rerr)
return return
} }

View File

@ -24,19 +24,19 @@ func TestTccBarrier(t *testing.T) {
func tccBarrierRollback(t *testing.T) { func tccBarrierRollback(t *testing.T) {
gid := "tccBarrierRollback" gid := "tccBarrierRollback"
resp, err := dtmcli.TccGlobalTransaction(DtmServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { err := dtmcli.TccGlobalTransaction(DtmServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) {
resp, err := tcc.CallBranch(&examples.TransReq{Amount: 30}, Busi+"/TccBTransOutTry", Busi+"/TccBTransOutConfirm", Busi+"/TccBTransOutCancel") _, err := tcc.CallBranch(&examples.TransReq{Amount: 30}, Busi+"/TccBTransOutTry", Busi+"/TccBTransOutConfirm", Busi+"/TccBTransOutCancel")
assert.True(t, !dtmcli.IsFailure(resp, err)) assert.Nil(t, err)
return tcc.CallBranch(&examples.TransReq{Amount: 30, TransInResult: "FAILURE"}, Busi+"/TccBTransInTry", Busi+"/TccBTransInConfirm", Busi+"/TccBTransInCancel") return tcc.CallBranch(&examples.TransReq{Amount: 30, TransInResult: "FAILURE"}, Busi+"/TccBTransInTry", Busi+"/TccBTransInConfirm", Busi+"/TccBTransInCancel")
}) })
assert.True(t, dtmcli.IsFailure(resp, err)) assert.Error(t, err)
WaitTransProcessed(gid) WaitTransProcessed(gid)
assert.Equal(t, "failed", getTransStatus(gid)) assert.Equal(t, "failed", getTransStatus(gid))
} }
func tccBarrierNormal(t *testing.T) { func tccBarrierNormal(t *testing.T) {
gid := "tccBarrierNormal" gid := "tccBarrierNormal"
_, err := dtmcli.TccGlobalTransaction(DtmServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { err := dtmcli.TccGlobalTransaction(DtmServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) {
_, err := tcc.CallBranch(&examples.TransReq{Amount: 30}, Busi+"/TccBTransOutTry", Busi+"/TccBTransOutConfirm", Busi+"/TccBTransOutCancel") _, err := tcc.CallBranch(&examples.TransReq{Amount: 30}, Busi+"/TccBTransOutTry", Busi+"/TccBTransOutConfirm", Busi+"/TccBTransOutCancel")
assert.Nil(t, err) assert.Nil(t, err)
return tcc.CallBranch(&examples.TransReq{Amount: 30}, Busi+"/TccBTransInTry", Busi+"/TccBTransInConfirm", Busi+"/TccBTransInCancel") return tcc.CallBranch(&examples.TransReq{Amount: 30}, Busi+"/TccBTransInTry", Busi+"/TccBTransInConfirm", Busi+"/TccBTransInCancel")
@ -50,7 +50,7 @@ func tccBarrierDisorder(t *testing.T) {
timeoutChan := make(chan string, 2) timeoutChan := make(chan string, 2)
finishedChan := make(chan string, 2) finishedChan := make(chan string, 2)
gid := "tccBarrierDisorder" gid := "tccBarrierDisorder"
_, err := dtmcli.TccGlobalTransaction(DtmServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { err := dtmcli.TccGlobalTransaction(DtmServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) {
body := &examples.TransReq{Amount: 30} body := &examples.TransReq{Amount: 30}
tryURL := Busi + "/TccBTransOutTry" tryURL := Busi + "/TccBTransOutTry"
confirmURL := Busi + "/TccBTransOutConfirm" confirmURL := Busi + "/TccBTransOutConfirm"
@ -69,7 +69,7 @@ func tccBarrierDisorder(t *testing.T) {
return res, err return res, err
})) }))
// 注册子事务 // 注册子事务
_, err := dtmcli.CallDtm(tcc.Dtm, M{ err := dtmcli.CallDtm(tcc.Dtm, M{
"gid": tcc.Gid, "gid": tcc.Gid,
"branch_id": branchID, "branch_id": branchID,
"trans_type": "tcc", "trans_type": "tcc",

View File

@ -19,7 +19,7 @@ func TestTcc(t *testing.T) {
func tccNormal(t *testing.T) { func tccNormal(t *testing.T) {
data := &examples.TransReq{Amount: 30} data := &examples.TransReq{Amount: 30}
gid := "tccNormal" gid := "tccNormal"
_, err := dtmcli.TccGlobalTransaction(examples.DtmServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { err := dtmcli.TccGlobalTransaction(examples.DtmServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) {
_, err := tcc.CallBranch(data, Busi+"/TransOut", Busi+"/TransOutConfirm", Busi+"/TransOutRevert") _, err := tcc.CallBranch(data, Busi+"/TransOut", Busi+"/TransOutConfirm", Busi+"/TransOutRevert")
assert.Nil(t, err) assert.Nil(t, err)
return tcc.CallBranch(data, Busi+"/TransIn", Busi+"/TransInConfirm", Busi+"/TransInRevert") return tcc.CallBranch(data, Busi+"/TransIn", Busi+"/TransInConfirm", Busi+"/TransInRevert")
@ -30,7 +30,7 @@ func tccNormal(t *testing.T) {
func tccRollback(t *testing.T) { func tccRollback(t *testing.T) {
gid := "tccRollback" gid := "tccRollback"
data := &examples.TransReq{Amount: 30, TransInResult: "FAILURE"} data := &examples.TransReq{Amount: 30, TransInResult: "FAILURE"}
_, err := dtmcli.TccGlobalTransaction(examples.DtmServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { err := dtmcli.TccGlobalTransaction(examples.DtmServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) {
_, rerr := tcc.CallBranch(data, Busi+"/TransOut", Busi+"/TransOutConfirm", Busi+"/TransOutRevert") _, rerr := tcc.CallBranch(data, Busi+"/TransOut", Busi+"/TransOutConfirm", Busi+"/TransOutRevert")
assert.Nil(t, rerr) assert.Nil(t, rerr)
examples.MainSwitch.TransOutRevertResult.SetOnce("PENDING") examples.MainSwitch.TransOutRevertResult.SetOnce("PENDING")

View File

@ -21,7 +21,7 @@ func TestXa(t *testing.T) {
func xaLocalError(t *testing.T) { func xaLocalError(t *testing.T) {
xc := examples.XaClient xc := examples.XaClient
_, err := xc.XaGlobalTransaction("xaLocalError", func(xa *dtmcli.Xa) (*resty.Response, error) { err := xc.XaGlobalTransaction("xaLocalError", func(xa *dtmcli.Xa) (*resty.Response, error) {
return nil, fmt.Errorf("an error") return nil, fmt.Errorf("an error")
}) })
assert.Error(t, err, fmt.Errorf("an error")) assert.Error(t, err, fmt.Errorf("an error"))
@ -30,7 +30,7 @@ func xaLocalError(t *testing.T) {
func xaNormal(t *testing.T) { func xaNormal(t *testing.T) {
xc := examples.XaClient xc := examples.XaClient
gid := "xaNormal" gid := "xaNormal"
_, err := xc.XaGlobalTransaction(gid, func(xa *dtmcli.Xa) (*resty.Response, error) { err := xc.XaGlobalTransaction(gid, func(xa *dtmcli.Xa) (*resty.Response, error) {
req := examples.GenTransReq(30, false, false) req := examples.GenTransReq(30, false, false)
resp, err := xa.CallBranch(req, examples.Busi+"/TransOutXa") resp, err := xa.CallBranch(req, examples.Busi+"/TransOutXa")
if err != nil { if err != nil {
@ -46,7 +46,7 @@ func xaNormal(t *testing.T) {
func xaRollback(t *testing.T) { func xaRollback(t *testing.T) {
xc := examples.XaClient xc := examples.XaClient
gid := "xaRollback" gid := "xaRollback"
_, err := xc.XaGlobalTransaction(gid, func(xa *dtmcli.Xa) (*resty.Response, error) { err := xc.XaGlobalTransaction(gid, func(xa *dtmcli.Xa) (*resty.Response, error) {
req := &examples.TransReq{Amount: 30, TransInResult: "FAILURE"} req := &examples.TransReq{Amount: 30, TransInResult: "FAILURE"}
resp, err := xa.CallBranch(req, examples.Busi+"/TransOutXa") resp, err := xa.CallBranch(req, examples.Busi+"/TransOutXa")
if err != nil { if err != nil {

View File

@ -21,14 +21,14 @@ func TccSetup(app *gin.Engine) {
// TccFireRequestNested 1 // TccFireRequestNested 1
func TccFireRequestNested() string { func TccFireRequestNested() string {
gid := dtmcli.MustGenGid(DtmServer) gid := dtmcli.MustGenGid(DtmServer)
ret, err := dtmcli.TccGlobalTransaction(DtmServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { err := dtmcli.TccGlobalTransaction(DtmServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) {
resp, err := tcc.CallBranch(&TransReq{Amount: 30}, Busi+"/TransOut", Busi+"/TransOutConfirm", Busi+"/TransOutRevert") resp, err := tcc.CallBranch(&TransReq{Amount: 30}, Busi+"/TransOut", Busi+"/TransOutConfirm", Busi+"/TransOutRevert")
if dtmcli.IsFailure(resp, err) { if err != nil {
return resp, err return resp, err
} }
return tcc.CallBranch(&TransReq{Amount: 30}, Busi+"/TransInTccParent", Busi+"/TransInConfirm", Busi+"/TransInRevert") return tcc.CallBranch(&TransReq{Amount: 30}, Busi+"/TransInTccParent", Busi+"/TransInConfirm", Busi+"/TransInRevert")
}) })
dtmcli.PanicIfFailure(ret, err) e2p(err)
return gid return gid
} }
@ -36,13 +36,13 @@ func TccFireRequestNested() string {
func TccFireRequest() string { func TccFireRequest() string {
logrus.Printf("tcc simple transaction begin") logrus.Printf("tcc simple transaction begin")
gid := dtmcli.MustGenGid(DtmServer) gid := dtmcli.MustGenGid(DtmServer)
ret, err := dtmcli.TccGlobalTransaction(DtmServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { err := dtmcli.TccGlobalTransaction(DtmServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) {
resp, err := tcc.CallBranch(&TransReq{Amount: 30}, Busi+"/TransOut", Busi+"/TransOutConfirm", Busi+"/TransOutRevert") resp, err := tcc.CallBranch(&TransReq{Amount: 30}, Busi+"/TransOut", Busi+"/TransOutConfirm", Busi+"/TransOutRevert")
if dtmcli.IsFailure(resp, err) { if err != nil {
return resp, err return resp, err
} }
return tcc.CallBranch(&TransReq{Amount: 30}, Busi+"/TransIn", Busi+"/TransInConfirm", Busi+"/TransInRevert") return tcc.CallBranch(&TransReq{Amount: 30}, Busi+"/TransIn", Busi+"/TransInConfirm", Busi+"/TransInRevert")
}) })
dtmcli.PanicIfFailure(ret, err) e2p(err)
return gid return gid
} }

View File

@ -15,14 +15,14 @@ import (
func TccBarrierFireRequest() string { func TccBarrierFireRequest() string {
logrus.Printf("tcc transaction begin") logrus.Printf("tcc transaction begin")
gid := dtmcli.MustGenGid(DtmServer) gid := dtmcli.MustGenGid(DtmServer)
ret, err := dtmcli.TccGlobalTransaction(DtmServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { err := dtmcli.TccGlobalTransaction(DtmServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) {
resp, err := tcc.CallBranch(&TransReq{Amount: 30}, Busi+"/TccBTransOutTry", Busi+"/TccBTransOutConfirm", Busi+"/TccBTransOutCancel") resp, err := tcc.CallBranch(&TransReq{Amount: 30}, Busi+"/TccBTransOutTry", Busi+"/TccBTransOutConfirm", Busi+"/TccBTransOutCancel")
if dtmcli.IsFailure(resp, err) { if err != nil {
return resp, err return resp, err
} }
return tcc.CallBranch(&TransReq{Amount: 30}, Busi+"/TccBTransInTry", Busi+"/TccBTransInConfirm", Busi+"/TccBTransInCancel") return tcc.CallBranch(&TransReq{Amount: 30}, Busi+"/TccBTransInTry", Busi+"/TccBTransInConfirm", Busi+"/TccBTransInCancel")
}) })
dtmcli.PanicIfFailure(ret, err) e2p(err)
return gid return gid
} }

View File

@ -28,7 +28,7 @@ func XaSetup(app *gin.Engine) {
// XaFireRequest 注册全局XA事务调用XA的分支 // XaFireRequest 注册全局XA事务调用XA的分支
func XaFireRequest() string { func XaFireRequest() string {
gid := dtmcli.MustGenGid(DtmServer) gid := dtmcli.MustGenGid(DtmServer)
_, err := XaClient.XaGlobalTransaction(gid, func(xa *dtmcli.Xa) (*resty.Response, error) { err := XaClient.XaGlobalTransaction(gid, func(xa *dtmcli.Xa) (*resty.Response, error) {
resp, err := xa.CallBranch(&TransReq{Amount: 30}, Busi+"/TransOutXa") resp, err := xa.CallBranch(&TransReq{Amount: 30}, Busi+"/TransOutXa")
if err != nil { if err != nil {
return resp, err return resp, err