From 451b43511f5cfa3fd37c6c0f21cb05a4adf09cce Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Mon, 6 Jun 2022 20:18:12 +0800 Subject: [PATCH 01/32] add table kv --- sqls/dtmsvr.storage.mysql.sql | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sqls/dtmsvr.storage.mysql.sql b/sqls/dtmsvr.storage.mysql.sql index 283bb75..019f877 100644 --- a/sqls/dtmsvr.storage.mysql.sql +++ b/sqls/dtmsvr.storage.mysql.sql @@ -41,3 +41,15 @@ CREATE TABLE IF NOT EXISTS dtm.trans_branch_op ( PRIMARY KEY (`id`), UNIQUE KEY `gid_uniq` (`gid`, `branch_id`, `op`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; +drop table IF EXISTS dtm.kv; +CREATE TABLE IF NOT EXISTS dtm.kv ( + `id` bigint(22) NOT NULL AUTO_INCREMENT, + `cat` varchar(45) NOT NULL COMMENT 'the category of this data', + `k` varchar(128) NOT NULL, + `v` TEXT, + `version` bigint(22) default 1 COMMENT 'version of the value', + create_time datetime default NULL, + update_time datetime DEFAULT NULL, + PRIMARY KEY (`id`) + UNIQUE key `uniq_k`(`cat`, `k`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; From a18972e0b3289307c32218d7a61794c639d1d944 Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Mon, 6 Jun 2022 20:43:15 +0800 Subject: [PATCH 02/32] fix sql syntax --- sqls/dtmsvr.storage.mysql.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqls/dtmsvr.storage.mysql.sql b/sqls/dtmsvr.storage.mysql.sql index 019f877..dd2a097 100644 --- a/sqls/dtmsvr.storage.mysql.sql +++ b/sqls/dtmsvr.storage.mysql.sql @@ -50,6 +50,6 @@ CREATE TABLE IF NOT EXISTS dtm.kv ( `version` bigint(22) default 1 COMMENT 'version of the value', create_time datetime default NULL, update_time datetime DEFAULT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), UNIQUE key `uniq_k`(`cat`, `k`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; From 779e17fab9b893ecd3a7a999565f91e4157f9c39 Mon Sep 17 00:00:00 2001 From: phprao Date: Mon, 13 Jun 2022 10:57:10 +0800 Subject: [PATCH 03/32] fix api logic of '/TransOutXa' --- test/busi/base_http.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/busi/base_http.go b/test/busi/base_http.go index 11bc525..c2bf076 100644 --- a/test/busi/base_http.go +++ b/test/busi/base_http.go @@ -141,7 +141,7 @@ func BaseAddRoute(app *gin.Engine) { })) app.POST(BusiAPI+"/TransOutXa", dtmutil.WrapHandler(func(c *gin.Context) interface{} { return dtmcli.XaLocalTransaction(c.Request.URL.Query(), BusiConf, func(db *sql.DB, xa *dtmcli.Xa) error { - return SagaAdjustBalance(db, TransOutUID, reqFrom(c).Amount, reqFrom(c).TransOutResult) + return SagaAdjustBalance(db, TransOutUID, -reqFrom(c).Amount, reqFrom(c).TransOutResult) }) })) app.POST(BusiAPI+"/TransOutTimeout", dtmutil.WrapHandler(func(c *gin.Context) interface{} { From 84ee15d11bd04e1f8c48018cacb11a9ec965c812 Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Thu, 16 Jun 2022 15:06:22 +0800 Subject: [PATCH 04/32] personal wechat back --- helper/README-cn.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/helper/README-cn.md b/helper/README-cn.md index f07f387..2153ae3 100644 --- a/helper/README-cn.md +++ b/helper/README-cn.md @@ -115,7 +115,9 @@ go run main.go 如果您希望更快的获得反馈,或者更多的了解其他用户在使用过程中的各种反馈,欢迎加入我们的微信交流群 -wechat +请加作者的微信 yedf2008 好友或者扫码加好友,备注 `dtm` 按照指引进群 + +![yedf2008](http://service.ivydad.com/cover/dubbingb6b5e2c0-2d2a-cd59-f7c5-c6b90aceb6f1.jpeg) 欢迎使用[dtm](https://github.com/dtm-labs/dtm),或者通过dtm学习实践分布式事务相关知识,欢迎star支持我们 From 4362724c6159d37b3a1423f46125d7e91e8354bf Mon Sep 17 00:00:00 2001 From: xyctruth <398041993@qq.com> Date: Mon, 20 Jun 2022 16:53:38 +0800 Subject: [PATCH 05/32] add rollback reason --- dtmsvr/storage/trans.go | 1 + dtmsvr/trans_status.go | 23 +++++++++++++++++++++-- dtmsvr/trans_type_tcc.go | 3 ++- go.sum | 28 +--------------------------- sqls/dtmsvr.storage.mysql.sql | 1 + sqls/dtmsvr.storage.postgres.sql | 3 ++- sqls/dtmsvr.storage.tdsql.sql | 1 + test/dtmsvr_test.go | 4 ++++ test/tcc_test.go | 3 +++ 9 files changed, 36 insertions(+), 31 deletions(-) diff --git a/dtmsvr/storage/trans.go b/dtmsvr/storage/trans.go index 04b13c4..749eb1a 100644 --- a/dtmsvr/storage/trans.go +++ b/dtmsvr/storage/trans.go @@ -32,6 +32,7 @@ type TransGlobalStore struct { Protocol string `json:"protocol,omitempty"` FinishTime *time.Time `json:"finish_time,omitempty"` RollbackTime *time.Time `json:"rollback_time,omitempty"` + RollbackReason string `json:"rollback_reason,omitempty"` Options string `json:"options,omitempty"` CustomData string `json:"custom_data,omitempty"` NextCronInterval int64 `json:"next_cron_interval,omitempty"` diff --git a/dtmsvr/trans_status.go b/dtmsvr/trans_status.go index 6f6a344..9cef0ae 100644 --- a/dtmsvr/trans_status.go +++ b/dtmsvr/trans_status.go @@ -36,7 +36,22 @@ func (t *TransGlobal) touchCronTime(ctype cronType, delay uint64) { logger.Infof("TouchCronTime for: %s", t.TransGlobalStore.String()) } -func (t *TransGlobal) changeStatus(status string) { +type changeStatusParams struct { + rollbackReason string +} +type changeStatusOption func(c *changeStatusParams) + +func withRollbackReason(rollbackReason string) changeStatusOption { + return func(c *changeStatusParams) { + c.rollbackReason = rollbackReason + } +} + +func (t *TransGlobal) changeStatus(status string, opts ...changeStatusOption) { + statusParams := &changeStatusParams{} + for _, opt := range opts { + opt(statusParams) + } updates := []string{"status", "update_time"} now := time.Now() if status == dtmcli.StatusSucceed { @@ -46,9 +61,13 @@ func (t *TransGlobal) changeStatus(status string) { t.RollbackTime = &now updates = append(updates, "rollback_time") } + if statusParams.rollbackReason != "" { + t.RollbackReason = statusParams.rollbackReason + updates = append(updates, "rollback_reason") + } t.UpdateTime = &now GetStore().ChangeGlobalStatus(&t.TransGlobalStore, status, updates, status == dtmcli.StatusSucceed || status == dtmcli.StatusFailed) - logger.Infof("ChangeGlobalStatus to %s ok for %s", status, t.TransGlobalStore.String()) + logger.Infof("ChangeGlobalStatus to %statusParams ok for %statusParams", status, t.TransGlobalStore.String()) t.Status = status } diff --git a/dtmsvr/trans_type_tcc.go b/dtmsvr/trans_type_tcc.go index 5146226..1f5ef2b 100644 --- a/dtmsvr/trans_type_tcc.go +++ b/dtmsvr/trans_type_tcc.go @@ -1,6 +1,7 @@ package dtmsvr import ( + "fmt" "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" "github.com/dtm-labs/dtm/dtmcli/logger" @@ -23,7 +24,7 @@ func (t *transTccProcessor) ProcessOnce(branches []TransBranch) error { return nil } if t.Status == dtmcli.StatusPrepared && t.isTimeout() { - t.changeStatus(dtmcli.StatusAborting) + t.changeStatus(dtmcli.StatusAborting, withRollbackReason(fmt.Sprintf("Timeout after %d seconds", t.TimeoutToFail))) } op := dtmimp.If(t.Status == dtmcli.StatusSubmitted, dtmimp.OpConfirm, dtmimp.OpCancel).(string) for current := len(branches) - 1; current >= 0; current-- { diff --git a/go.sum b/go.sum index bfee152..98d85de 100644 --- a/go.sum +++ b/go.sum @@ -67,7 +67,6 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= github.com/alicebob/miniredis/v2 v2.17.0/go.mod h1:gquAfGbzn92jvtrSC69+6zZnwSODVXVpYDRaGhWaL6I= -github.com/aliyun/alibaba-cloud-sdk-go v1.61.18 h1:zOVTBdCKFd9JbCKz9/nt+FovbjPFmb7mUnp8nH9fQBA= github.com/aliyun/alibaba-cloud-sdk-go v1.61.18/go.mod h1:v8ESoHo4SyHmuB4b1tJqDHxfTGEciD+yhvOU/5s1Rfk= github.com/aliyun/alibaba-cloud-sdk-go v1.61.1402/go.mod h1:RcDobYh8k5VP6TNybz9m++gL3ijVI5wueVr0EM10VsU= github.com/aliyun/alibaba-cloud-sdk-go v1.61.1620 h1:diBUSNskvZjiX1LFa3I+AfHaVnKvphXHddf0eVuCVFg= @@ -136,8 +135,6 @@ github.com/dtm-labs/dtmdriver v0.0.1/go.mod h1:fLiEeD2BPwM9Yq96TfcP9KpbTwFsn5nTx github.com/dtm-labs/dtmdriver v0.0.2/go.mod h1:fLiEeD2BPwM9Yq96TfcP9KpbTwFsn5nTxa/PP0jmFuk= github.com/dtm-labs/dtmdriver v0.0.3 h1:9iAtvXKR3lJXQ7dvS87e4xdtmqkzN+ofek+CF9AvUSY= github.com/dtm-labs/dtmdriver v0.0.3/go.mod h1:fLiEeD2BPwM9Yq96TfcP9KpbTwFsn5nTxa/PP0jmFuk= -github.com/dtm-labs/dtmdriver-gozero v0.0.4 h1:GN+x3pmk545BgvbR4oiKhJ7N8k5yZ2rkG1aCwj8ZDZ8= -github.com/dtm-labs/dtmdriver-gozero v0.0.4/go.mod h1:B5FqzfvzGe2AcB8MpAP34eSLszkCd6hm+t5KJN2Fu/o= github.com/dtm-labs/dtmdriver-gozero v0.0.5 h1:cMBkURDRPcb1Y6/kY+x/yxYA8KWMG+fkK6b+cs4WXKo= github.com/dtm-labs/dtmdriver-gozero v0.0.5/go.mod h1:U4nIisQ5SBZrajp7ky1Bi0eBxPiGqVy+tOs47beobY4= github.com/dtm-labs/dtmdriver-http v1.2.2 h1:QOul+PpK1KQyXXx5viNrHrEFIc/nFxmX4fJfI3DLUqI= @@ -185,7 +182,6 @@ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs= github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= -github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= @@ -228,15 +224,12 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/form/v4 v4.2.0/go.mod h1:q1a2BY+AQUUzhl6xA/6hBetay6dEIhMHjgvJiGo6K7U= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= -github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-playground/validator/v10 v10.11.0 h1:0W+xRM511GY47Yy3bZUbJVitCNg2BOGlCyvTqsp/xIw= github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= @@ -466,10 +459,10 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI= github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= @@ -508,7 +501,6 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= @@ -708,11 +700,9 @@ github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3/go.mod h1:QDlpd3qS71vYtakd2hmdpqhJ9nwv6mD6A30bQ1BPBFE= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= -github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= @@ -734,7 +724,6 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/zeromicro/go-zero v1.3.0/go.mod h1:Hy4o1VFAt32lXaQMbaBhoFeZjA/rJqJ4PTGNdGsURcc= -github.com/zeromicro/go-zero v1.3.2 h1:2HcmceZDEGwZWvofCG+0GXyh+Gtz/wKCW4Fq8Mb7KIg= github.com/zeromicro/go-zero v1.3.2/go.mod h1:DEj3Fwj1Ui1ltsgf6YqwTL9nD4+tYzIRX0c1pWtQo1E= github.com/zeromicro/go-zero v1.3.3 h1:6qv9PcfqfB1tMgp1FJlP1LfWSZ4XD+FwojvA2h5LL2k= github.com/zeromicro/go-zero v1.3.3/go.mod h1:LwuYc2V04ZHhWPWGJYQ+kJ5DT4QSkeaZGqXiQcpkfks= @@ -756,8 +745,6 @@ go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lL go.etcd.io/etcd/client/v3 v3.5.1/go.mod h1:OnjH4M8OnAotwaB2l9bVgZzRFKru7/ZMoS46OtKyd3Q= go.etcd.io/etcd/client/v3 v3.5.2 h1:WdnejrUtQC4nCxK0/dLTMqKOB+U5TP/2Ya0BJL+1otA= go.etcd.io/etcd/client/v3 v3.5.2/go.mod h1:kOOaWFFgHygyT0WlSmL8TJiXmMysO/nNUlEsSsN6W4o= -go.mongodb.org/mongo-driver v1.8.3 h1:TDKlTkGDKm9kkJVUOAXDK5/fkqKHJVwYQSpoRfB43R4= -go.mongodb.org/mongo-driver v1.8.3/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY= go.mongodb.org/mongo-driver v1.9.0 h1:f3aLGJvQmBl8d9S40IL+jEyBC6hfLPbJjv9t5hEM9ck= go.mongodb.org/mongo-driver v1.9.0/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -766,8 +753,6 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= -go.opentelemetry.io/otel v1.6.3 h1:FLOfo8f9JzFVFVyU+MSRJc2HdEAXQgm7pIv2uFKRSZE= -go.opentelemetry.io/otel v1.6.3/go.mod h1:7BgNga5fNlF/iZjG06hM3yofffp0ofKCDwSXx1GC4dI= go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM= go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk= go.opentelemetry.io/otel/exporters/jaeger v1.3.0/go.mod h1:KoYHi1BtkUPncGSRtCe/eh1ijsnePhSkxwzz07vU0Fc= @@ -775,8 +760,6 @@ go.opentelemetry.io/otel/exporters/zipkin v1.3.0/go.mod h1:LxGGfHIYbvsFnrJtBcazb go.opentelemetry.io/otel/sdk v1.3.0 h1:3278edCoH89MEJ0Ky8WQXVmDQv3FX4ZJ3Pp+9fJreAI= go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= -go.opentelemetry.io/otel/trace v1.6.3 h1:IqN4L+5b0mPNjdXIiZ90Ni4Bl5BRkDQywePLWemd9bc= -go.opentelemetry.io/otel/trace v1.6.3/go.mod h1:GNJQusJlUgZl9/TQBPKU/Y/ty+0iVB5fjhKeJGZPGFs= go.opentelemetry.io/otel/trace v1.7.0 h1:O37Iogk1lEkMRXewVtZ1BBTVn5JEp8GrJvP92bJqC6o= go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= @@ -828,8 +811,6 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -914,7 +895,6 @@ golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220421235706-1d1ef9303861 h1:yssD99+7tqHWO5Gwh81phT+67hg+KttniBr6UnEXOY8= golang.org/x/net v0.0.0-20220421235706-1d1ef9303861/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -936,7 +916,6 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 h1:w8s32wxx3sY+OjLlv9qltkLU5yvJzxjjgiHWLjdIcw4= golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1012,8 +991,6 @@ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1160,7 +1137,6 @@ google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20220112215332-a9c7c0acf9f2/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220228195345-15d65a4533f7 h1:ntPPoHzFW6Xp09ueznmahONZufyoSakK/piXnr2BU3I= google.golang.org/genproto v0.0.0-20220228195345-15d65a4533f7/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220422154200-b37d22cd5731 h1:nquqdM9+ps0JZcIiI70+tqoaIFS5Ql4ZuK8UXnz3HfE= google.golang.org/genproto v0.0.0-20220422154200-b37d22cd5731/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= @@ -1183,7 +1159,6 @@ google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.46.2 h1:u+MLGgVf7vRdjEYZ8wDFhAVNmhkbJ5hmrA1LMWK1CAQ= @@ -1216,7 +1191,6 @@ gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaD gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.42.0 h1:7N3gPTt50s8GuLortA00n8AqRTk75qOP98+mTPpgzRk= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI= diff --git a/sqls/dtmsvr.storage.mysql.sql b/sqls/dtmsvr.storage.mysql.sql index dd2a097..50e4f9a 100644 --- a/sqls/dtmsvr.storage.mysql.sql +++ b/sqls/dtmsvr.storage.mysql.sql @@ -19,6 +19,7 @@ CREATE TABLE if not EXISTS dtm.trans_global ( `next_cron_time` datetime default null comment 'next time to process this trans. for use of cron job', `owner` varchar(128) not null default '' comment 'who is locking this trans', `ext_data` TEXT comment 'extended data for this trans', + `rollback_reason` varchar(1024) DEFAULT '' COMMENT 'rollback reason for transaction', PRIMARY KEY (`id`), UNIQUE KEY `gid` (`gid`), key `owner`(`owner`), diff --git a/sqls/dtmsvr.storage.postgres.sql b/sqls/dtmsvr.storage.postgres.sql index 2a1cf67..898de34 100644 --- a/sqls/dtmsvr.storage.postgres.sql +++ b/sqls/dtmsvr.storage.postgres.sql @@ -18,6 +18,7 @@ CREATE TABLE if not EXISTS trans_global ( next_cron_time timestamp(0) with time zone default null, owner varchar(128) not null default '', ext_data text, + rollback_reason varchar(1024) DEFAULT '', PRIMARY KEY (id), CONSTRAINT gid UNIQUE (gid) ); @@ -41,4 +42,4 @@ CREATE TABLE IF NOT EXISTS trans_branch_op ( update_time timestamp(0) with time zone DEFAULT NULL, PRIMARY KEY (id), CONSTRAINT gid_branch_uniq UNIQUE (gid, branch_id, op) -); \ No newline at end of file +); diff --git a/sqls/dtmsvr.storage.tdsql.sql b/sqls/dtmsvr.storage.tdsql.sql index ded809f..a24992c 100644 --- a/sqls/dtmsvr.storage.tdsql.sql +++ b/sqls/dtmsvr.storage.tdsql.sql @@ -19,6 +19,7 @@ CREATE TABLE if not EXISTS dtm.trans_global ( `next_cron_time` datetime default null comment 'next time to process this trans. for use of cron job', `owner` varchar(128) not null default '' comment 'who is locking this trans', `ext_data` TEXT comment 'extended data for this trans', + `rollback_reason` varchar(1024) DEFAULT '' COMMENT 'rollback reason for transaction', PRIMARY KEY (`id`,`gid`), UNIQUE KEY `id` (`id`,`gid`), UNIQUE KEY `gid` (`gid`), diff --git a/test/dtmsvr_test.go b/test/dtmsvr_test.go index 345bebe..273fe36 100644 --- a/test/dtmsvr_test.go +++ b/test/dtmsvr_test.go @@ -26,6 +26,10 @@ func getTransStatus(gid string) string { return dtmsvr.GetTransGlobal(gid).Status } +func getTrans(gid string) *dtmsvr.TransGlobal { + return dtmsvr.GetTransGlobal(gid) +} + func getBranchesStatus(gid string) []string { branches := dtmsvr.GetStore().FindBranches(gid) status := []string{} diff --git a/test/tcc_test.go b/test/tcc_test.go index 60fccd2..3196926 100644 --- a/test/tcc_test.go +++ b/test/tcc_test.go @@ -7,6 +7,7 @@ package test import ( + "fmt" "testing" "github.com/dtm-labs/dtm/dtmcli" @@ -67,6 +68,8 @@ func TestTccTimeout(t *testing.T) { }) assert.Error(t, err) assert.Equal(t, StatusFailed, getTransStatus(gid)) + assert.Regexp(t, `^Timeout after \d+ seconds$`, getTrans(gid).RollbackReason) + fmt.Println(getTrans(gid).RollbackReason) assert.Equal(t, []string{StatusSucceed, StatusPrepared}, getBranchesStatus(gid)) } From 591e75b17a52a24ef066041b62737685aa829542 Mon Sep 17 00:00:00 2001 From: xyctruth <398041993@qq.com> Date: Mon, 20 Jun 2022 16:58:52 +0800 Subject: [PATCH 06/32] fix log fmt --- dtmsvr/trans_status.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dtmsvr/trans_status.go b/dtmsvr/trans_status.go index 9cef0ae..a9d497b 100644 --- a/dtmsvr/trans_status.go +++ b/dtmsvr/trans_status.go @@ -67,7 +67,7 @@ func (t *TransGlobal) changeStatus(status string, opts ...changeStatusOption) { } t.UpdateTime = &now GetStore().ChangeGlobalStatus(&t.TransGlobalStore, status, updates, status == dtmcli.StatusSucceed || status == dtmcli.StatusFailed) - logger.Infof("ChangeGlobalStatus to %statusParams ok for %statusParams", status, t.TransGlobalStore.String()) + logger.Infof("ChangeGlobalStatus to %s ok for %s", status, t.TransGlobalStore.String()) t.Status = status } From 069aa0b8386670167c8305a5a35c3a765807c192 Mon Sep 17 00:00:00 2001 From: xyctruth <398041993@qq.com> Date: Mon, 20 Jun 2022 17:01:04 +0800 Subject: [PATCH 07/32] fix golangci-lint --- dtmsvr/trans_type_tcc.go | 1 + 1 file changed, 1 insertion(+) diff --git a/dtmsvr/trans_type_tcc.go b/dtmsvr/trans_type_tcc.go index 1f5ef2b..11f23b7 100644 --- a/dtmsvr/trans_type_tcc.go +++ b/dtmsvr/trans_type_tcc.go @@ -2,6 +2,7 @@ package dtmsvr import ( "fmt" + "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" "github.com/dtm-labs/dtm/dtmcli/logger" From f796e5c3bad00742f5adda2280f873b8f373c30f Mon Sep 17 00:00:00 2001 From: xyctruth <398041993@qq.com> Date: Mon, 20 Jun 2022 17:08:43 +0800 Subject: [PATCH 08/32] xa add rollback_reason --- dtmsvr/trans_type_xa.go | 4 +++- test/tcc_test.go | 2 -- test/xa_test.go | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/dtmsvr/trans_type_xa.go b/dtmsvr/trans_type_xa.go index d4ca3b3..c74f188 100644 --- a/dtmsvr/trans_type_xa.go +++ b/dtmsvr/trans_type_xa.go @@ -1,6 +1,8 @@ package dtmsvr import ( + "fmt" + "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" ) @@ -22,7 +24,7 @@ func (t *transXaProcessor) ProcessOnce(branches []TransBranch) error { return nil } if t.Status == dtmcli.StatusPrepared && t.isTimeout() { - t.changeStatus(dtmcli.StatusAborting) + t.changeStatus(dtmcli.StatusAborting, withRollbackReason(fmt.Sprintf("Timeout after %d seconds", t.TimeoutToFail))) } currentType := dtmimp.If(t.Status == dtmcli.StatusSubmitted, dtmimp.OpCommit, dtmimp.OpRollback).(string) for i, branch := range branches { diff --git a/test/tcc_test.go b/test/tcc_test.go index 3196926..f4f229d 100644 --- a/test/tcc_test.go +++ b/test/tcc_test.go @@ -7,7 +7,6 @@ package test import ( - "fmt" "testing" "github.com/dtm-labs/dtm/dtmcli" @@ -69,7 +68,6 @@ func TestTccTimeout(t *testing.T) { assert.Error(t, err) assert.Equal(t, StatusFailed, getTransStatus(gid)) assert.Regexp(t, `^Timeout after \d+ seconds$`, getTrans(gid).RollbackReason) - fmt.Println(getTrans(gid).RollbackReason) assert.Equal(t, []string{StatusSucceed, StatusPrepared}, getBranchesStatus(gid)) } diff --git a/test/xa_test.go b/test/xa_test.go index 82d10c7..a15c339 100644 --- a/test/xa_test.go +++ b/test/xa_test.go @@ -94,6 +94,7 @@ func TestXaTimeout(t *testing.T) { }) assert.Error(t, err) assert.Equal(t, StatusFailed, getTransStatus(gid)) + assert.Regexp(t, `^Timeout after \d+ seconds$`, getTrans(gid).RollbackReason) assert.Equal(t, []string{}, getBranchesStatus(gid)) } From 60abdfc6cdbedea29fe9297e824ac8d451ccaa57 Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Wed, 22 Jun 2022 15:31:32 +0800 Subject: [PATCH 09/32] next_cron_time query use time string. independent of db timezone --- dtmsvr/storage/sql/sql.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/dtmsvr/storage/sql/sql.go b/dtmsvr/storage/sql/sql.go index 7ad4cbc..0ad3565 100644 --- a/dtmsvr/storage/sql/sql.go +++ b/dtmsvr/storage/sql/sql.go @@ -138,9 +138,10 @@ func (s *Store) TouchCronTime(global *storage.TransGlobalStore, nextCronInterval func (s *Store) LockOneGlobalTrans(expireIn time.Duration) *storage.TransGlobalStore { db := dbGet() owner := shortuuid.New() + nextCronTime := getTimeStr(int64(expireIn / time.Second)) where := map[string]string{ - dtmimp.DBTypeMysql: fmt.Sprintf(`next_cron_time < date_add(now(), interval %d second) and status in ('prepared', 'aborting', 'submitted') limit 1`, int(expireIn/time.Second)), - dtmimp.DBTypePostgres: fmt.Sprintf(`id in (select id from trans_global where next_cron_time < current_timestamp + interval '%d second' and status in ('prepared', 'aborting', 'submitted') limit 1 )`, int(expireIn/time.Second)), + dtmimp.DBTypeMysql: fmt.Sprintf(`next_cron_time < '%s' and status in ('prepared', 'aborting', 'submitted') limit 1`, nextCronTime), + dtmimp.DBTypePostgres: fmt.Sprintf(`id in (select id from trans_global where next_cron_time < '%s' and status in ('prepared', 'aborting', 'submitted') limit 1 )`, nextCronTime), }[conf.Store.Driver] sql := fmt.Sprintf(`UPDATE trans_global SET update_time='%s',next_cron_time='%s', owner='%s' WHERE %s`, @@ -162,9 +163,10 @@ func (s *Store) LockOneGlobalTrans(expireIn time.Duration) *storage.TransGlobalS // ResetCronTime reset nextCronTime // unfinished transactions need to be retried as soon as possible after business downtime is recovered func (s *Store) ResetCronTime(after time.Duration, limit int64) (succeedCount int64, hasRemaining bool, err error) { + nextCronTime := getTimeStr(int64(after / time.Second)) where := map[string]string{ - dtmimp.DBTypeMysql: fmt.Sprintf(`next_cron_time > date_add(now(), interval %d second) and status in ('prepared', 'aborting', 'submitted') limit %d`, int(after/time.Second), limit), - dtmimp.DBTypePostgres: fmt.Sprintf(`id in (select id from trans_global where next_cron_time > current_timestamp + interval '%d second' and status in ('prepared', 'aborting', 'submitted') limit %d )`, int(after/time.Second), limit), + dtmimp.DBTypeMysql: fmt.Sprintf(`next_cron_time > '%s' and status in ('prepared', 'aborting', 'submitted') limit %d`, nextCronTime, limit), + dtmimp.DBTypePostgres: fmt.Sprintf(`id in (select id from trans_global where next_cron_time > '%s' and status in ('prepared', 'aborting', 'submitted') limit %d )`, nextCronTime, limit), }[conf.Store.Driver] sql := fmt.Sprintf(`UPDATE trans_global SET update_time='%s',next_cron_time='%s' WHERE %s`, From 2e8508c43ef4b395eb862e33db9362773c94caa4 Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Wed, 22 Jun 2022 16:17:23 +0800 Subject: [PATCH 10/32] update release order --- .github/workflows/release.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 59a61df..2edc31e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,6 +18,18 @@ jobs: - name: Check out code uses: actions/checkout@v3 + - name: Validates GO releaser config + uses: docker://goreleaser/goreleaser:v1.7.0 + with: + args: check + + - name: Create release on GitHub + uses: docker://goreleaser/goreleaser:v1.7.0 + with: + args: release -f helper/.goreleaser.yml --rm-dist + env: + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + - name: Setup node uses: actions/setup-node@v3 with: @@ -49,18 +61,6 @@ jobs: echo > dist/placeholder cd .. - - name: Validates GO releaser config - uses: docker://goreleaser/goreleaser:v1.7.0 - with: - args: check - - - name: Create release on GitHub - uses: docker://goreleaser/goreleaser:v1.7.0 - with: - args: release -f helper/.goreleaser.yml --rm-dist - env: - GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} - - name: Create Docker id: meta uses: docker/metadata-action@v3 From 9e5cb99d135bc876dd8b638625c21ab852d78cff Mon Sep 17 00:00:00 2001 From: xyctruth <398041993@qq.com> Date: Wed, 22 Jun 2022 16:26:31 +0800 Subject: [PATCH 11/32] saga add RollbackReason --- dtmsvr/trans_type_saga.go | 9 ++++++--- test/saga_options_test.go | 2 ++ test/saga_test.go | 5 +++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/dtmsvr/trans_type_saga.go b/dtmsvr/trans_type_saga.go index 2009ae4..31d082c 100644 --- a/dtmsvr/trans_type_saga.go +++ b/dtmsvr/trans_type_saga.go @@ -55,7 +55,7 @@ func (t *transSagaProcessor) ProcessOnce(branches []TransBranch) error { // when saga tasks is fetched, it always need to process logger.Debugf("status: %s timeout: %t", t.Status, t.isTimeout()) if t.Status == dtmcli.StatusSubmitted && t.isTimeout() { - t.changeStatus(dtmcli.StatusAborting) + t.changeStatus(dtmcli.StatusAborting, withRollbackReason(fmt.Sprintf("Timeout after %d seconds", t.TimeoutToFail))) } n := len(branches) @@ -219,8 +219,11 @@ func (t *transSagaProcessor) ProcessOnce(branches []TransBranch) error { t.changeStatus(dtmcli.StatusSucceed) return nil } - if t.Status == dtmcli.StatusSubmitted && (rsAFailed > 0 || t.isTimeout()) { - t.changeStatus(dtmcli.StatusAborting) + if t.Status == dtmcli.StatusSubmitted && rsAFailed > 0 { + t.changeStatus(dtmcli.StatusAborting, withRollbackReason("Transaction branch execution failed")) + } + if t.Status == dtmcli.StatusSubmitted && t.isTimeout() { + t.changeStatus(dtmcli.StatusAborting, withRollbackReason(fmt.Sprintf("Timeout after %d seconds", t.TimeoutToFail))) } if t.Status == dtmcli.StatusAborting { prepareToCompensate() diff --git a/test/saga_options_test.go b/test/saga_options_test.go index 6134ee7..557ab1d 100644 --- a/test/saga_options_test.go +++ b/test/saga_options_test.go @@ -56,6 +56,8 @@ func TestSagaOptionsTimeout(t *testing.T) { cronTransOnceForwardNow(t, gid, 3600) assert.Equal(t, StatusFailed, getTransStatus(saga.Gid)) assert.Equal(t, []string{StatusSucceed, StatusPrepared, StatusPrepared, StatusPrepared}, getBranchesStatus(saga.Gid)) + assert.Regexp(t, `^Timeout after \d+ seconds$`, getTrans(gid).RollbackReason) + } func TestSagaGlobalTransWithRequestTimeout(t *testing.T) { diff --git a/test/saga_test.go b/test/saga_test.go index d7b9ad7..56409a1 100644 --- a/test/saga_test.go +++ b/test/saga_test.go @@ -22,6 +22,7 @@ func TestSagaNormal(t *testing.T) { waitTransProcessed(saga.Gid) assert.Equal(t, []string{StatusPrepared, StatusSucceed, StatusPrepared, StatusSucceed}, getBranchesStatus(saga.Gid)) assert.Equal(t, StatusSucceed, getTransStatus(saga.Gid)) + assert.Equal(t, "", getTrans(saga.Gid).RollbackReason) } func TestSagaRollback(t *testing.T) { @@ -31,6 +32,7 @@ func TestSagaRollback(t *testing.T) { waitTransProcessed(saga.Gid) assert.Equal(t, []string{StatusSucceed, StatusSucceed, StatusSucceed, StatusFailed}, getBranchesStatus(saga.Gid)) assert.Equal(t, StatusFailed, getTransStatus(saga.Gid)) + assert.Equal(t, "Transaction branch execution failed", getTrans(saga.Gid).RollbackReason) } func TestSagaOngoingSucceed(t *testing.T) { @@ -44,6 +46,7 @@ func TestSagaOngoingSucceed(t *testing.T) { cronTransOnce(t, gid) assert.Equal(t, []string{StatusPrepared, StatusSucceed, StatusPrepared, StatusSucceed}, getBranchesStatus(saga.Gid)) assert.Equal(t, StatusSucceed, getTransStatus(saga.Gid)) + assert.Equal(t, "", getTrans(saga.Gid).RollbackReason) } func TestSagaFailed(t *testing.T) { @@ -54,9 +57,11 @@ func TestSagaFailed(t *testing.T) { assert.Nil(t, err) waitTransProcessed(saga.Gid) assert.Equal(t, StatusAborting, getTransStatus(saga.Gid)) + assert.Equal(t, "Transaction branch execution failed", getTrans(saga.Gid).RollbackReason) cronTransOnce(t, gid) assert.Equal(t, StatusFailed, getTransStatus(saga.Gid)) assert.Equal(t, []string{StatusSucceed, StatusSucceed, StatusSucceed, StatusFailed}, getBranchesStatus(saga.Gid)) + assert.Equal(t, "Transaction branch execution failed", getTrans(saga.Gid).RollbackReason) } func TestSagaAbnormal(t *testing.T) { From 47c2abcb757bdef483dd7d9d8b00811152a257b9 Mon Sep 17 00:00:00 2001 From: xyctruth <398041993@qq.com> Date: Wed, 22 Jun 2022 18:50:47 +0800 Subject: [PATCH 12/32] saga http failed rollback reason --- dtmsvr/storage/trans.go | 17 +++++++++-------- dtmsvr/trans_status.go | 1 + dtmsvr/trans_type_saga.go | 15 +++++++++------ test/saga_test.go | 3 ++- test/types.go | 2 +- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/dtmsvr/storage/trans.go b/dtmsvr/storage/trans.go index 749eb1a..ee64312 100644 --- a/dtmsvr/storage/trans.go +++ b/dtmsvr/storage/trans.go @@ -55,14 +55,15 @@ func (g *TransGlobalStore) String() string { // TransBranchStore branch transaction type TransBranchStore struct { dtmutil.ModelBase - Gid string `json:"gid,omitempty"` - URL string `json:"url,omitempty"` - BinData []byte - BranchID string `json:"branch_id,omitempty"` - Op string `json:"op,omitempty"` - Status string `json:"status,omitempty"` - FinishTime *time.Time `json:"finish_time,omitempty"` - RollbackTime *time.Time `json:"rollback_time,omitempty"` + Gid string `json:"gid,omitempty"` + URL string `json:"url,omitempty"` + BinData []byte + BranchID string `json:"branch_id,omitempty"` + Op string `json:"op,omitempty"` + Status string `json:"status,omitempty"` + FinishTime *time.Time `json:"finish_time,omitempty"` + RollbackTime *time.Time `json:"rollback_time,omitempty"` + RollbackReason string `json:"-" gorm:"-"` } // TableName TableName diff --git a/dtmsvr/trans_status.go b/dtmsvr/trans_status.go index a9d497b..750c095 100644 --- a/dtmsvr/trans_status.go +++ b/dtmsvr/trans_status.go @@ -190,6 +190,7 @@ func (t *TransGlobal) getBranchResult(branch *TransBranch) (string, error) { if err == nil { return dtmcli.StatusSucceed, nil } else if t.TransType == "saga" && branch.Op == dtmimp.OpAction && errors.Is(err, dtmcli.ErrFailure) { + branch.RollbackReason = fmt.Sprintf("url:%s return failed: %s", branch.URL, err.Error()) return dtmcli.StatusFailed, nil } else if errors.Is(err, dtmcli.ErrOngoing) { return "", dtmcli.ErrOngoing diff --git a/dtmsvr/trans_type_saga.go b/dtmsvr/trans_type_saga.go index 31d082c..359bc7b 100644 --- a/dtmsvr/trans_type_saga.go +++ b/dtmsvr/trans_type_saga.go @@ -45,10 +45,11 @@ type cSagaCustom struct { } type branchResult struct { - index int - status string - started bool - op string + index int + status string + started bool + op string + rollbackReason string } func (t *transSagaProcessor) ProcessOnce(branches []TransBranch) error { @@ -73,6 +74,7 @@ func (t *transSagaProcessor) ProcessOnce(branches []TransBranch) error { } // resultStats var rsAToStart, rsAStarted, rsADone, rsAFailed, rsASucceed, rsCToStart, rsCDone, rsCSucceed int + var rollbackReason string branchResults := make([]branchResult, n) // save the branch result for i := 0; i < n; i++ { b := branches[i] @@ -125,7 +127,7 @@ func (t *transSagaProcessor) ProcessOnce(branches []TransBranch) error { if x := recover(); x != nil { err = dtmimp.AsError(x) } - resultChan <- branchResult{index: i, status: branches[i].Status, op: branches[i].Op} + resultChan <- branchResult{index: i, status: branches[i].Status, op: branches[i].Op, rollbackReason: branches[i].RollbackReason} if err != nil && !errors.Is(err, dtmcli.ErrOngoing) { logger.Errorf("exec branch %s %s %s error: %v", branches[i].BranchID, branches[i].Op, branches[i].URL, err) } @@ -172,6 +174,7 @@ func (t *transSagaProcessor) ProcessOnce(branches []TransBranch) error { rsADone++ if r.status == dtmcli.StatusFailed { rsAFailed++ + rollbackReason = r.rollbackReason } else if r.status == dtmcli.StatusSucceed { rsASucceed++ } @@ -220,7 +223,7 @@ func (t *transSagaProcessor) ProcessOnce(branches []TransBranch) error { return nil } if t.Status == dtmcli.StatusSubmitted && rsAFailed > 0 { - t.changeStatus(dtmcli.StatusAborting, withRollbackReason("Transaction branch execution failed")) + t.changeStatus(dtmcli.StatusAborting, withRollbackReason(rollbackReason)) } if t.Status == dtmcli.StatusSubmitted && t.isTimeout() { t.changeStatus(dtmcli.StatusAborting, withRollbackReason(fmt.Sprintf("Timeout after %d seconds", t.TimeoutToFail))) diff --git a/test/saga_test.go b/test/saga_test.go index 56409a1..564c4a4 100644 --- a/test/saga_test.go +++ b/test/saga_test.go @@ -27,12 +27,13 @@ func TestSagaNormal(t *testing.T) { func TestSagaRollback(t *testing.T) { saga := genSaga(dtmimp.GetFuncName(), false, true) + saga.Concurrent = false err := saga.Submit() assert.Nil(t, err) waitTransProcessed(saga.Gid) assert.Equal(t, []string{StatusSucceed, StatusSucceed, StatusSucceed, StatusFailed}, getBranchesStatus(saga.Gid)) assert.Equal(t, StatusFailed, getTransStatus(saga.Gid)) - assert.Equal(t, "Transaction branch execution failed", getTrans(saga.Gid).RollbackReason) + assert.Equal(t, "url:http://localhost:8081/api/busi/TransIn return failed: {\"error\":\"FAILURE\"}. FAILURE", getTrans(saga.Gid).RollbackReason) } func TestSagaOngoingSucceed(t *testing.T) { diff --git a/test/types.go b/test/types.go index 0f3ed43..3193f53 100644 --- a/test/types.go +++ b/test/types.go @@ -33,7 +33,7 @@ func waitTransProcessed(gid string) { case id := <-dtmsvr.TransProcessedTestChan: logger.FatalfIf(id != gid, "------- expecting: %s but %s found", gid, id) logger.Debugf("finish for gid %s", gid) - case <-time.After(time.Duration(time.Second * 4)): + case <-time.After(time.Duration(time.Second * 10000)): logger.FatalfIf(true, "Wait Trans timeout") } } From 95ef160a45ca7279ab7701dea971ad75f072f12f Mon Sep 17 00:00:00 2001 From: xyctruth <398041993@qq.com> Date: Wed, 22 Jun 2022 18:53:01 +0800 Subject: [PATCH 13/32] saga http failed rollback reason --- test/saga_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/saga_test.go b/test/saga_test.go index 564c4a4..38f2bf7 100644 --- a/test/saga_test.go +++ b/test/saga_test.go @@ -58,11 +58,10 @@ func TestSagaFailed(t *testing.T) { assert.Nil(t, err) waitTransProcessed(saga.Gid) assert.Equal(t, StatusAborting, getTransStatus(saga.Gid)) - assert.Equal(t, "Transaction branch execution failed", getTrans(saga.Gid).RollbackReason) cronTransOnce(t, gid) assert.Equal(t, StatusFailed, getTransStatus(saga.Gid)) assert.Equal(t, []string{StatusSucceed, StatusSucceed, StatusSucceed, StatusFailed}, getBranchesStatus(saga.Gid)) - assert.Equal(t, "Transaction branch execution failed", getTrans(saga.Gid).RollbackReason) + assert.Equal(t, "url:http://localhost:8081/api/busi/TransIn return failed: {\"error\":\"FAILURE\"}. FAILURE", getTrans(saga.Gid).RollbackReason) } func TestSagaAbnormal(t *testing.T) { From 707b07cf12fa316cb33d5dd16e10081745fa6cae Mon Sep 17 00:00:00 2001 From: xyctruth <398041993@qq.com> Date: Thu, 23 Jun 2022 10:53:09 +0800 Subject: [PATCH 14/32] saga http failed rollback reason --- dtmsvr/storage/trans.go | 18 +++++++++--------- dtmsvr/trans_status.go | 2 +- dtmsvr/trans_type_saga.go | 18 +++++++++--------- test/busi/base_types.go | 1 + test/busi/busi.go | 6 ++++++ test/saga_test.go | 5 ++--- 6 files changed, 28 insertions(+), 22 deletions(-) diff --git a/dtmsvr/storage/trans.go b/dtmsvr/storage/trans.go index ee64312..f6f1a47 100644 --- a/dtmsvr/storage/trans.go +++ b/dtmsvr/storage/trans.go @@ -55,15 +55,15 @@ func (g *TransGlobalStore) String() string { // TransBranchStore branch transaction type TransBranchStore struct { dtmutil.ModelBase - Gid string `json:"gid,omitempty"` - URL string `json:"url,omitempty"` - BinData []byte - BranchID string `json:"branch_id,omitempty"` - Op string `json:"op,omitempty"` - Status string `json:"status,omitempty"` - FinishTime *time.Time `json:"finish_time,omitempty"` - RollbackTime *time.Time `json:"rollback_time,omitempty"` - RollbackReason string `json:"-" gorm:"-"` + Gid string `json:"gid,omitempty"` + URL string `json:"url,omitempty"` + BinData []byte + BranchID string `json:"branch_id,omitempty"` + Op string `json:"op,omitempty"` + Status string `json:"status,omitempty"` + FinishTime *time.Time `json:"finish_time,omitempty"` + RollbackTime *time.Time `json:"rollback_time,omitempty"` + Error error `json:"-" gorm:"-"` } // TableName TableName diff --git a/dtmsvr/trans_status.go b/dtmsvr/trans_status.go index 750c095..fa1e51e 100644 --- a/dtmsvr/trans_status.go +++ b/dtmsvr/trans_status.go @@ -190,7 +190,7 @@ func (t *TransGlobal) getBranchResult(branch *TransBranch) (string, error) { if err == nil { return dtmcli.StatusSucceed, nil } else if t.TransType == "saga" && branch.Op == dtmimp.OpAction && errors.Is(err, dtmcli.ErrFailure) { - branch.RollbackReason = fmt.Sprintf("url:%s return failed: %s", branch.URL, err.Error()) + branch.Error = fmt.Errorf("url:%s return failed: %w", branch.URL, err) return dtmcli.StatusFailed, nil } else if errors.Is(err, dtmcli.ErrOngoing) { return "", dtmcli.ErrOngoing diff --git a/dtmsvr/trans_type_saga.go b/dtmsvr/trans_type_saga.go index 359bc7b..9117515 100644 --- a/dtmsvr/trans_type_saga.go +++ b/dtmsvr/trans_type_saga.go @@ -45,11 +45,11 @@ type cSagaCustom struct { } type branchResult struct { - index int - status string - started bool - op string - rollbackReason string + index int + status string + started bool + op string + err error } func (t *transSagaProcessor) ProcessOnce(branches []TransBranch) error { @@ -74,7 +74,7 @@ func (t *transSagaProcessor) ProcessOnce(branches []TransBranch) error { } // resultStats var rsAToStart, rsAStarted, rsADone, rsAFailed, rsASucceed, rsCToStart, rsCDone, rsCSucceed int - var rollbackReason string + var failureError error branchResults := make([]branchResult, n) // save the branch result for i := 0; i < n; i++ { b := branches[i] @@ -127,7 +127,7 @@ func (t *transSagaProcessor) ProcessOnce(branches []TransBranch) error { if x := recover(); x != nil { err = dtmimp.AsError(x) } - resultChan <- branchResult{index: i, status: branches[i].Status, op: branches[i].Op, rollbackReason: branches[i].RollbackReason} + resultChan <- branchResult{index: i, status: branches[i].Status, op: branches[i].Op, err: branches[i].Error} if err != nil && !errors.Is(err, dtmcli.ErrOngoing) { logger.Errorf("exec branch %s %s %s error: %v", branches[i].BranchID, branches[i].Op, branches[i].URL, err) } @@ -174,7 +174,7 @@ func (t *transSagaProcessor) ProcessOnce(branches []TransBranch) error { rsADone++ if r.status == dtmcli.StatusFailed { rsAFailed++ - rollbackReason = r.rollbackReason + failureError = r.err } else if r.status == dtmcli.StatusSucceed { rsASucceed++ } @@ -223,7 +223,7 @@ func (t *transSagaProcessor) ProcessOnce(branches []TransBranch) error { return nil } if t.Status == dtmcli.StatusSubmitted && rsAFailed > 0 { - t.changeStatus(dtmcli.StatusAborting, withRollbackReason(rollbackReason)) + t.changeStatus(dtmcli.StatusAborting, withRollbackReason(failureError.Error())) } if t.Status == dtmcli.StatusSubmitted && t.isTimeout() { t.changeStatus(dtmcli.StatusAborting, withRollbackReason(fmt.Sprintf("Timeout after %d seconds", t.TimeoutToFail))) diff --git a/test/busi/base_types.go b/test/busi/base_types.go index 541c2cb..0d4171d 100644 --- a/test/busi/base_types.go +++ b/test/busi/base_types.go @@ -142,6 +142,7 @@ type mainSwitchType struct { QueryPreparedResult AutoEmptyString NextResult AutoEmptyString JrpcResult AutoEmptyString + FailureReason AutoEmptyString } // MainSwitch controls busi success or fail diff --git a/test/busi/busi.go b/test/busi/busi.go index 7d24985..93e8e29 100644 --- a/test/busi/busi.go +++ b/test/busi/busi.go @@ -48,6 +48,12 @@ func handleGeneralBusiness(c *gin.Context, result1 string, result2 string, busi if res == "ERROR" { return errors.New("ERROR from user") } + if res == dtmimp.ResultFailure { + failureReason := MainSwitch.FailureReason.Fetch() + if failureReason != "" { + return fmt.Errorf("%s. %w", failureReason, dtmimp.ErrFailure) + } + } return dtmcli.String2DtmError(res) } diff --git a/test/saga_test.go b/test/saga_test.go index 38f2bf7..aa8c791 100644 --- a/test/saga_test.go +++ b/test/saga_test.go @@ -27,13 +27,13 @@ func TestSagaNormal(t *testing.T) { func TestSagaRollback(t *testing.T) { saga := genSaga(dtmimp.GetFuncName(), false, true) - saga.Concurrent = false + busi.MainSwitch.FailureReason.SetOnce("Insufficient balance") err := saga.Submit() assert.Nil(t, err) waitTransProcessed(saga.Gid) assert.Equal(t, []string{StatusSucceed, StatusSucceed, StatusSucceed, StatusFailed}, getBranchesStatus(saga.Gid)) assert.Equal(t, StatusFailed, getTransStatus(saga.Gid)) - assert.Equal(t, "url:http://localhost:8081/api/busi/TransIn return failed: {\"error\":\"FAILURE\"}. FAILURE", getTrans(saga.Gid).RollbackReason) + assert.Equal(t, "url:http://localhost:8081/api/busi/TransIn return failed: {\"error\":\"Insufficient balance. FAILURE\"}. FAILURE", getTrans(saga.Gid).RollbackReason) } func TestSagaOngoingSucceed(t *testing.T) { @@ -61,7 +61,6 @@ func TestSagaFailed(t *testing.T) { cronTransOnce(t, gid) assert.Equal(t, StatusFailed, getTransStatus(saga.Gid)) assert.Equal(t, []string{StatusSucceed, StatusSucceed, StatusSucceed, StatusFailed}, getBranchesStatus(saga.Gid)) - assert.Equal(t, "url:http://localhost:8081/api/busi/TransIn return failed: {\"error\":\"FAILURE\"}. FAILURE", getTrans(saga.Gid).RollbackReason) } func TestSagaAbnormal(t *testing.T) { From 80437d04dbd4055da9bc5a2ab90f4e83f53b2470 Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Thu, 23 Jun 2022 11:02:40 +0800 Subject: [PATCH 15/32] fix boltdb bug --- dtmsvr/storage/boltdb/boltdb.go | 31 +++++++++++++++---------------- dtmsvr/storage/trans.go | 4 ++++ 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/dtmsvr/storage/boltdb/boltdb.go b/dtmsvr/storage/boltdb/boltdb.go index bccc401..eeedcaf 100644 --- a/dtmsvr/storage/boltdb/boltdb.go +++ b/dtmsvr/storage/boltdb/boltdb.go @@ -11,7 +11,6 @@ import ( "strings" "time" - "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" "github.com/dtm-labs/dtm/dtmcli/logger" "github.com/dtm-labs/dtm/dtmsvr/storage" @@ -383,34 +382,34 @@ func (s *Store) TouchCronTime(global *storage.TransGlobalStore, nextCronInterval // LockOneGlobalTrans finds GlobalTrans func (s *Store) LockOneGlobalTrans(expireIn time.Duration) *storage.TransGlobalStore { - var trans *storage.TransGlobalStore + var transo *storage.TransGlobalStore min := fmt.Sprintf("%d", time.Now().Add(expireIn).Unix()) - next := time.Now().Add(time.Duration(s.retryInterval) * time.Second) err := s.boltDb.Update(func(t *bolt.Tx) error { cursor := t.Bucket(bucketIndex).Cursor() toDelete := [][]byte{} - for trans == nil || trans.Status == dtmcli.StatusSucceed || trans.Status == dtmcli.StatusFailed { - k, v := cursor.First() - if k == nil || string(k) > min { - return storage.ErrNotFound - } - trans = tGetGlobal(t, string(v)) + for k, v := cursor.First(); k != nil && string(k) <= min; k, v = cursor.Next() { toDelete = append(toDelete, k) + trans := tGetGlobal(t, string(v)) + if trans != nil && !trans.IsFinished() { + transo = trans + break + } } for _, k := range toDelete { err := t.Bucket(bucketIndex).Delete(k) dtmimp.E2P(err) } - trans.NextCronTime = &next - tPutGlobal(t, trans) - tPutIndex(t, next.Unix(), trans.Gid) + if transo != nil { + next := time.Now().Add(time.Duration(s.retryInterval) * time.Second) + transo.NextCronTime = &next + tPutGlobal(t, transo) + tPutIndex(t, next.Unix(), transo.Gid) + + } return nil }) - if err == storage.ErrNotFound { - return nil - } dtmimp.E2P(err) - return trans + return transo } // ResetCronTime reset nextCronTime diff --git a/dtmsvr/storage/trans.go b/dtmsvr/storage/trans.go index 749eb1a..29bc6c4 100644 --- a/dtmsvr/storage/trans.go +++ b/dtmsvr/storage/trans.go @@ -52,6 +52,10 @@ func (g *TransGlobalStore) String() string { return dtmimp.MustMarshalString(g) } +func (g *TransGlobalStore) IsFinished() bool { + return g.Status == dtmcli.StatusFailed || g.Status == dtmcli.StatusSucceed +} + // TransBranchStore branch transaction type TransBranchStore struct { dtmutil.ModelBase From d2e20b317e15f4129684dfe1502d67ef84d73a27 Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Thu, 23 Jun 2022 11:08:11 +0800 Subject: [PATCH 16/32] fix lint --- dtmsvr/storage/trans.go | 1 + 1 file changed, 1 insertion(+) diff --git a/dtmsvr/storage/trans.go b/dtmsvr/storage/trans.go index 29bc6c4..43eed98 100644 --- a/dtmsvr/storage/trans.go +++ b/dtmsvr/storage/trans.go @@ -52,6 +52,7 @@ func (g *TransGlobalStore) String() string { return dtmimp.MustMarshalString(g) } +// IsFinished return true if status == "failed" || status == "succeed" func (g *TransGlobalStore) IsFinished() bool { return g.Status == dtmcli.StatusFailed || g.Status == dtmcli.StatusSucceed } From 774c96ecee86822cf52fd30ce5968b08ee5c707e Mon Sep 17 00:00:00 2001 From: xyctruth <398041993@qq.com> Date: Thu, 23 Jun 2022 11:29:03 +0800 Subject: [PATCH 17/32] fix some --- test/busi/busi.go | 5 +---- test/saga_test.go | 2 +- test/types.go | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/test/busi/busi.go b/test/busi/busi.go index 93e8e29..6749783 100644 --- a/test/busi/busi.go +++ b/test/busi/busi.go @@ -49,10 +49,7 @@ func handleGeneralBusiness(c *gin.Context, result1 string, result2 string, busi return errors.New("ERROR from user") } if res == dtmimp.ResultFailure { - failureReason := MainSwitch.FailureReason.Fetch() - if failureReason != "" { - return fmt.Errorf("%s. %w", failureReason, dtmimp.ErrFailure) - } + return fmt.Errorf("reason:%s. %w", MainSwitch.FailureReason.Fetch(), dtmimp.ErrFailure) } return dtmcli.String2DtmError(res) } diff --git a/test/saga_test.go b/test/saga_test.go index aa8c791..f536a4c 100644 --- a/test/saga_test.go +++ b/test/saga_test.go @@ -33,7 +33,7 @@ func TestSagaRollback(t *testing.T) { waitTransProcessed(saga.Gid) assert.Equal(t, []string{StatusSucceed, StatusSucceed, StatusSucceed, StatusFailed}, getBranchesStatus(saga.Gid)) assert.Equal(t, StatusFailed, getTransStatus(saga.Gid)) - assert.Equal(t, "url:http://localhost:8081/api/busi/TransIn return failed: {\"error\":\"Insufficient balance. FAILURE\"}. FAILURE", getTrans(saga.Gid).RollbackReason) + assert.Equal(t, "url:http://localhost:8081/api/busi/TransIn return failed: {\"error\":\"reason:Insufficient balance. FAILURE\"}. FAILURE", getTrans(saga.Gid).RollbackReason) } func TestSagaOngoingSucceed(t *testing.T) { diff --git a/test/types.go b/test/types.go index 3193f53..0f3ed43 100644 --- a/test/types.go +++ b/test/types.go @@ -33,7 +33,7 @@ func waitTransProcessed(gid string) { case id := <-dtmsvr.TransProcessedTestChan: logger.FatalfIf(id != gid, "------- expecting: %s but %s found", gid, id) logger.Debugf("finish for gid %s", gid) - case <-time.After(time.Duration(time.Second * 10000)): + case <-time.After(time.Duration(time.Second * 4)): logger.FatalfIf(true, "Wait Trans timeout") } } From ef007b046111ea0fead02d4d6e3b666247f60881 Mon Sep 17 00:00:00 2001 From: xyctruth <398041993@qq.com> Date: Thu, 23 Jun 2022 11:59:31 +0800 Subject: [PATCH 18/32] grpc error reason --- dtmgrpc/type.go | 3 ++- test/busi/busi.go | 2 +- test/saga_grpc_test.go | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/dtmgrpc/type.go b/dtmgrpc/type.go index f92d830..bce24ba 100644 --- a/dtmgrpc/type.go +++ b/dtmgrpc/type.go @@ -8,6 +8,7 @@ package dtmgrpc import ( context "context" + "fmt" "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" @@ -38,7 +39,7 @@ func GrpcError2DtmError(err error) error { if st.Message() == dtmcli.ResultOngoing { return dtmcli.ErrOngoing } - return dtmcli.ErrFailure + return fmt.Errorf("%s. %w", st.Message(), dtmcli.ErrFailure) } else if ok && st.Code() == codes.FailedPrecondition { return dtmcli.ErrOngoing } diff --git a/test/busi/busi.go b/test/busi/busi.go index 6749783..d6b30bc 100644 --- a/test/busi/busi.go +++ b/test/busi/busi.go @@ -34,7 +34,7 @@ func handleGrpcBusiness(in *BusiReq, result1 string, result2 string, busi string if res == dtmcli.ResultSuccess { return nil } else if res == dtmcli.ResultFailure { - return status.New(codes.Aborted, dtmcli.ResultFailure).Err() + return status.New(codes.Aborted, fmt.Sprintf("reason:%s. %s", MainSwitch.FailureReason.Fetch(), dtmimp.ErrFailure)).Err() } else if res == dtmcli.ResultOngoing { return status.New(codes.FailedPrecondition, dtmcli.ResultOngoing).Err() } diff --git a/test/saga_grpc_test.go b/test/saga_grpc_test.go index 94f1732..273dee6 100644 --- a/test/saga_grpc_test.go +++ b/test/saga_grpc_test.go @@ -28,6 +28,7 @@ func TestSagaGrpcNormal(t *testing.T) { func TestSagaGrpcRollback(t *testing.T) { gid := dtmimp.GetFuncName() saga := genSagaGrpc(gid, false, true) + busi.MainSwitch.FailureReason.SetOnce("Insufficient balance") busi.MainSwitch.TransOutRevertResult.SetOnce(dtmcli.ResultOngoing) saga.Submit() waitTransProcessed(saga.Gid) @@ -35,6 +36,7 @@ func TestSagaGrpcRollback(t *testing.T) { cronTransOnce(t, gid) assert.Equal(t, StatusFailed, getTransStatus(saga.Gid)) assert.Equal(t, []string{StatusSucceed, StatusSucceed, StatusSucceed, StatusFailed}, getBranchesStatus(saga.Gid)) + assert.Equal(t, "url:localhost:58081/busi.Busi/TransIn return failed: reason:Insufficient balance. FAILURE. FAILURE", getTrans(saga.Gid).RollbackReason) } func TestSagaGrpcCurrent(t *testing.T) { From 71f4aaa47034f658c54afce5daf849d4750f1553 Mon Sep 17 00:00:00 2001 From: xyctruth <398041993@qq.com> Date: Thu, 23 Jun 2022 11:59:43 +0800 Subject: [PATCH 19/32] grpc error reason --- dtmgrpc/type.go | 1 + test/busi/busi.go | 2 +- test/saga_grpc_test.go | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dtmgrpc/type.go b/dtmgrpc/type.go index bce24ba..14244e3 100644 --- a/dtmgrpc/type.go +++ b/dtmgrpc/type.go @@ -39,6 +39,7 @@ func GrpcError2DtmError(err error) error { if st.Message() == dtmcli.ResultOngoing { return dtmcli.ErrOngoing } + return fmt.Errorf("%s. %w", st.Message(), dtmcli.ErrFailure) } else if ok && st.Code() == codes.FailedPrecondition { return dtmcli.ErrOngoing diff --git a/test/busi/busi.go b/test/busi/busi.go index d6b30bc..81c9c9e 100644 --- a/test/busi/busi.go +++ b/test/busi/busi.go @@ -34,7 +34,7 @@ func handleGrpcBusiness(in *BusiReq, result1 string, result2 string, busi string if res == dtmcli.ResultSuccess { return nil } else if res == dtmcli.ResultFailure { - return status.New(codes.Aborted, fmt.Sprintf("reason:%s. %s", MainSwitch.FailureReason.Fetch(), dtmimp.ErrFailure)).Err() + return status.New(codes.Aborted, fmt.Sprintf("reason:%s", MainSwitch.FailureReason.Fetch())).Err() } else if res == dtmcli.ResultOngoing { return status.New(codes.FailedPrecondition, dtmcli.ResultOngoing).Err() } diff --git a/test/saga_grpc_test.go b/test/saga_grpc_test.go index 273dee6..9a98d06 100644 --- a/test/saga_grpc_test.go +++ b/test/saga_grpc_test.go @@ -36,7 +36,7 @@ func TestSagaGrpcRollback(t *testing.T) { cronTransOnce(t, gid) assert.Equal(t, StatusFailed, getTransStatus(saga.Gid)) assert.Equal(t, []string{StatusSucceed, StatusSucceed, StatusSucceed, StatusFailed}, getBranchesStatus(saga.Gid)) - assert.Equal(t, "url:localhost:58081/busi.Busi/TransIn return failed: reason:Insufficient balance. FAILURE. FAILURE", getTrans(saga.Gid).RollbackReason) + assert.Equal(t, "url:localhost:58081/busi.Busi/TransIn return failed: reason:Insufficient balance. FAILURE", getTrans(saga.Gid).RollbackReason) } func TestSagaGrpcCurrent(t *testing.T) { From d42a3b9c949d02125139e8f1b61977e22060472a Mon Sep 17 00:00:00 2001 From: leiyuan Date: Thu, 23 Jun 2022 12:42:58 +0800 Subject: [PATCH 20/32] deferDo method logic should not be wrapped by defer agin,thus results panic ignored and not do fail method --- dtmcli/dtmimp/utils.go | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/dtmcli/dtmimp/utils.go b/dtmcli/dtmimp/utils.go index 1e5607a..3127fbe 100644 --- a/dtmcli/dtmimp/utils.go +++ b/dtmcli/dtmimp/utils.go @@ -235,16 +235,14 @@ func RespAsErrorCompatible(resp *resty.Response) error { // DeferDo a common defer do used in dtmcli/dtmgrpc func DeferDo(rerr *error, success func() error, fail func() error) { - defer func() { - if x := recover(); x != nil { - _ = fail() - panic(x) - } else if *rerr != nil { - _ = fail() - } else { - *rerr = success() - } - }() + if x := recover(); x != nil { + _ = fail() + panic(x) + } else if *rerr != nil { + _ = fail() + } else { + *rerr = success() + } } // Escape solve CodeQL reported problem From 97be1a189ca5c896e496b10e28daf1e38ff5a3a3 Mon Sep 17 00:00:00 2001 From: xyctruth <398041993@qq.com> Date: Thu, 23 Jun 2022 18:02:07 +0800 Subject: [PATCH 21/32] jsonrpc error reason --- dtmcli/dtmimp/utils.go | 19 ++++++++ dtmsvr/trans_status.go | 103 +++++++++++++++++++++-------------------- 2 files changed, 71 insertions(+), 51 deletions(-) diff --git a/dtmcli/dtmimp/utils.go b/dtmcli/dtmimp/utils.go index 1e5607a..71b2860 100644 --- a/dtmcli/dtmimp/utils.go +++ b/dtmcli/dtmimp/utils.go @@ -20,6 +20,8 @@ import ( "sync" "time" + "github.com/dtm-labs/dtm/dtmcli" + "github.com/dtm-labs/dtm/dtmcli/logger" "github.com/go-resty/resty/v2" ) @@ -233,6 +235,23 @@ func RespAsErrorCompatible(resp *resty.Response) error { return nil } +// JsonRpcRespAsError translate json rpc resty response to error +func JsonRpcRespAsError(resp *resty.Response) error { + str := resp.String() + var result map[string]interface{} + MustUnmarshalString(str, &result) + if result["error"] != nil { + rerr := result["error"].(map[string]interface{}) + if rerr["code"] == JrpcCodeFailure { + return fmt.Errorf("%s. %w", str, ErrFailure) + } else if rerr["code"] == JrpcCodeOngoing { + return dtmcli.ErrOngoing + } + return errors.New(resp.String()) + } + return nil +} + // DeferDo a common defer do used in dtmcli/dtmgrpc func DeferDo(rerr *error, success func() error, fail func() error) { defer func() { diff --git a/dtmsvr/trans_status.go b/dtmsvr/trans_status.go index fa1e51e..80350e7 100644 --- a/dtmsvr/trans_status.go +++ b/dtmsvr/trans_status.go @@ -113,59 +113,60 @@ func (t *TransGlobal) getURLResult(uri string, branchID, op string, branchPayloa dtmimp.RestyClient.SetTimeout(time.Duration(t.RequestTimeout) * time.Second) } if t.Protocol == "json-rpc" && strings.Contains(uri, "method") { - var params map[string]interface{} - dtmimp.MustUnmarshal(branchPayload, ¶ms) - u, err := url.Parse(uri) - dtmimp.E2P(err) - params["gid"] = t.Gid - params["trans_type"] = t.TransType - params["branch_id"] = branchID - params["op"] = op - resp, err := dtmimp.RestyClient.R().SetBody(map[string]interface{}{ - "params": params, - "jsonrpc": "2.0", - "method": u.Query().Get("method"), - "id": shortuuid.New(), - }). - SetHeader("Content-type", "application/json"). - SetHeaders(t.Ext.Headers). - SetHeaders(t.TransOptions.BranchHeaders). - Post(uri) - if err == nil { - err = dtmimp.RespAsErrorCompatible(resp) - } - var result map[string]interface{} - if err == nil { - dtmimp.MustUnmarshalString(resp.String(), &result) - if result["error"] != nil { - rerr := result["error"].(map[string]interface{}) - if rerr["code"] == dtmimp.JrpcCodeFailure { - return dtmcli.ErrFailure - } else if rerr["code"] == dtmimp.JrpcCodeOngoing { - return dtmcli.ErrOngoing - } - return errors.New(resp.String()) - } - } - return err + return t.getJsonRpcResult(uri, branchID, op, branchPayload) } - resp, err := dtmimp.RestyClient.R().SetBody(string(branchPayload)). - SetQueryParams(map[string]string{ - "gid": t.Gid, - "trans_type": t.TransType, - "branch_id": branchID, - "op": op, - }). - SetHeader("Content-type", "application/json"). - SetHeaders(t.Ext.Headers). - SetHeaders(t.TransOptions.BranchHeaders). - Execute(dtmimp.If(branchPayload != nil || t.TransType == "xa", "POST", "GET").(string), uri) - if err != nil { - return err - } - return dtmimp.RespAsErrorCompatible(resp) + return t.getHttpResult(uri, branchID, op, branchPayload) + } + return t.getGrpcResult(uri, branchID, op, branchPayload) +} + +func (t *TransGlobal) getHttpResult(uri string, branchID, op string, branchPayload []byte) error { + resp, err := dtmimp.RestyClient.R().SetBody(string(branchPayload)). + SetQueryParams(map[string]string{ + "gid": t.Gid, + "trans_type": t.TransType, + "branch_id": branchID, + "op": op, + }). + SetHeader("Content-type", "application/json"). + SetHeaders(t.Ext.Headers). + SetHeaders(t.TransOptions.BranchHeaders). + Execute(dtmimp.If(branchPayload != nil || t.TransType == "xa", "POST", "GET").(string), uri) + if err != nil { + return err } - dtmimp.PanicIf(t.Protocol == dtmimp.ProtocolHTTP, fmt.Errorf("bad url for http: %s", uri)) + return dtmimp.RespAsErrorCompatible(resp) +} + +func (t *TransGlobal) getJsonRpcResult(uri string, branchID, op string, branchPayload []byte) error { + var params map[string]interface{} + dtmimp.MustUnmarshal(branchPayload, ¶ms) + u, err := url.Parse(uri) + dtmimp.E2P(err) + params["gid"] = t.Gid + params["trans_type"] = t.TransType + params["branch_id"] = branchID + params["op"] = op + resp, err := dtmimp.RestyClient.R().SetBody(map[string]interface{}{ + "params": params, + "jsonrpc": "2.0", + "method": u.Query().Get("method"), + "id": shortuuid.New(), + }). + SetHeader("Content-type", "application/json"). + SetHeaders(t.Ext.Headers). + SetHeaders(t.TransOptions.BranchHeaders). + Post(uri) + if err == nil { + err = dtmimp.RespAsErrorCompatible(resp) + } + if err == nil { + err = dtmimp.JsonRpcRespAsError(resp) + } + return err +} + +func (t *TransGlobal) getGrpcResult(uri string, branchID, op string, branchPayload []byte) error { // grpc handler server, method, err := dtmdriver.GetDriver().ParseServerMethod(uri) if err != nil { From ee4571a93e7cc0344e947b0b293df2cea8748773 Mon Sep 17 00:00:00 2001 From: xyctruth <398041993@qq.com> Date: Thu, 23 Jun 2022 18:11:00 +0800 Subject: [PATCH 22/32] fix package reference --- dtmcli/dtmimp/utils.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dtmcli/dtmimp/utils.go b/dtmcli/dtmimp/utils.go index 71b2860..363c98c 100644 --- a/dtmcli/dtmimp/utils.go +++ b/dtmcli/dtmimp/utils.go @@ -20,8 +20,6 @@ import ( "sync" "time" - "github.com/dtm-labs/dtm/dtmcli" - "github.com/dtm-labs/dtm/dtmcli/logger" "github.com/go-resty/resty/v2" ) @@ -245,7 +243,7 @@ func JsonRpcRespAsError(resp *resty.Response) error { if rerr["code"] == JrpcCodeFailure { return fmt.Errorf("%s. %w", str, ErrFailure) } else if rerr["code"] == JrpcCodeOngoing { - return dtmcli.ErrOngoing + return ErrOngoing } return errors.New(resp.String()) } From d30daa959c4427fd35bb363f0e691d9bbd27d822 Mon Sep 17 00:00:00 2001 From: xyctruth <398041993@qq.com> Date: Thu, 23 Jun 2022 18:19:42 +0800 Subject: [PATCH 23/32] fix go lint --- dtmcli/dtmimp/utils.go | 4 ++-- dtmsvr/trans_status.go | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dtmcli/dtmimp/utils.go b/dtmcli/dtmimp/utils.go index 363c98c..93dd1fb 100644 --- a/dtmcli/dtmimp/utils.go +++ b/dtmcli/dtmimp/utils.go @@ -233,8 +233,8 @@ func RespAsErrorCompatible(resp *resty.Response) error { return nil } -// JsonRpcRespAsError translate json rpc resty response to error -func JsonRpcRespAsError(resp *resty.Response) error { +// RespAsErrorByJSONRPC translate json rpc resty response to error +func RespAsErrorByJSONRPC(resp *resty.Response) error { str := resp.String() var result map[string]interface{} MustUnmarshalString(str, &result) diff --git a/dtmsvr/trans_status.go b/dtmsvr/trans_status.go index 80350e7..eb47f7e 100644 --- a/dtmsvr/trans_status.go +++ b/dtmsvr/trans_status.go @@ -113,14 +113,14 @@ func (t *TransGlobal) getURLResult(uri string, branchID, op string, branchPayloa dtmimp.RestyClient.SetTimeout(time.Duration(t.RequestTimeout) * time.Second) } if t.Protocol == "json-rpc" && strings.Contains(uri, "method") { - return t.getJsonRpcResult(uri, branchID, op, branchPayload) + return t.getJSONRPCResult(uri, branchID, op, branchPayload) } - return t.getHttpResult(uri, branchID, op, branchPayload) + return t.getHTTPResult(uri, branchID, op, branchPayload) } return t.getGrpcResult(uri, branchID, op, branchPayload) } -func (t *TransGlobal) getHttpResult(uri string, branchID, op string, branchPayload []byte) error { +func (t *TransGlobal) getHTTPResult(uri string, branchID, op string, branchPayload []byte) error { resp, err := dtmimp.RestyClient.R().SetBody(string(branchPayload)). SetQueryParams(map[string]string{ "gid": t.Gid, @@ -138,7 +138,7 @@ func (t *TransGlobal) getHttpResult(uri string, branchID, op string, branchPaylo return dtmimp.RespAsErrorCompatible(resp) } -func (t *TransGlobal) getJsonRpcResult(uri string, branchID, op string, branchPayload []byte) error { +func (t *TransGlobal) getJSONRPCResult(uri string, branchID, op string, branchPayload []byte) error { var params map[string]interface{} dtmimp.MustUnmarshal(branchPayload, ¶ms) u, err := url.Parse(uri) @@ -161,7 +161,7 @@ func (t *TransGlobal) getJsonRpcResult(uri string, branchID, op string, branchPa err = dtmimp.RespAsErrorCompatible(resp) } if err == nil { - err = dtmimp.JsonRpcRespAsError(resp) + err = dtmimp.RespAsErrorByJSONRPC(resp) } return err } From 5eabe6239f4a066cc10c44faf2bef2947f04fe3a Mon Sep 17 00:00:00 2001 From: xyctruth <398041993@qq.com> Date: Fri, 24 Jun 2022 11:29:48 +0800 Subject: [PATCH 24/32] tcc rollback_reson --- dtmcli/dtmimp/trans_base.go | 1 + dtmcli/tcc.go | 1 + dtmgrpc/dtmgpb/dtmgimp.proto | 1 + dtmgrpc/tcc.go | 1 + dtmsvr/api.go | 2 +- test/tcc_test.go | 1 + 6 files changed, 6 insertions(+), 1 deletion(-) diff --git a/dtmcli/dtmimp/trans_base.go b/dtmcli/dtmimp/trans_base.go index 876bf55..cd77910 100644 --- a/dtmcli/dtmimp/trans_base.go +++ b/dtmcli/dtmimp/trans_base.go @@ -50,6 +50,7 @@ type TransOptions struct { PassthroughHeaders []string `json:"passthrough_headers,omitempty" gorm:"-"` // for inherit the specified gin context headers BranchHeaders map[string]string `json:"branch_headers,omitempty" gorm:"-"` // custom branch headers, dtm server => service api Concurrent bool `json:"concurrent" gorm:"-"` // for trans type: saga msg + RollbackReason string `json:"rollback_reason,omitempty" gorm:"-"` } // TransBase base for all trans diff --git a/dtmcli/tcc.go b/dtmcli/tcc.go index 1451427..6c2d191 100644 --- a/dtmcli/tcc.go +++ b/dtmcli/tcc.go @@ -41,6 +41,7 @@ func TccGlobalTransaction2(dtm string, gid string, custom func(*Tcc), tccFunc Tc defer dtmimp.DeferDo(&rerr, func() error { return dtmimp.TransCallDtm(&tcc.TransBase, tcc, "submit") }, func() error { + tcc.RollbackReason = rerr.Error() return dtmimp.TransCallDtm(&tcc.TransBase, tcc, "abort") }) _, rerr = tccFunc(tcc) diff --git a/dtmgrpc/dtmgpb/dtmgimp.proto b/dtmgrpc/dtmgpb/dtmgimp.proto index 0a76d53..8aedea2 100644 --- a/dtmgrpc/dtmgpb/dtmgimp.proto +++ b/dtmgrpc/dtmgpb/dtmgimp.proto @@ -21,6 +21,7 @@ message DtmTransOptions { repeated string PassthroughHeaders = 4; map BranchHeaders = 5; int64 RequestTimeout = 6; + string RollbackReason = 7; } // DtmRequest request sent to dtm server diff --git a/dtmgrpc/tcc.go b/dtmgrpc/tcc.go index 24a2f6a..d9d52a4 100644 --- a/dtmgrpc/tcc.go +++ b/dtmgrpc/tcc.go @@ -43,6 +43,7 @@ func TccGlobalTransaction2(dtm string, gid string, custom func(*TccGrpc), tccFun defer dtmimp.DeferDo(&rerr, func() error { return dtmgimp.DtmGrpcCall(&tcc.TransBase, "Submit") }, func() error { + tcc.RollbackReason = rerr.Error() return dtmgimp.DtmGrpcCall(&tcc.TransBase, "Abort") }) return tccFunc(tcc) diff --git a/dtmsvr/api.go b/dtmsvr/api.go index 831884a..b90e8ad 100644 --- a/dtmsvr/api.go +++ b/dtmsvr/api.go @@ -56,7 +56,7 @@ func svcAbort(t *TransGlobal) interface{} { if t.TransType != "xa" && t.TransType != "tcc" || dbt.Status != dtmcli.StatusPrepared && dbt.Status != dtmcli.StatusAborting { return fmt.Errorf("trans type: '%s' current status '%s', cannot abort. %w", dbt.TransType, dbt.Status, dtmcli.ErrFailure) } - dbt.changeStatus(dtmcli.StatusAborting) + dbt.changeStatus(dtmcli.StatusAborting, withRollbackReason(t.RollbackReason)) branches := GetStore().FindBranches(t.Gid) return dbt.Process(branches) } diff --git a/test/tcc_test.go b/test/tcc_test.go index f4f229d..8297afa 100644 --- a/test/tcc_test.go +++ b/test/tcc_test.go @@ -46,6 +46,7 @@ func TestTccRollback(t *testing.T) { cronTransOnce(t, gid) assert.Equal(t, StatusFailed, getTransStatus(gid)) assert.Equal(t, []string{StatusSucceed, StatusPrepared, StatusSucceed, StatusPrepared}, getBranchesStatus(gid)) + assert.Equal(t, "{\"error\":\"reason:. FAILURE\"}. FAILURE", getTrans(gid).RollbackReason) } func TestTccTimeout(t *testing.T) { From 09cdabc22c56a01856eef259a95cc97533c1ed92 Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Fri, 24 Jun 2022 11:17:24 +0800 Subject: [PATCH 25/32] embed serve compatible with windows --- main.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/main.go b/main.go index 2dd51c2..8d3d5a6 100644 --- a/main.go +++ b/main.go @@ -45,15 +45,18 @@ var admin embed.FS var target = "" -func getSub(f1 fs.FS, sub string) fs.FS { - f2, err := fs.Sub(f1, sub) - logger.FatalIfError(err) - return f2 +func getSub(f1 fs.FS, subs ...string) fs.FS { + var err error + for _, sub := range subs { + f1, err = fs.Sub(f1, sub) + logger.FatalIfError(err) + } + return f1 } func addAdmin(app *gin.Engine, conf *config.Type) { // for released dtm, serve admin from local files because the build output has been embed // for testing users, proxy admin to target because the build output has not been embed - dist := getSub(admin, "admin/dist") + dist := getSub(admin, "admin", "dist") index, err := dist.Open("index.html") if err == nil { cont, err := ioutil.ReadAll(index) From 90470eb8ace01e51ffe230c5bc53d0b727daeb68 Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Fri, 24 Jun 2022 11:37:18 +0800 Subject: [PATCH 26/32] pb generated --- dtmgrpc/dtmgpb/dtmgimp.pb.go | 133 ++++++++++++++++-------------- dtmgrpc/dtmgpb/dtmgimp_grpc.pb.go | 2 +- 2 files changed, 73 insertions(+), 62 deletions(-) diff --git a/dtmgrpc/dtmgpb/dtmgimp.pb.go b/dtmgrpc/dtmgpb/dtmgimp.pb.go index 671c1c6..7fb30b6 100644 --- a/dtmgrpc/dtmgpb/dtmgimp.pb.go +++ b/dtmgrpc/dtmgpb/dtmgimp.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.27.1 -// protoc v3.19.4 +// protoc-gen-go v1.28.0 +// protoc v3.17.3 // source: dtmgrpc/dtmgpb/dtmgimp.proto package dtmgpb @@ -32,6 +32,7 @@ type DtmTransOptions struct { PassthroughHeaders []string `protobuf:"bytes,4,rep,name=PassthroughHeaders,proto3" json:"PassthroughHeaders,omitempty"` BranchHeaders map[string]string `protobuf:"bytes,5,rep,name=BranchHeaders,proto3" json:"BranchHeaders,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` RequestTimeout int64 `protobuf:"varint,6,opt,name=RequestTimeout,proto3" json:"RequestTimeout,omitempty"` + RollbackReason string `protobuf:"bytes,7,opt,name=RollbackReason,proto3" json:"RollbackReason,omitempty"` } func (x *DtmTransOptions) Reset() { @@ -108,6 +109,13 @@ func (x *DtmTransOptions) GetRequestTimeout() int64 { return 0 } +func (x *DtmTransOptions) GetRollbackReason() string { + if x != nil { + return x.RollbackReason + } + return "" +} + // DtmRequest request sent to dtm server type DtmRequest struct { state protoimpl.MessageState @@ -345,7 +353,7 @@ var file_dtmgrpc_dtmgpb_dtmgimp_proto_rawDesc = []byte{ 0x2f, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xea, 0x02, 0x0a, 0x0f, 0x44, 0x74, 0x6d, 0x54, 0x72, 0x61, 0x6e, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x92, 0x03, 0x0a, 0x0f, 0x44, 0x74, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x57, 0x61, 0x69, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x57, 0x61, 0x69, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x69, 0x6d, 0x65, @@ -363,66 +371,69 @@ var file_dtmgrpc_dtmgpb_dtmgimp_proto_rawDesc = []byte{ 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x1a, - 0x40, 0x0a, 0x12, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x22, 0xfc, 0x01, 0x0a, 0x0a, 0x44, 0x74, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x10, 0x0a, 0x03, 0x47, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x47, - 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x54, 0x79, 0x70, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x3c, 0x0a, 0x0c, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, - 0x2e, 0x44, 0x74, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x0c, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x22, - 0x0a, 0x0c, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x64, 0x44, 0x61, - 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x42, 0x69, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, - 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0b, 0x42, 0x69, 0x6e, 0x50, 0x61, 0x79, 0x6c, - 0x6f, 0x61, 0x64, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x65, - 0x70, 0x61, 0x72, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x53, 0x74, - 0x65, 0x70, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x53, 0x74, 0x65, 0x70, 0x73, - 0x22, 0x1f, 0x0a, 0x0b, 0x44, 0x74, 0x6d, 0x47, 0x69, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x47, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x47, 0x69, - 0x64, 0x22, 0x82, 0x02, 0x0a, 0x10, 0x44, 0x74, 0x6d, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x47, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x47, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, - 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, - 0x49, 0x44, 0x12, 0x0e, 0x0a, 0x02, 0x4f, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, - 0x4f, 0x70, 0x12, 0x37, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x23, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x42, 0x72, - 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x44, 0x61, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x42, - 0x75, 0x73, 0x69, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x0b, 0x42, 0x75, 0x73, 0x69, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x1a, 0x37, 0x0a, - 0x09, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, 0xb1, 0x02, 0x0a, 0x03, 0x44, 0x74, 0x6d, 0x12, 0x38, - 0x0a, 0x06, 0x4e, 0x65, 0x77, 0x47, 0x69, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x1a, 0x14, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x47, 0x69, - 0x64, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x37, 0x0a, 0x06, 0x53, 0x75, 0x62, 0x6d, - 0x69, 0x74, 0x12, 0x13, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, - 0x00, 0x12, 0x38, 0x0a, 0x07, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x12, 0x13, 0x2e, 0x64, - 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x05, 0x41, - 0x62, 0x6f, 0x72, 0x74, 0x12, 0x13, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, + 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, + 0x26, 0x0a, 0x0e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x61, 0x73, 0x6f, + 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, + 0x6b, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x1a, 0x40, 0x0a, 0x12, 0x42, 0x72, 0x61, 0x6e, 0x63, + 0x68, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xfc, 0x01, 0x0a, 0x0a, 0x44, 0x74, + 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x47, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x47, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x3c, 0x0a, 0x0c, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, + 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0c, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, + 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x75, + 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x42, 0x69, + 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0c, 0x52, + 0x0b, 0x42, 0x69, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x12, 0x24, 0x0a, 0x0d, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x64, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, + 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x53, 0x74, 0x65, 0x70, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x53, 0x74, 0x65, 0x70, 0x73, 0x22, 0x1f, 0x0a, 0x0b, 0x44, 0x74, 0x6d, 0x47, + 0x69, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x47, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x47, 0x69, 0x64, 0x22, 0x82, 0x02, 0x0a, 0x10, 0x44, 0x74, + 0x6d, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, + 0x0a, 0x03, 0x47, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x47, 0x69, 0x64, + 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, + 0x0a, 0x08, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x49, 0x44, 0x12, 0x0e, 0x0a, 0x02, 0x4f, 0x70, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x4f, 0x70, 0x12, 0x37, 0x0a, 0x04, 0x44, 0x61, + 0x74, 0x61, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, + 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x44, + 0x61, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x42, 0x75, 0x73, 0x69, 0x50, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x42, 0x75, 0x73, 0x69, 0x50, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x1a, 0x37, 0x0a, 0x09, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, 0xb1, + 0x02, 0x0a, 0x03, 0x44, 0x74, 0x6d, 0x12, 0x38, 0x0a, 0x06, 0x4e, 0x65, 0x77, 0x47, 0x69, 0x64, + 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x14, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, + 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x47, 0x69, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, + 0x12, 0x37, 0x0a, 0x06, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x12, 0x13, 0x2e, 0x64, 0x74, 0x6d, + 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x38, 0x0a, 0x07, 0x50, 0x72, 0x65, + 0x70, 0x61, 0x72, 0x65, 0x12, 0x13, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x22, 0x00, 0x12, 0x45, 0x0a, 0x0e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x42, - 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x19, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, - 0x44, 0x74, 0x6d, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2f, - 0x64, 0x74, 0x6d, 0x67, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x79, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x05, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x12, 0x13, 0x2e, 0x64, + 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x45, 0x0a, 0x0e, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x19, 0x2e, + 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x42, 0x72, 0x61, 0x6e, 0x63, + 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x22, 0x00, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2f, 0x64, 0x74, 0x6d, 0x67, 0x70, 0x62, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/dtmgrpc/dtmgpb/dtmgimp_grpc.pb.go b/dtmgrpc/dtmgpb/dtmgimp_grpc.pb.go index db22f19..dea3605 100644 --- a/dtmgrpc/dtmgpb/dtmgimp_grpc.pb.go +++ b/dtmgrpc/dtmgpb/dtmgimp_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v3.19.4 +// - protoc v3.17.3 // source: dtmgrpc/dtmgpb/dtmgimp.proto package dtmgpb From 29388599e6db9bd29adfe87f305c5ef5108783a9 Mon Sep 17 00:00:00 2001 From: xyctruth <398041993@qq.com> Date: Fri, 24 Jun 2022 11:44:37 +0800 Subject: [PATCH 27/32] tcc grpc rollback_reson --- dtmgrpc/dtmgimp/utils.go | 1 + dtmsvr/trans_class.go | 14 ++++++++------ test/tcc_grpc_test.go | 1 + 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/dtmgrpc/dtmgimp/utils.go b/dtmgrpc/dtmgimp/utils.go index d10b321..532c5d5 100644 --- a/dtmgrpc/dtmgimp/utils.go +++ b/dtmgrpc/dtmgimp/utils.go @@ -37,6 +37,7 @@ func DtmGrpcCall(s *dtmimp.TransBase, operation string) error { PassthroughHeaders: s.PassthroughHeaders, BranchHeaders: s.BranchHeaders, RequestTimeout: s.RequestTimeout, + RollbackReason: s.RollbackReason, }, QueryPrepared: s.QueryPrepared, CustomedData: s.CustomData, diff --git a/dtmsvr/trans_class.go b/dtmsvr/trans_class.go index 1e239c0..35d0ee0 100644 --- a/dtmsvr/trans_class.go +++ b/dtmsvr/trans_class.go @@ -94,12 +94,13 @@ func TransFromDtmRequest(ctx context.Context, c *dtmgpb.DtmRequest) *TransGlobal o = c.TransOptions } r := TransGlobal{TransGlobalStore: storage.TransGlobalStore{ - Gid: c.Gid, - TransType: c.TransType, - QueryPrepared: c.QueryPrepared, - Protocol: "grpc", - BinPayloads: c.BinPayloads, - CustomData: c.CustomedData, + Gid: c.Gid, + TransType: c.TransType, + QueryPrepared: c.QueryPrepared, + Protocol: "grpc", + BinPayloads: c.BinPayloads, + CustomData: c.CustomedData, + RollbackReason: o.RollbackReason, TransOptions: dtmcli.TransOptions{ WaitResult: o.WaitResult, TimeoutToFail: o.TimeoutToFail, @@ -107,6 +108,7 @@ func TransFromDtmRequest(ctx context.Context, c *dtmgpb.DtmRequest) *TransGlobal PassthroughHeaders: o.PassthroughHeaders, BranchHeaders: o.BranchHeaders, RequestTimeout: o.RequestTimeout, + RollbackReason: o.RollbackReason, }, }} if c.Steps != "" { diff --git a/test/tcc_grpc_test.go b/test/tcc_grpc_test.go index 5a7c336..6e5e745 100644 --- a/test/tcc_grpc_test.go +++ b/test/tcc_grpc_test.go @@ -52,6 +52,7 @@ func TestTccGrpcRollback(t *testing.T) { cronTransOnce(t, gid) assert.Equal(t, StatusFailed, getTransStatus(gid)) assert.Equal(t, []string{StatusSucceed, StatusPrepared, StatusSucceed, StatusPrepared}, getBranchesStatus(gid)) + assert.Equal(t, "rpc error: code = Aborted desc = reason:", getTrans(gid).RollbackReason) } func TestTccGrpcNested(t *testing.T) { From 7e4beb8fca66946ffc272bcdb33ef2d150ff8231 Mon Sep 17 00:00:00 2001 From: xyctruth <398041993@qq.com> Date: Fri, 24 Jun 2022 11:50:50 +0800 Subject: [PATCH 28/32] fix err is nil --- dtmcli/dtmimp/utils.go | 1 + dtmcli/tcc.go | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/dtmcli/dtmimp/utils.go b/dtmcli/dtmimp/utils.go index 97ca42c..386d834 100644 --- a/dtmcli/dtmimp/utils.go +++ b/dtmcli/dtmimp/utils.go @@ -253,6 +253,7 @@ func RespAsErrorByJSONRPC(resp *resty.Response) error { // DeferDo a common defer do used in dtmcli/dtmgrpc func DeferDo(rerr *error, success func() error, fail func() error) { if x := recover(); x != nil { + *rerr = AsError(x) _ = fail() panic(x) } else if *rerr != nil { diff --git a/dtmcli/tcc.go b/dtmcli/tcc.go index 6c2d191..a0b6ff9 100644 --- a/dtmcli/tcc.go +++ b/dtmcli/tcc.go @@ -41,7 +41,9 @@ func TccGlobalTransaction2(dtm string, gid string, custom func(*Tcc), tccFunc Tc defer dtmimp.DeferDo(&rerr, func() error { return dtmimp.TransCallDtm(&tcc.TransBase, tcc, "submit") }, func() error { - tcc.RollbackReason = rerr.Error() + if rerr != nil { + tcc.RollbackReason = rerr.Error() + } return dtmimp.TransCallDtm(&tcc.TransBase, tcc, "abort") }) _, rerr = tccFunc(tcc) From bbb6c379f24626c3c7ad916ee50d301d994c6489 Mon Sep 17 00:00:00 2001 From: "zhanhua.cheng" Date: Fri, 24 Jun 2022 14:28:39 +0800 Subject: [PATCH 29/32] =?UTF-8?q?dtmServer=E6=B3=A8=E5=86=8C=E5=88=B0nacos?= =?UTF-8?q?=E6=8C=87=E5=AE=9A=E7=9A=84=E5=91=BD=E5=90=8D=E7=A9=BA=E9=97=B4?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conf.sample.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.sample.yml b/conf.sample.yml index a256a2a..f0f2cb6 100644 --- a/conf.sample.yml +++ b/conf.sample.yml @@ -46,7 +46,7 @@ # Driver: 'dtm-driver-http' # name of the driver to handle register/discover # RegistryType: 'nacos' # RegistryAddress: '127.0.0.1:8848,127.0.0.1:8848' -# RegistryOptions: '{"UserName":"nacos","Password":"nacos","NotLoadCacheAtStart":true}' +# RegistryOptions: '{"namespaceId":"a6843d66-cf5b-43ab-b7e7-461200dfe76c","UserName":"nacos","Password":"nacos","NotLoadCacheAtStart":true}' # Target: '{"ServiceName":"dtmService","Enable":true,"Healthy":true,"Weight":10}' # target and options # EndPoint: '127.0.0.1:36789' From cca6675b568002344a014f489201138a300ed084 Mon Sep 17 00:00:00 2001 From: nehcoab Date: Mon, 27 Jun 2022 22:40:55 +0800 Subject: [PATCH 30/32] docs: correct spelling subtraction -> sub-transaction --- README.md | 6 +++--- helper/README-en.md | 6 +++--- test/busi/quick_start.go | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 1c7e181..5ce855d 100644 --- a/README.md +++ b/README.md @@ -59,11 +59,11 @@ go run main.go req := &gin.H{"amount": 30} // micro-service payload // DtmServer is the address of DTM micro-service saga := dtmcli.NewSaga(DtmServer, shortuuid.New()). - // add a TransOut subtraction,forward operation with url: qsBusi+"/TransOut", reverse compensation operation with url: qsBusi+"/TransOutCom" + // add a TransOut sub-transaction,forward operation with url: qsBusi+"/TransOut", reverse compensation operation with url: qsBusi+"/TransOutCom" Add(qsBusi+"/TransOut", qsBusi+"/TransOutCom", req). - // add a TransIn subtraction, forward operation with url: qsBusi+"/TransIn", reverse compensation operation with url: qsBusi+"/TransInCom" + // add a TransIn sub-transaction, forward operation with url: qsBusi+"/TransIn", reverse compensation operation with url: qsBusi+"/TransInCom" Add(qsBusi+"/TransIn", qsBusi+"/TransInCom", req) - // submit the created saga transaction,dtm ensures all subtractions either complete or get revoked + // submit the created saga transaction,dtm ensures all sub-transactions either complete or get revoked err := saga.Submit() ``` diff --git a/helper/README-en.md b/helper/README-en.md index 740ae92..4caed84 100644 --- a/helper/README-en.md +++ b/helper/README-en.md @@ -57,11 +57,11 @@ go run main.go req := &gin.H{"amount": 30} // micro-service payload // DtmServer is the address of DTM micro-service saga := dtmcli.NewSaga(DtmServer, shortuuid.New()). - // add a TransOut subtraction,forward operation with url: qsBusi+"/TransOut", reverse compensation operation with url: qsBusi+"/TransOutCom" + // add a TransOut sub-transaction,forward operation with url: qsBusi+"/TransOut", reverse compensation operation with url: qsBusi+"/TransOutCom" Add(qsBusi+"/TransOut", qsBusi+"/TransOutCom", req). - // add a TransIn subtraction, forward operation with url: qsBusi+"/TransIn", reverse compensation operation with url: qsBusi+"/TransInCom" + // add a TransIn sub-transaction, forward operation with url: qsBusi+"/TransIn", reverse compensation operation with url: qsBusi+"/TransInCom" Add(qsBusi+"/TransIn", qsBusi+"/TransInCom", req) - // submit the created saga transaction,dtm ensures all subtractions either complete or get revoked + // submit the created saga transaction,dtm ensures all sub-transactions either complete or get revoked err := saga.Submit() ``` diff --git a/test/busi/quick_start.go b/test/busi/quick_start.go index 2f33d72..729be30 100644 --- a/test/busi/quick_start.go +++ b/test/busi/quick_start.go @@ -61,11 +61,11 @@ func QsFireRequest() string { req := &gin.H{"amount": 30} // load of micro-service // DtmServer is the url of dtm saga := dtmcli.NewSaga(dtmServer, shortuuid.New()). - // add a TransOut subtraction,forward operation with url: qsBusi+"/TransOut", reverse compensation operation with url: qsBusi+"/TransOutCompensate" + // add a TransOut sub-transaction,forward operation with url: qsBusi+"/TransOut", reverse compensation operation with url: qsBusi+"/TransOutCompensate" Add(qsBusi+"/TransOut", qsBusi+"/TransOutCompensate", req). - // add a TransIn subtraction, forward operation with url: qsBusi+"/TransIn", reverse compensation operation with url: qsBusi+"/TransInCompensate" + // add a TransIn sub-transaction, forward operation with url: qsBusi+"/TransIn", reverse compensation operation with url: qsBusi+"/TransInCompensate" Add(qsBusi+"/TransIn", qsBusi+"/TransInCompensate", req) - // submit the created saga transaction,dtm ensures all subtractions either complete or get revoked + // submit the created saga transaction,dtm ensures all sub-transactions either complete or get revoked err := saga.Submit() if err != nil { From 6356090bd01ddf61a15cf3ad0b2ee2ffa756444b Mon Sep 17 00:00:00 2001 From: xyctruth <398041993@qq.com> Date: Tue, 28 Jun 2022 12:08:03 +0800 Subject: [PATCH 31/32] saga submit sync get branch error --- dtmsvr/trans_process.go | 4 ++++ test/saga_grpc_test.go | 2 +- test/saga_options_test.go | 2 ++ test/saga_test.go | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/dtmsvr/trans_process.go b/dtmsvr/trans_process.go index 7a8fe46..793d341 100644 --- a/dtmsvr/trans_process.go +++ b/dtmsvr/trans_process.go @@ -45,7 +45,11 @@ func (t *TransGlobal) process(branches []TransBranch) error { if err != nil { return err } + if submitting && t.Status != dtmcli.StatusSucceed { + if t.RollbackReason != "" { + return fmt.Errorf(t.RollbackReason) + } return fmt.Errorf("wait result not return success: %w", dtmcli.ErrFailure) } return nil diff --git a/test/saga_grpc_test.go b/test/saga_grpc_test.go index 9a98d06..2b85826 100644 --- a/test/saga_grpc_test.go +++ b/test/saga_grpc_test.go @@ -36,7 +36,7 @@ func TestSagaGrpcRollback(t *testing.T) { cronTransOnce(t, gid) assert.Equal(t, StatusFailed, getTransStatus(saga.Gid)) assert.Equal(t, []string{StatusSucceed, StatusSucceed, StatusSucceed, StatusFailed}, getBranchesStatus(saga.Gid)) - assert.Equal(t, "url:localhost:58081/busi.Busi/TransIn return failed: reason:Insufficient balance. FAILURE", getTrans(saga.Gid).RollbackReason) + assert.Contains(t, getTrans(saga.Gid).RollbackReason, "Insufficient balance") } func TestSagaGrpcCurrent(t *testing.T) { diff --git a/test/saga_options_test.go b/test/saga_options_test.go index 557ab1d..c113e74 100644 --- a/test/saga_options_test.go +++ b/test/saga_options_test.go @@ -98,9 +98,11 @@ func TestSagaOptionsCommittedOngoingWait(t *testing.T) { func TestSagaOptionsRollbackWait(t *testing.T) { saga := genSaga(dtmimp.GetFuncName(), false, true) + busi.MainSwitch.FailureReason.SetOnce("Insufficient balance") saga.WaitResult = true err := saga.Submit() assert.Error(t, err) + assert.Contains(t, err.Error(), "Insufficient balance") waitTransProcessed(saga.Gid) assert.Equal(t, StatusFailed, getTransStatus(saga.Gid)) assert.Equal(t, []string{StatusSucceed, StatusSucceed, StatusSucceed, StatusFailed}, getBranchesStatus(saga.Gid)) diff --git a/test/saga_test.go b/test/saga_test.go index f536a4c..c1ed49a 100644 --- a/test/saga_test.go +++ b/test/saga_test.go @@ -33,7 +33,7 @@ func TestSagaRollback(t *testing.T) { waitTransProcessed(saga.Gid) assert.Equal(t, []string{StatusSucceed, StatusSucceed, StatusSucceed, StatusFailed}, getBranchesStatus(saga.Gid)) assert.Equal(t, StatusFailed, getTransStatus(saga.Gid)) - assert.Equal(t, "url:http://localhost:8081/api/busi/TransIn return failed: {\"error\":\"reason:Insufficient balance. FAILURE\"}. FAILURE", getTrans(saga.Gid).RollbackReason) + assert.Contains(t, getTrans(saga.Gid).RollbackReason, "Insufficient balance") } func TestSagaOngoingSucceed(t *testing.T) { From e8df3b1f9888cb396506ac04b76b9c15c275bb78 Mon Sep 17 00:00:00 2001 From: xyctruth <398041993@qq.com> Date: Tue, 28 Jun 2022 13:55:49 +0800 Subject: [PATCH 32/32] saga submit sync get branch error --- dtmgrpc/type.go | 7 ++++--- dtmsvr/trans_process.go | 2 +- test/saga_grpc_test.go | 14 ++++++++++++++ test/saga_options_test.go | 1 + 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/dtmgrpc/type.go b/dtmgrpc/type.go index 14244e3..713a368 100644 --- a/dtmgrpc/type.go +++ b/dtmgrpc/type.go @@ -8,6 +8,7 @@ package dtmgrpc import ( context "context" + "errors" "fmt" "github.com/dtm-labs/dtm/dtmcli" @@ -23,9 +24,9 @@ import ( // DtmError2GrpcError translate dtm error to grpc error func DtmError2GrpcError(res interface{}) error { e, ok := res.(error) - if ok && e == dtmimp.ErrFailure { - return status.New(codes.Aborted, dtmcli.ResultFailure).Err() - } else if ok && e == dtmimp.ErrOngoing { + if ok && errors.Is(e, dtmimp.ErrFailure) { + return status.New(codes.Aborted, e.Error()).Err() + } else if ok && errors.Is(e, dtmimp.ErrOngoing) { return status.New(codes.FailedPrecondition, dtmcli.ResultOngoing).Err() } return e diff --git a/dtmsvr/trans_process.go b/dtmsvr/trans_process.go index 793d341..c2b4f2a 100644 --- a/dtmsvr/trans_process.go +++ b/dtmsvr/trans_process.go @@ -48,7 +48,7 @@ func (t *TransGlobal) process(branches []TransBranch) error { if submitting && t.Status != dtmcli.StatusSucceed { if t.RollbackReason != "" { - return fmt.Errorf(t.RollbackReason) + return fmt.Errorf("%s. %w", t.RollbackReason, dtmcli.ErrFailure) } return fmt.Errorf("wait result not return success: %w", dtmcli.ErrFailure) } diff --git a/test/saga_grpc_test.go b/test/saga_grpc_test.go index 2b85826..2128bbb 100644 --- a/test/saga_grpc_test.go +++ b/test/saga_grpc_test.go @@ -123,6 +123,20 @@ func TestSagaGrpcWithGlobalTransRequestTimeout(t *testing.T) { waitTransProcessed(gid) } +func TestSagaGrpcOptionsRollbackWait(t *testing.T) { + gid := dtmimp.GetFuncName() + saga := genSagaGrpc(gid, false, true) + busi.MainSwitch.FailureReason.SetOnce("Insufficient balance") + saga.WaitResult = true + err := saga.Submit() + assert.Error(t, err) + assert.Contains(t, err.Error(), "Insufficient balance") + waitTransProcessed(saga.Gid) + assert.Equal(t, StatusFailed, getTransStatus(saga.Gid)) + assert.Equal(t, []string{StatusSucceed, StatusSucceed, StatusSucceed, StatusFailed}, getBranchesStatus(saga.Gid)) + assert.Contains(t, getTrans(saga.Gid).RollbackReason, "Insufficient balance") +} + func TestSagaGrpcCronPassthroughHeadersYes(t *testing.T) { gidYes := dtmimp.GetFuncName() sagaYes := dtmgrpc.NewSagaGrpc(dtmutil.DefaultGrpcServer, gidYes) diff --git a/test/saga_options_test.go b/test/saga_options_test.go index c113e74..cd43ece 100644 --- a/test/saga_options_test.go +++ b/test/saga_options_test.go @@ -106,6 +106,7 @@ func TestSagaOptionsRollbackWait(t *testing.T) { waitTransProcessed(saga.Gid) assert.Equal(t, StatusFailed, getTransStatus(saga.Gid)) assert.Equal(t, []string{StatusSucceed, StatusSucceed, StatusSucceed, StatusFailed}, getBranchesStatus(saga.Gid)) + assert.Contains(t, getTrans(saga.Gid).RollbackReason, "Insufficient balance") } func TestSagaPassthroughHeadersYes(t *testing.T) {