dtm/dtmsvr/api.go
2021-07-04 09:36:16 +08:00

107 lines
2.9 KiB
Go

package dtmsvr
import (
"errors"
"fmt"
"github.com/gin-gonic/gin"
"github.com/yedf/dtm/common"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
func AddRoute(engine *gin.Engine) {
engine.POST("/api/dtmsvr/prepare", common.WrapHandler(Prepare))
engine.POST("/api/dtmsvr/submit", common.WrapHandler(Submit))
engine.POST("/api/dtmsvr/registerXaBranch", common.WrapHandler(RegisterXaBranch))
engine.POST("/api/dtmsvr/registerTccBranch", common.WrapHandler(RegisterTccBranch))
engine.POST("/api/dtmsvr/abort", common.WrapHandler(Abort))
engine.GET("/api/dtmsvr/query", common.WrapHandler(Query))
}
func Prepare(c *gin.Context) (interface{}, error) {
m := TransFromContext(c)
m.Status = "prepared"
m.SaveNew(dbGet())
return M{"message": "SUCCESS", "gid": m.Gid}, nil
}
func Submit(c *gin.Context) (interface{}, error) {
db := dbGet()
m := TransFromContext(c)
m.Status = "submitted"
m.SaveNew(db)
go m.Process(db)
return M{"message": "SUCCESS", "gid": m.Gid}, nil
}
func Abort(c *gin.Context) (interface{}, error) {
db := dbGet()
m := TransFromContext(c)
m = TransFromDb(db, m.Gid)
if m.TransType != "xa" && m.TransType != "tcc" || m.Status != "prepared" {
return nil, fmt.Errorf("unexpected trans data. type: %s status: %s for gid: %s", m.TransType, m.Status, m.Gid)
}
go m.Process(db)
return M{"message": "SUCCESS"}, nil
}
func RegisterXaBranch(c *gin.Context) (interface{}, error) {
branch := TransBranch{}
err := c.BindJSON(&branch)
e2p(err)
branches := []TransBranch{branch, branch}
db := dbGet()
branches[0].BranchType = "rollback"
branches[1].BranchType = "commit"
db.Must().Clauses(clause.OnConflict{
DoNothing: true,
}).Create(branches)
e2p(err)
global := TransGlobal{Gid: branch.Gid}
global.touch(db, config.TransCronInterval)
return M{"message": "SUCCESS"}, nil
}
func RegisterTccBranch(c *gin.Context) (interface{}, error) {
data := common.MS{}
err := c.BindJSON(&data)
e2p(err)
branch := TransBranch{
Gid: data["gid"],
BranchID: data["branch_id"],
Status: data["status"],
Data: data["data"],
}
branches := []TransBranch{branch, branch, branch}
for i, b := range []string{"cancel", "confirm", "try"} {
branches[i].BranchType = b
branches[i].Url = data[b]
}
dbGet().Must().Clauses(clause.OnConflict{
DoNothing: true,
}).Create(branches)
e2p(err)
global := TransGlobal{Gid: branch.Gid}
global.touch(dbGet(), config.TransCronInterval)
return M{"message": "SUCCESS"}, nil
}
func Query(c *gin.Context) (interface{}, error) {
gid := c.Query("gid")
if gid == "" {
return nil, errors.New("no gid specified")
}
trans := TransGlobal{}
db := dbGet()
dbr := db.Must().Where("gid", gid).First(&trans)
if dbr.Error == gorm.ErrRecordNotFound {
return M{"transaction": nil, "branches": [0]int{}}, nil
}
branches := []TransBranch{}
db.Must().Where("gid", gid).Find(&branches)
return M{"transaction": trans, "branches": branches}, nil
}