update status
This commit is contained in:
parent
6a1048e981
commit
3a71edea40
@ -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)
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
// 数据库里没有上次的结果,属于重复空补偿,直接返回成功
|
// 数据库里没有上次的结果,属于重复空补偿,直接返回成功
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user