golang dtm server

go
git clone https://github.com/dtm-labs/dtm && cd dtm
go run main.go

git clone https://github.com/dtm-labs/dtmcli-go-sample && cd dtmcli-go-sample
go run main.go
go
// QsFireRequest quick start: fire request
func QsFireRequest() string {
    fmt.Println(mount)
    req := &gin.H{"amount": 30} // 微服務的載荷
    // DtmServer為DTM服務的地址
    saga := dtmcli.NewSaga(dtmServer, dtmcli.MustGenGid(dtmServer)).
        // 添加一個TransOut的子事務,正向操作為url: qsBusi+"/TransOut", 逆向操作為url: qsBusi+"/TransOutCompensate"
        Add(qsBusi+"/TransOut", qsBusi+"/TransOutCompensate", req).
        // 添加一個TransIn的子事務,正向操作為url: qsBusi+"/TransOut", 逆向操作為url: qsBusi+"/TransInCompensate"
        Add(qsBusi+"/TransIn", qsBusi+"/TransInCompensate", req)
    // 提交saga事務,dtm會完成所有的子事務/回滾所有的子事務
    err := saga.Submit()
    logger.FatalIfError(err)
    return saga.Gid
} 
go
var mount = 30
func qsAddRoute(app *gin.Engine) {

    app.POST(qsBusiAPI+"/TransIn", func(c *gin.Context) {
        logger.Infof("TransIn")
        // c.JSON(200, "")
        mount += 60
        fmt.Println(mount)
        c.JSON(409, "") // Status 409 for Failure. Won't be retried
    })
    app.POST(qsBusiAPI+"/TransInCompensate", func(c *gin.Context) {
        logger.Infof("TransInCompensate")
        mount -= 60
        fmt.Println(mount)
        c.JSON(200, "")
    })
    app.POST(qsBusiAPI+"/TransOut", func(c *gin.Context) {
        logger.Infof("TransOut")
        mount -= 20
        fmt.Println(mount)
        c.JSON(200, "")
    })
    app.POST(qsBusiAPI+"/TransOutCompensate", func(c *gin.Context) {
        logger.Infof("TransOutCompensate")
        mount += 20
        fmt.Println(mount)
        c.JSON(200, "")
    })
}

當你的微服務都是http request 則在

go
        Add(qsBusi+"/TransOut", qsBusi+"/TransOutCompensate", req).
        // 添加一個TransIn的子事務,正向操作為url: qsBusi+"/TransOut", 逆向操作為url: qsBusi+"/TransInCompensate"
        Add(qsBusi+"/TransIn", qsBusi+"/TransInCompensate", req)

要確保這部分的業務邏輯一定要對否則rollback

go
    app.POST(qsBusiAPI+"/TransIn", func(c *gin.Context) {
        logger.Infof("TransIn")
        // c.JSON(200, "")
        mount += 60
        fmt.Println(mount)
        c.JSON(409, "") // Status 409 for Failure. Won't be retried
    })

可以看到最終值可以維持不變