saga should refactor next
This commit is contained in:
parent
60c5c95972
commit
fa8abb239f
@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/yedf/dtm/common"
|
"github.com/yedf/dtm/common"
|
||||||
|
"gorm.io/gorm"
|
||||||
"gorm.io/gorm/clause"
|
"gorm.io/gorm/clause"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -47,9 +48,16 @@ func Branch(c *gin.Context) (interface{}, error) {
|
|||||||
branch := TransBranch{}
|
branch := TransBranch{}
|
||||||
err := c.BindJSON(&branch)
|
err := c.BindJSON(&branch)
|
||||||
e2p(err)
|
e2p(err)
|
||||||
db := dbGet()
|
branches := []TransBranch{branch, branch}
|
||||||
db.Must().Clauses(clause.OnConflict{
|
err = dbGet().Transaction(func(tx *gorm.DB) error {
|
||||||
DoNothing: true,
|
db := &common.MyDb{DB: tx}
|
||||||
}).Create(&branch)
|
branches[0].BranchType = "rollback"
|
||||||
|
branches[1].BranchType = "commit"
|
||||||
|
db.Must().Clauses(clause.OnConflict{
|
||||||
|
DoNothing: true,
|
||||||
|
}).Create(branches)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
e2p(err)
|
||||||
return M{"message": "SUCCESS"}, nil
|
return M{"message": "SUCCESS"}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,6 +29,7 @@ func TestDtmSvr(t *testing.T) {
|
|||||||
go StartSvr()
|
go StartSvr()
|
||||||
go examples.SagaStartSvr()
|
go examples.SagaStartSvr()
|
||||||
go examples.XaStartSvr()
|
go examples.XaStartSvr()
|
||||||
|
go examples.TccStartSvr()
|
||||||
time.Sleep(time.Duration(100 * 1000 * 1000))
|
time.Sleep(time.Duration(100 * 1000 * 1000))
|
||||||
|
|
||||||
// 清理数据
|
// 清理数据
|
||||||
@ -36,7 +37,8 @@ func TestDtmSvr(t *testing.T) {
|
|||||||
e2p(dbGet().Exec("truncate trans_branch").Error)
|
e2p(dbGet().Exec("truncate trans_branch").Error)
|
||||||
e2p(dbGet().Exec("truncate trans_log").Error)
|
e2p(dbGet().Exec("truncate trans_log").Error)
|
||||||
examples.ResetXaData()
|
examples.ResetXaData()
|
||||||
// tccNormal(t)
|
tccNormal(t)
|
||||||
|
tccRollback(t)
|
||||||
sagaCommittedPending(t)
|
sagaCommittedPending(t)
|
||||||
sagaPreparePending(t)
|
sagaPreparePending(t)
|
||||||
xaRollback(t)
|
xaRollback(t)
|
||||||
@ -58,7 +60,7 @@ func TestCover(t *testing.T) {
|
|||||||
// 测试使用的全局对象
|
// 测试使用的全局对象
|
||||||
var initdb = dbGet()
|
var initdb = dbGet()
|
||||||
|
|
||||||
func getSagaModel(gid string) *TransGlobal {
|
func getTransStatus(gid string) *TransGlobal {
|
||||||
sm := TransGlobal{}
|
sm := TransGlobal{}
|
||||||
dbr := dbGet().Model(&sm).Where("gid=?", gid).First(&sm)
|
dbr := dbGet().Model(&sm).Where("gid=?", gid).First(&sm)
|
||||||
e2p(dbr.Error)
|
e2p(dbr.Error)
|
||||||
@ -67,7 +69,7 @@ func getSagaModel(gid string) *TransGlobal {
|
|||||||
|
|
||||||
func getBranchesStatus(gid string) []string {
|
func getBranchesStatus(gid string) []string {
|
||||||
steps := []TransBranch{}
|
steps := []TransBranch{}
|
||||||
dbr := dbGet().Model(&TransBranch{}).Where("gid=?", gid).Find(&steps)
|
dbr := dbGet().Model(&TransBranch{}).Where("gid=?", gid).Order("id").Find(&steps)
|
||||||
e2p(dbr.Error)
|
e2p(dbr.Error)
|
||||||
status := []string{}
|
status := []string{}
|
||||||
for _, step := range steps {
|
for _, step := range steps {
|
||||||
@ -95,7 +97,7 @@ func xaNormal(t *testing.T) {
|
|||||||
})
|
})
|
||||||
e2p(err)
|
e2p(err)
|
||||||
WaitTransProcessed(gid)
|
WaitTransProcessed(gid)
|
||||||
assert.Equal(t, []string{"succeed", "succeed"}, getBranchesStatus(gid))
|
assert.Equal(t, []string{"prepared", "succeed", "prepared", "succeed"}, getBranchesStatus(gid))
|
||||||
}
|
}
|
||||||
|
|
||||||
func xaRollback(t *testing.T) {
|
func xaRollback(t *testing.T) {
|
||||||
@ -119,25 +121,31 @@ func xaRollback(t *testing.T) {
|
|||||||
logrus.Errorf("global transaction failed, so rollback")
|
logrus.Errorf("global transaction failed, so rollback")
|
||||||
}
|
}
|
||||||
WaitTransProcessed(gid)
|
WaitTransProcessed(gid)
|
||||||
assert.Equal(t, []string{"failed"}, getBranchesStatus(gid))
|
assert.Equal(t, []string{"succeed", "prepared"}, getBranchesStatus(gid))
|
||||||
|
assert.Equal(t, "failed", getTransStatus(gid).Status)
|
||||||
}
|
}
|
||||||
|
|
||||||
func tccNormal(t *testing.T) {
|
func tccNormal(t *testing.T) {
|
||||||
tcc := genTcc("gid-normal-tcc", false, false)
|
tcc := genTcc("gid-tcc-normal", false, false)
|
||||||
tcc.Prepare(tcc.QueryPrepared)
|
tcc.Prepare(tcc.QueryPrepared)
|
||||||
assert.Equal(t, "prepared", getSagaModel(tcc.Gid).Status)
|
assert.Equal(t, "prepared", getTransStatus(tcc.Gid).Status)
|
||||||
tcc.Commit()
|
tcc.Commit()
|
||||||
assert.Equal(t, "committed", getSagaModel(tcc.Gid).Status)
|
assert.Equal(t, "committed", getTransStatus(tcc.Gid).Status)
|
||||||
WaitTransProcessed(tcc.Gid)
|
WaitTransProcessed(tcc.Gid)
|
||||||
assert.Equal(t, []string{"prepared", "succeed", "succeed", "prepared", "succeed", "succeed"}, getBranchesStatus(tcc.Gid))
|
assert.Equal(t, []string{"prepared", "succeed", "succeed", "prepared", "succeed", "succeed"}, getBranchesStatus(tcc.Gid))
|
||||||
|
}
|
||||||
|
func tccRollback(t *testing.T) {
|
||||||
|
tcc := genTcc("gid-tcc-rollback", false, true)
|
||||||
|
tcc.Commit()
|
||||||
|
WaitTransProcessed(tcc.Gid)
|
||||||
|
assert.Equal(t, []string{"succeed", "prepared", "succeed", "succeed", "prepared", "failed"}, getBranchesStatus(tcc.Gid))
|
||||||
}
|
}
|
||||||
func sagaNormal(t *testing.T) {
|
func sagaNormal(t *testing.T) {
|
||||||
saga := genSaga("gid-noramlSaga", false, false)
|
saga := genSaga("gid-noramlSaga", false, false)
|
||||||
saga.Prepare(saga.QueryPrepared)
|
saga.Prepare(saga.QueryPrepared)
|
||||||
assert.Equal(t, "prepared", getSagaModel(saga.Gid).Status)
|
assert.Equal(t, "prepared", getTransStatus(saga.Gid).Status)
|
||||||
saga.Commit()
|
saga.Commit()
|
||||||
assert.Equal(t, "committed", getSagaModel(saga.Gid).Status)
|
assert.Equal(t, "committed", getTransStatus(saga.Gid).Status)
|
||||||
WaitTransProcessed(saga.Gid)
|
WaitTransProcessed(saga.Gid)
|
||||||
assert.Equal(t, []string{"prepared", "succeed", "prepared", "succeed"}, getBranchesStatus(saga.Gid))
|
assert.Equal(t, []string{"prepared", "succeed", "prepared", "succeed"}, getBranchesStatus(saga.Gid))
|
||||||
}
|
}
|
||||||
@ -147,7 +155,7 @@ func sagaRollback(t *testing.T) {
|
|||||||
saga.Commit()
|
saga.Commit()
|
||||||
WaitTransProcessed(saga.Gid)
|
WaitTransProcessed(saga.Gid)
|
||||||
saga.Prepare(saga.QueryPrepared)
|
saga.Prepare(saga.QueryPrepared)
|
||||||
assert.Equal(t, "failed", getSagaModel(saga.Gid).Status)
|
assert.Equal(t, "failed", getTransStatus(saga.Gid).Status)
|
||||||
assert.Equal(t, []string{"failed", "succeed", "failed", "failed"}, getBranchesStatus(saga.Gid))
|
assert.Equal(t, []string{"failed", "succeed", "failed", "failed"}, getBranchesStatus(saga.Gid))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +167,7 @@ func sagaPrepareCancel(t *testing.T) {
|
|||||||
CronTransOnce(-10*time.Second, "prepared")
|
CronTransOnce(-10*time.Second, "prepared")
|
||||||
examples.SagaTransQueryResult = ""
|
examples.SagaTransQueryResult = ""
|
||||||
config.PreparedExpire = 60
|
config.PreparedExpire = 60
|
||||||
assert.Equal(t, "canceled", getSagaModel(saga.Gid).Status)
|
assert.Equal(t, "canceled", getTransStatus(saga.Gid).Status)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sagaPreparePending(t *testing.T) {
|
func sagaPreparePending(t *testing.T) {
|
||||||
@ -168,9 +176,9 @@ func sagaPreparePending(t *testing.T) {
|
|||||||
examples.SagaTransQueryResult = "PENDING"
|
examples.SagaTransQueryResult = "PENDING"
|
||||||
CronTransOnce(-10*time.Second, "prepared")
|
CronTransOnce(-10*time.Second, "prepared")
|
||||||
examples.SagaTransQueryResult = ""
|
examples.SagaTransQueryResult = ""
|
||||||
assert.Equal(t, "prepared", getSagaModel(saga.Gid).Status)
|
assert.Equal(t, "prepared", getTransStatus(saga.Gid).Status)
|
||||||
CronTransOnce(-10*time.Second, "prepared")
|
CronTransOnce(-10*time.Second, "prepared")
|
||||||
assert.Equal(t, "succeed", getSagaModel(saga.Gid).Status)
|
assert.Equal(t, "succeed", getTransStatus(saga.Gid).Status)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sagaCommittedPending(t *testing.T) {
|
func sagaCommittedPending(t *testing.T) {
|
||||||
@ -183,7 +191,7 @@ func sagaCommittedPending(t *testing.T) {
|
|||||||
assert.Equal(t, []string{"prepared", "succeed", "prepared", "prepared"}, getBranchesStatus(saga.Gid))
|
assert.Equal(t, []string{"prepared", "succeed", "prepared", "prepared"}, getBranchesStatus(saga.Gid))
|
||||||
CronTransOnce(-10*time.Second, "committed")
|
CronTransOnce(-10*time.Second, "committed")
|
||||||
assert.Equal(t, []string{"prepared", "succeed", "prepared", "succeed"}, getBranchesStatus(saga.Gid))
|
assert.Equal(t, []string{"prepared", "succeed", "prepared", "succeed"}, getBranchesStatus(saga.Gid))
|
||||||
assert.Equal(t, "succeed", getSagaModel(saga.Gid).Status)
|
assert.Equal(t, "succeed", getTransStatus(saga.Gid).Status)
|
||||||
}
|
}
|
||||||
|
|
||||||
func genSaga(gid string, outFailed bool, inFailed bool) *dtm.Saga {
|
func genSaga(gid string, outFailed bool, inFailed bool) *dtm.Saga {
|
||||||
|
|||||||
@ -137,8 +137,7 @@ func (t *TransTccProcessor) ExecBranch(db *common.MyDb, branch *TransBranch) str
|
|||||||
body := resp.String()
|
body := resp.String()
|
||||||
t.touch(db)
|
t.touch(db)
|
||||||
if strings.Contains(body, "SUCCESS") {
|
if strings.Contains(body, "SUCCESS") {
|
||||||
status := common.If(branch.BranchType == "cancel", "failed", "succeed").(string)
|
branch.changeStatus(db, "succeed")
|
||||||
branch.changeStatus(db, status)
|
|
||||||
return "SUCCESS"
|
return "SUCCESS"
|
||||||
}
|
}
|
||||||
if branch.BranchType == "try" && strings.Contains(body, "FAIL") {
|
if branch.BranchType == "try" && strings.Contains(body, "FAIL") {
|
||||||
@ -193,7 +192,7 @@ func (t *TransXaProcessor) ExecBranch(db *common.MyDb, branch *TransBranch) stri
|
|||||||
if !strings.Contains(body, "SUCCESS") {
|
if !strings.Contains(body, "SUCCESS") {
|
||||||
panic(fmt.Errorf("bad response: %s", body))
|
panic(fmt.Errorf("bad response: %s", body))
|
||||||
}
|
}
|
||||||
branch.changeStatus(db, common.If(t.Status == "prepared", "failed", "succeed").(string))
|
branch.changeStatus(db, "succeed")
|
||||||
return "SUCCESS"
|
return "SUCCESS"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,25 +200,12 @@ func (t *TransXaProcessor) ProcessOnce(db *common.MyDb, branches []TransBranch)
|
|||||||
if t.Status == "succeed" {
|
if t.Status == "succeed" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if t.Status == "committed" {
|
currentType := common.If(t.Status == "committed", "commit", "rollback").(string)
|
||||||
for _, branch := range branches {
|
for _, branch := range branches {
|
||||||
if branch.Status == "succeed" {
|
if branch.BranchType == currentType && branch.Status != "succeed" {
|
||||||
continue
|
|
||||||
}
|
|
||||||
_ = t.ExecBranch(db, &branch)
|
|
||||||
t.touch(db) // 更新update_time,避免被定时任务再次
|
|
||||||
}
|
|
||||||
t.changeStatus(db, "succeed")
|
|
||||||
} else if t.Status == "prepared" { // 未commit直接处理的情况为回滚场景
|
|
||||||
for _, branch := range branches {
|
|
||||||
if branch.Status == "failed" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
_ = t.ExecBranch(db, &branch)
|
_ = t.ExecBranch(db, &branch)
|
||||||
t.touch(db)
|
t.touch(db)
|
||||||
}
|
}
|
||||||
t.changeStatus(db, "failed")
|
|
||||||
} else {
|
|
||||||
e2p(fmt.Errorf("bad trans status: %s", t.Status))
|
|
||||||
}
|
}
|
||||||
|
t.changeStatus(db, common.If(t.Status == "committed", "succeed", "failed").(string))
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user