dtm/dtmcli/tcc.go
2021-08-11 15:46:25 +08:00

82 lines
2.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package dtmcli
import (
"fmt"
"net/url"
"github.com/go-resty/resty/v2"
)
// Tcc struct of tcc
type Tcc struct {
TransBase
}
// TccGlobalFunc type of global tcc call
type TccGlobalFunc func(tcc *Tcc) (*resty.Response, error)
// TccGlobalTransaction begin a tcc global transaction
// dtm dtm服务器地址
// gid 全局事务id
// tccFunc tcc事务函数里面会定义全局事务的分支
func TccGlobalTransaction(dtm string, gid string, tccFunc TccGlobalFunc) (rerr error) {
tcc := &Tcc{TransBase: *NewTransBase(gid, "tcc", dtm, "")}
rerr = tcc.callDtm(tcc, "prepare")
if rerr != nil {
return rerr
}
// 小概率情况下prepare成功了但是由于网络状况导致上面Failure那么不执行下面defer的内容等待超时后再回滚标记事务失败也没有问题
defer func() {
x := recover()
operation := If(x == nil && rerr == nil, "submit", "abort").(string)
err := tcc.callDtm(tcc, operation)
if rerr == nil {
rerr = err
}
if x != nil {
panic(x)
}
}()
resp, rerr := tccFunc(tcc)
rerr = CheckResponse(resp, rerr)
return
}
// TccFromQuery tcc from request info
func TccFromQuery(qs url.Values) (*Tcc, error) {
tcc := &Tcc{TransBase: *TransBaseFromQuery(qs)}
if tcc.Dtm == "" || tcc.Gid == "" {
return nil, fmt.Errorf("bad tcc info. dtm: %s, gid: %s parentID: %s", tcc.Dtm, tcc.Gid, tcc.parentID)
}
return tcc, nil
}
// CallBranch call a tcc branch
// 函数首先注册子事务的所有分支成功后调用try分支返回try分支的调用结果
func (t *Tcc) CallBranch(body interface{}, tryURL string, confirmURL string, cancelURL string) (*resty.Response, error) {
branchID := t.NewBranchID()
err := t.callDtm(&M{
"gid": t.Gid,
"branch_id": branchID,
"trans_type": "tcc",
"data": string(MustMarshal(body)),
"try": tryURL,
"confirm": confirmURL,
"cancel": cancelURL,
}, "registerTccBranch")
if err != nil {
return nil, err
}
resp, err := RestyClient.R().
SetBody(body).
SetQueryParams(MS{
"dtm": t.Dtm,
"gid": t.Gid,
"branch_id": branchID,
"trans_type": "tcc",
"branch_type": "try",
}).
Post(tryURL)
return resp, CheckResponse(resp, err)
}