update status

This commit is contained in:
yedf2 2021-07-23 14:58:28 +08:00
parent 6a1048e981
commit 3a71edea40
10 changed files with 60 additions and 45 deletions

View File

@ -9,7 +9,7 @@ import (
"testing" "testing"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-playground/assert/v2" "github.com/stretchr/testify/assert"
) )
func TestEP(t *testing.T) { func TestEP(t *testing.T) {
@ -83,6 +83,10 @@ func TestSome(t *testing.T) {
n := MustAtoi("123") n := MustAtoi("123")
assert.Equal(t, 123, n) assert.Equal(t, 123, n)
err := CatchP(func() {
MustAtoi("abc")
})
assert.Error(t, err)
wd := MustGetwd() wd := MustGetwd()
assert.NotEqual(t, "", wd) assert.NotEqual(t, "", wd)

View File

@ -5,6 +5,7 @@ import (
"database/sql" "database/sql"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/url"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@ -26,18 +27,25 @@ func (t *TransInfo) String() string {
return fmt.Sprintf("transInfo: %s %s %s %s", t.TransType, t.Gid, t.BranchID, t.BranchType) return fmt.Sprintf("transInfo: %s %s %s %s", t.TransType, t.Gid, t.BranchID, t.BranchType)
} }
// TransInfoFromReq construct transaction info from request // MustGetTrans construct transaction info from request
func TransInfoFromReq(c *gin.Context) *TransInfo { func MustGetTrans(c *gin.Context) *TransInfo {
ti, err := TransInfoFromQuery(c.Request.URL.Query())
e2p(err)
return ti
}
// TransInfoFromQuery construct transaction info from request
func TransInfoFromQuery(qs url.Values) (*TransInfo, error) {
ti := &TransInfo{ ti := &TransInfo{
TransType: c.Query("trans_type"), TransType: qs.Get("trans_type"),
Gid: c.Query("gid"), Gid: qs.Get("gid"),
BranchID: c.Query("branch_id"), BranchID: qs.Get("branch_id"),
BranchType: c.Query("branch_type"), BranchType: qs.Get("branch_type"),
} }
if ti.TransType == "" || ti.Gid == "" || ti.BranchID == "" || ti.BranchType == "" { if ti.TransType == "" || ti.Gid == "" || ti.BranchID == "" || ti.BranchType == "" {
panic(fmt.Errorf("invlid trans info: %v", ti)) return nil, fmt.Errorf("invlid trans info: %v", ti)
} }
return ti return ti, nil
} }
// BarrierModel barrier model for gorm // BarrierModel barrier model for gorm
@ -119,7 +127,7 @@ func ThroughBarrierCall(db *sql.DB, transInfo *TransInfo, busiCall BusiFunc) (re
return return
} }
if result.Valid { // 数据库里有上一次结果,返回上一次的结果 if result.Valid { // 数据库里有上一次结果,返回上一次的结果
res = json.Unmarshal([]byte(result.String), &res) rerr = json.Unmarshal([]byte(result.String), &res)
return return
} }
// 数据库里没有上次的结果,属于重复空补偿,直接返回成功 // 数据库里没有上次的结果,属于重复空补偿,直接返回成功

View File

@ -3,7 +3,6 @@ package dtmcli
import ( import (
"fmt" "fmt"
jsonitor "github.com/json-iterator/go"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/yedf/dtm/common" "github.com/yedf/dtm/common"
) )
@ -54,12 +53,7 @@ func (s *Msg) Add(action string, postData interface{}) *Msg {
func (s *Msg) Submit() error { func (s *Msg) Submit() error {
logrus.Printf("committing %s body: %v", s.Gid, &s.MsgData) logrus.Printf("committing %s body: %v", s.Gid, &s.MsgData)
resp, err := common.RestyClient.R().SetBody(&s.MsgData).Post(fmt.Sprintf("%s/submit", s.Server)) resp, err := common.RestyClient.R().SetBody(&s.MsgData).Post(fmt.Sprintf("%s/submit", s.Server))
rerr := CheckDtmResponse(resp, err) return CheckDtmResponse(resp, err)
if rerr != nil {
return rerr
}
s.Gid = jsonitor.Get(resp.Body(), "gid").ToString()
return nil
} }
// Prepare prepare the msg // Prepare prepare the msg

View File

@ -3,7 +3,6 @@ package dtmcli
import ( import (
"fmt" "fmt"
jsonitor "github.com/json-iterator/go"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/yedf/dtm/common" "github.com/yedf/dtm/common"
) )
@ -55,10 +54,5 @@ func (s *Saga) Add(action string, compensate string, postData interface{}) *Saga
func (s *Saga) Submit() error { func (s *Saga) Submit() error {
logrus.Printf("committing %s body: %v", s.Gid, &s.SagaData) logrus.Printf("committing %s body: %v", s.Gid, &s.SagaData)
resp, err := common.RestyClient.R().SetBody(&s.SagaData).Post(fmt.Sprintf("%s/submit", s.Server)) resp, err := common.RestyClient.R().SetBody(&s.SagaData).Post(fmt.Sprintf("%s/submit", s.Server))
rerr := CheckDtmResponse(resp, err) return CheckDtmResponse(resp, err)
if rerr != nil {
return rerr
}
s.Gid = jsonitor.Get(resp.Body(), "gid").ToString()
return nil
} }

View File

@ -81,13 +81,11 @@ func (t *Tcc) CallBranch(body interface{}, tryURL string, confirmURL string, can
"cancel": cancelURL, "cancel": cancelURL,
}). }).
Post(t.Dtm + "/registerTccBranch") Post(t.Dtm + "/registerTccBranch")
err = CheckDtmResponse(resp, err)
if err != nil { if err != nil {
return resp, err return resp, err
} }
if !strings.Contains(resp.String(), "SUCCESS") { resp, err = common.RestyClient.R().
return nil, fmt.Errorf("registerTccBranch failed: %s", resp.String())
}
r, err := common.RestyClient.R().
SetBody(body). SetBody(body).
SetQueryParams(common.MS{ SetQueryParams(common.MS{
"dtm": t.Dtm, "dtm": t.Dtm,
@ -97,8 +95,8 @@ func (t *Tcc) CallBranch(body interface{}, tryURL string, confirmURL string, can
"branch_type": "try", "branch_type": "try",
}). }).
Post(tryURL) Post(tryURL)
if err == nil && strings.Contains(r.String(), "FAILURE") { if err == nil && strings.Contains(resp.String(), "FAILURE") {
return r, fmt.Errorf("branch return failure: %s", r.String()) err = fmt.Errorf("branch return failure: %s", resp.String())
} }
return r, err return resp, err
} }

View File

@ -1,6 +1,7 @@
package dtmcli package dtmcli
import ( import (
"net/url"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -18,4 +19,6 @@ func TestTypes(t *testing.T) {
idGen.NewBranchID() idGen.NewBranchID()
}) })
assert.Error(t, err) assert.Error(t, err)
_, err = TransInfoFromQuery(url.Values{})
assert.Error(t, err)
} }

View File

@ -21,14 +21,14 @@ func addRoute(engine *gin.Engine) {
} }
func newGid(c *gin.Context) (interface{}, error) { func newGid(c *gin.Context) (interface{}, error) {
return M{"gid": GenGid()}, nil return M{"gid": GenGid(), "dtm_result": "SUCCESS"}, nil
} }
func prepare(c *gin.Context) (interface{}, error) { func prepare(c *gin.Context) (interface{}, error) {
t := TransFromContext(c) t := TransFromContext(c)
t.Status = "prepared" t.Status = "prepared"
t.saveNew(dbGet()) t.saveNew(dbGet())
return M{"dtm_result": "SUCCESS", "gid": t.Gid}, nil return M{"dtm_result": "SUCCESS"}, nil
} }
func submit(c *gin.Context) (interface{}, error) { func submit(c *gin.Context) (interface{}, error) {
@ -41,7 +41,7 @@ func submit(c *gin.Context) (interface{}, error) {
t.Status = "submitted" t.Status = "submitted"
t.saveNew(db) t.saveNew(db)
go t.Process(db) go t.Process(db)
return M{"dtm_result": "SUCCESS", "gid": t.Gid}, nil return M{"dtm_result": "SUCCESS"}, nil
} }
func abort(c *gin.Context) (interface{}, error) { func abort(c *gin.Context) (interface{}, error) {

View File

@ -56,6 +56,14 @@ func TestType(t *testing.T) {
dtmcli.MustGenGid("http://localhost:8080/api/no") dtmcli.MustGenGid("http://localhost:8080/api/no")
}) })
assert.Error(t, err) assert.Error(t, err)
err = common.CatchP(func() {
resp, err := common.RestyClient.R().SetBody(common.M{
"gid": "1",
"trans_type": "msg",
}).Get("http://localhost:8080/api/dtmsvr/abort")
common.CheckRestySuccess(resp, err)
})
assert.Error(t, err)
} }
func getTransStatus(gid string) string { func getTransStatus(gid string) string {
@ -140,11 +148,17 @@ func TestSqlDB(t *testing.T) {
asserts.Equal(dbr.RowsAffected, int64(1)) asserts.Equal(dbr.RowsAffected, int64(1))
dbr = db.Model(&dtmcli.BarrierModel{}).Where("gid=?", "gid2").Find(&[]dtmcli.BarrierModel{}) dbr = db.Model(&dtmcli.BarrierModel{}).Where("gid=?", "gid2").Find(&[]dtmcli.BarrierModel{})
asserts.Equal(dbr.RowsAffected, int64(0)) asserts.Equal(dbr.RowsAffected, int64(0))
gid2Res := common.M{"result": "first"}
_, err = dtmcli.ThroughBarrierCall(db.ToSQLDB(), transInfo, func(db *sql.DB) (interface{}, error) { _, err = dtmcli.ThroughBarrierCall(db.ToSQLDB(), transInfo, func(db *sql.DB) (interface{}, error) {
logrus.Printf("submit gid2") logrus.Printf("submit gid2")
return nil, nil return gid2Res, nil
}) })
asserts.Nil(err) asserts.Nil(err)
dbr = db.Model(&dtmcli.BarrierModel{}).Where("gid=?", "gid2").Find(&[]dtmcli.BarrierModel{}) dbr = db.Model(&dtmcli.BarrierModel{}).Where("gid=?", "gid2").Find(&[]dtmcli.BarrierModel{})
asserts.Equal(dbr.RowsAffected, int64(1)) asserts.Equal(dbr.RowsAffected, int64(1))
newResult, err := dtmcli.ThroughBarrierCall(db.ToSQLDB(), transInfo, func(db *sql.DB) (interface{}, error) {
logrus.Printf("submit gid2")
return common.MS{"result": "ignored"}, nil
})
asserts.Equal(newResult, gid2Res)
} }

View File

@ -44,13 +44,13 @@ func sagaBarrierTransIn(c *gin.Context) (interface{}, error) {
if req.TransInResult != "" { if req.TransInResult != "" {
return req.TransInResult, nil return req.TransInResult, nil
} }
return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.TransInfoFromReq(c), func(sdb *sql.DB) (interface{}, error) { return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.MustGetTrans(c), func(sdb *sql.DB) (interface{}, error) {
return sagaBarrierAdjustBalance(sdb, 1, req.Amount) return sagaBarrierAdjustBalance(sdb, 1, req.Amount)
}) })
} }
func sagaBarrierTransInCompensate(c *gin.Context) (interface{}, error) { func sagaBarrierTransInCompensate(c *gin.Context) (interface{}, error) {
return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.TransInfoFromReq(c), func(sdb *sql.DB) (interface{}, error) { return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.MustGetTrans(c), func(sdb *sql.DB) (interface{}, error) {
return sagaBarrierAdjustBalance(sdb, 1, -reqFrom(c).Amount) return sagaBarrierAdjustBalance(sdb, 1, -reqFrom(c).Amount)
}) })
} }
@ -60,13 +60,13 @@ func sagaBarrierTransOut(c *gin.Context) (interface{}, error) {
if req.TransInResult != "" { if req.TransInResult != "" {
return req.TransInResult, nil return req.TransInResult, nil
} }
return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.TransInfoFromReq(c), func(sdb *sql.DB) (interface{}, error) { return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.MustGetTrans(c), func(sdb *sql.DB) (interface{}, error) {
return sagaBarrierAdjustBalance(sdb, 2, -req.Amount) return sagaBarrierAdjustBalance(sdb, 2, -req.Amount)
}) })
} }
func sagaBarrierTransOutCompensate(c *gin.Context) (interface{}, error) { func sagaBarrierTransOutCompensate(c *gin.Context) (interface{}, error) {
return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.TransInfoFromReq(c), func(sdb *sql.DB) (interface{}, error) { return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.MustGetTrans(c), func(sdb *sql.DB) (interface{}, error) {
return sagaBarrierAdjustBalance(sdb, 2, reqFrom(c).Amount) return sagaBarrierAdjustBalance(sdb, 2, reqFrom(c).Amount)
}) })
} }

View File

@ -70,19 +70,19 @@ func tccBarrierTransInTry(c *gin.Context) (interface{}, error) {
if req.TransInResult != "" { if req.TransInResult != "" {
return req.TransInResult, nil return req.TransInResult, nil
} }
return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.TransInfoFromReq(c), func(sdb *sql.DB) (interface{}, error) { return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.MustGetTrans(c), func(sdb *sql.DB) (interface{}, error) {
return adjustTrading(sdb, transInUID, req.Amount) return adjustTrading(sdb, transInUID, req.Amount)
}) })
} }
func tccBarrierTransInConfirm(c *gin.Context) (interface{}, error) { func tccBarrierTransInConfirm(c *gin.Context) (interface{}, error) {
return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.TransInfoFromReq(c), func(sdb *sql.DB) (interface{}, error) { return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.MustGetTrans(c), func(sdb *sql.DB) (interface{}, error) {
return adjustBalance(sdb, transInUID, reqFrom(c).Amount) return adjustBalance(sdb, transInUID, reqFrom(c).Amount)
}) })
} }
func tccBarrierTransInCancel(c *gin.Context) (interface{}, error) { func tccBarrierTransInCancel(c *gin.Context) (interface{}, error) {
return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.TransInfoFromReq(c), func(sdb *sql.DB) (interface{}, error) { return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.MustGetTrans(c), func(sdb *sql.DB) (interface{}, error) {
return adjustTrading(sdb, transInUID, -reqFrom(c).Amount) return adjustTrading(sdb, transInUID, -reqFrom(c).Amount)
}) })
} }
@ -92,20 +92,20 @@ func tccBarrierTransOutTry(c *gin.Context) (interface{}, error) {
if req.TransInResult != "" { if req.TransInResult != "" {
return req.TransInResult, nil return req.TransInResult, nil
} }
return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.TransInfoFromReq(c), func(sdb *sql.DB) (interface{}, error) { return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.MustGetTrans(c), func(sdb *sql.DB) (interface{}, error) {
return adjustTrading(sdb, transOutUID, -req.Amount) return adjustTrading(sdb, transOutUID, -req.Amount)
}) })
} }
func tccBarrierTransOutConfirm(c *gin.Context) (interface{}, error) { func tccBarrierTransOutConfirm(c *gin.Context) (interface{}, error) {
return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.TransInfoFromReq(c), func(sdb *sql.DB) (interface{}, error) { return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.MustGetTrans(c), func(sdb *sql.DB) (interface{}, error) {
return adjustBalance(sdb, transOutUID, -reqFrom(c).Amount) return adjustBalance(sdb, transOutUID, -reqFrom(c).Amount)
}) })
} }
// TccBarrierTransOutCancel will be use in test // TccBarrierTransOutCancel will be use in test
func TccBarrierTransOutCancel(c *gin.Context) (interface{}, error) { func TccBarrierTransOutCancel(c *gin.Context) (interface{}, error) {
return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.TransInfoFromReq(c), func(sdb *sql.DB) (interface{}, error) { return dtmcli.ThroughBarrierCall(dbGet().ToSQLDB(), dtmcli.MustGetTrans(c), func(sdb *sql.DB) (interface{}, error) {
return adjustTrading(sdb, transOutUID, reqFrom(c).Amount) return adjustTrading(sdb, transOutUID, reqFrom(c).Amount)
}) })
} }