From 1e835778d6a5d68431852f58b02ac3443220fb55 Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Wed, 29 Dec 2021 15:40:14 +0800 Subject: [PATCH 01/22] default no config needed --- .gitignore | 6 +- .golangci.yml | 6 +- .vscode/launch.json.sample | 33 -- .vscode/settings.json.sample | 3 - README-cn.md | 37 +- app/main.go | 82 ----- bench/main.go | 14 +- bench/svr/http.go | 26 +- common/config.go | 128 ------- common/types_test.go | 67 ---- conf.sample.yml | 7 - dtmcli/dtmimp/utils.go | 2 +- dtmgrpc/dtmgimp/types.go | 7 +- dtmsvr/api_http.go | 20 +- dtmsvr/config/config.go | 83 +++++ {common => dtmsvr/config}/config_test.go | 27 +- {common => dtmsvr/config}/config_utils.go | 34 +- dtmsvr/cron.go | 2 +- dtmsvr/storage/boltdb/boltdb.go | 13 +- dtmsvr/storage/redis/redis.go | 39 ++- dtmsvr/storage/registry/registry.go | 6 +- dtmsvr/storage/sql/sql.go | 32 +- dtmsvr/storage/trans.go | 6 +- dtmsvr/svr.go | 18 +- dtmsvr/svr_imports.go | 7 - dtmsvr/trans_process.go | 4 +- dtmsvr/trans_status.go | 8 +- dtmsvr/utils.go | 4 +- dtmsvr/utils_test.go | 4 +- dtmutil/consts.go | 14 + {common => dtmutil}/db.go | 16 +- {common => dtmutil}/utils.go | 2 +- {common => dtmutil}/utils_test.go | 4 +- examples/base.go | 14 - examples/busi.pb.go | 330 ------------------ examples/data.go | 55 --- examples/grpc_msg.go | 25 -- examples/grpc_saga.go | 36 -- examples/grpc_saga_barrier.go | 70 ---- examples/grpc_tcc.go | 32 -- examples/grpc_xa.go | 37 -- examples/http_gorm_xa.go | 29 -- examples/http_msg.go | 28 -- examples/http_saga.go | 56 --- examples/http_saga_barrier.go | 79 ----- examples/http_saga_gorm_barrier.go | 43 --- examples/http_tcc.go | 51 --- examples/http_tcc_barrier.go | 111 ------ examples/http_xa.go | 42 --- go.mod | 1 + go.sum | 1 + helper/test-cover.sh | 2 +- main.go | 72 ++++ qs/main.go | 19 + sqls/{examples.mysql.sql => busi.mysql.sql} | 0 ...xamples.postgres.sql => busi.postgres.sql} | 0 test/api_test.go | 14 +- test/base_test.go | 12 +- test/busi/barrier.go | 124 +++++++ {examples => test/busi}/base_grpc.go | 45 +-- {examples => test/busi}/base_http.go | 124 +++---- {examples => test/busi}/base_types.go | 84 +++-- test/busi/busi.go | 85 +++++ test/busi/busi.pb.go | 325 +++++++++++++++++ {examples => test/busi}/busi.proto | 4 +- {examples => test/busi}/busi_grpc.pb.go | 74 ++-- {examples => test/busi}/quick_start.go | 38 +- test/busi/startup.go | 23 ++ test/busi/utils.go | 61 ++++ test/common_test.go | 38 ++ test/dtmsvr_test.go | 16 +- test/examples_test.go | 20 -- test/main_test.go | 47 ++- test/msg_grpc_test.go | 21 +- test/msg_options_test.go | 4 +- test/msg_test.go | 21 +- test/saga_barrier_test.go | 4 +- test/saga_compatible_test.go | 7 +- test/saga_concurrent_test.go | 6 +- test/saga_grpc_barrier_test.go | 11 +- test/saga_grpc_test.go | 23 +- test/saga_options_test.go | 10 +- test/saga_test.go | 27 +- test/store_test.go | 14 +- test/tcc_barrier_test.go | 93 ++--- test/tcc_cover_test.go | 4 +- test/tcc_grpc_cover_test.go | 13 +- test/tcc_grpc_test.go | 31 +- test/tcc_test.go | 21 +- test/types.go | 12 +- test/xa_cover_test.go | 12 +- test/xa_grpc_test.go | 22 +- test/xa_test.go | 32 +- 93 files changed, 1446 insertions(+), 1970 deletions(-) delete mode 100644 .vscode/launch.json.sample delete mode 100644 .vscode/settings.json.sample delete mode 100644 app/main.go delete mode 100644 common/config.go delete mode 100644 common/types_test.go create mode 100644 dtmsvr/config/config.go rename {common => dtmsvr/config}/config_test.go (68%) rename {common => dtmsvr/config}/config_utils.go (64%) delete mode 100644 dtmsvr/svr_imports.go create mode 100644 dtmutil/consts.go rename {common => dtmutil}/db.go (90%) rename {common => dtmutil}/utils.go (99%) rename {common => dtmutil}/utils_test.go (96%) delete mode 100644 examples/base.go delete mode 100644 examples/busi.pb.go delete mode 100644 examples/data.go delete mode 100644 examples/grpc_msg.go delete mode 100644 examples/grpc_saga.go delete mode 100644 examples/grpc_saga_barrier.go delete mode 100644 examples/grpc_tcc.go delete mode 100644 examples/grpc_xa.go delete mode 100644 examples/http_gorm_xa.go delete mode 100644 examples/http_msg.go delete mode 100644 examples/http_saga.go delete mode 100644 examples/http_saga_barrier.go delete mode 100644 examples/http_saga_gorm_barrier.go delete mode 100644 examples/http_tcc.go delete mode 100644 examples/http_tcc_barrier.go delete mode 100644 examples/http_xa.go create mode 100644 main.go create mode 100644 qs/main.go rename sqls/{examples.mysql.sql => busi.mysql.sql} (100%) rename sqls/{examples.postgres.sql => busi.postgres.sql} (100%) create mode 100644 test/busi/barrier.go rename {examples => test/busi}/base_grpc.go (71%) rename {examples => test/busi}/base_http.go (53%) rename {examples => test/busi}/base_types.go (52%) create mode 100644 test/busi/busi.go create mode 100644 test/busi/busi.pb.go rename {examples => test/busi}/busi.proto (96%) rename {examples => test/busi}/busi_grpc.pb.go (91%) rename {examples => test/busi}/quick_start.go (58%) create mode 100644 test/busi/startup.go create mode 100644 test/busi/utils.go create mode 100644 test/common_test.go delete mode 100644 test/examples_test.go diff --git a/.gitignore b/.gitignore index 771c69c..e89d163 100644 --- a/.gitignore +++ b/.gitignore @@ -5,11 +5,13 @@ conf.yml main dist .idea/** -.vscode/*.json +.vscode default.etcd */**/*.bolt # Output file of unit test coverage coverage.* profile.* -test.sh \ No newline at end of file +test.sh +dtm +dtm.* \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml index 78a6813..5d5bf7b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,8 +1,8 @@ run: deadline: 5m - skip-dirs: - - test - - examples + # skip-dirs: + # - test + # - examples linter-settings: goconst: diff --git a/.vscode/launch.json.sample b/.vscode/launch.json.sample deleted file mode 100644 index 7cf371c..0000000 --- a/.vscode/launch.json.sample +++ /dev/null @@ -1,33 +0,0 @@ -{ - // 使用 IntelliSense 了解相关属性。 - // 悬停以查看现有属性的描述。 - // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Launch", - "type": "go", - "request": "launch", - "mode": "debug", - "program": "${workspaceFolder}/app/main.go", - "cwd": "${workspaceFolder}", - "env": { - // "GIN_MODE": "release" - }, - "args": ["grpc_saga"] - }, - { - "name": "Test", - "type": "go", - "request": "launch", - "mode": "test", - "port": 2345, - "host": "127.0.0.1", - "program": "${file}", - "env": { - // "GIN_MODE": "release" - }, - "args": [] - } - ] -} \ No newline at end of file diff --git a/.vscode/settings.json.sample b/.vscode/settings.json.sample deleted file mode 100644 index 079a897..0000000 --- a/.vscode/settings.json.sample +++ /dev/null @@ -1,3 +0,0 @@ -{ - "go.formatTool": "gofmt" -} \ No newline at end of file diff --git a/README-cn.md b/README-cn.md index 27be69d..122e7df 100644 --- a/README-cn.md +++ b/README-cn.md @@ -74,26 +74,21 @@ DTM是一款golang开发的分布式事务管理器,解决了跨数据库、 具体微服务接入使用,参见[微服务支持](https://dtm.pub/protocol/intro.html) ## 快速开始 -### 获取代码 +如果您不是Go语言,可以跳转[各语言客户端及示例](https://dtm.pub/summary/code.html#go),里面有相关的快速开始示例 -`git clone https://github.com/dtm-labs/dtm && cd dtm` +### 运行dtm -### dtm依赖于mysql - -安装[docker 20.04+](https://docs.docker.com/get-docker/)之后 - -`docker-compose -f helper/compose.mysql.yml up` - -> 您也可以配置使用现有的mysql,需要高级权限,允许dtm创建数据库 -> -> `cp conf.sample.yml conf.yml # 修改conf.yml` +``` bash +git clone https://github.com/dtm-labs/dtm && cd dtm +go run main.go +``` -### 启动并运行saga示例 -`go run app/main.go qs` +### 启动并运行一个saga示例 +`go run qs/main.go` -## 开始使用 +## 接入详解 -### 使用 +### 接入代码 ``` GO // 具体业务微服务地址 const qsBusi = "http://localhost:8081/api/busi_saga" @@ -117,8 +112,8 @@ DTM是一款golang开发的分布式事务管理器,解决了跨数据库、 -### 完整示例 -参考[examples/quick_start.go](./examples/quick_start.go) +### 更多示例 +参考[dtm-labs/dtm-examples](https://github.com/dtm-labs/dtm-examples) ## 公众号 您可以关注公众号:分布式事务,及时跟踪dtm的最新内容 @@ -129,11 +124,3 @@ DTM是一款golang开发的分布式事务管理器,解决了跨数据库、 欢迎使用[dtm](https://github.com/dtm-labs/dtm),或者通过dtm学习实践分布式事务相关知识,欢迎star支持我们 -## 谁在使用 -
- 腾讯 - 常青藤爸爸 - 镜小二 - 极欧科技 - 金数智联 -
diff --git a/app/main.go b/app/main.go deleted file mode 100644 index f6c2d26..0000000 --- a/app/main.go +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2021 yedf. All rights reserved. - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - */ - -package main - -import ( - "fmt" - "os" - "strings" - - _ "go.uber.org/automaxprocs" - - "github.com/dtm-labs/dtm/common" - "github.com/dtm-labs/dtm/dtmcli" - "github.com/dtm-labs/dtm/dtmcli/logger" - "github.com/dtm-labs/dtm/dtmsvr" - "github.com/dtm-labs/dtm/dtmsvr/storage/registry" - "github.com/dtm-labs/dtm/examples" -) - -var Version, Commit, Date string - -var usage = `dtm is a lightweight distributed transaction manager. - -usage: - dtm [command] - -Available commands: - version print dtm version - dtmsvr run dtm as a server - dev create all needed table and run dtm as a server - bench start bench server - - quick_start run quick start example (dtm will create needed table) - qs same as quick_start -` - -func main() { - if len(os.Args) == 1 { - fmt.Println(usage) - for name := range examples.Samples { - fmt.Printf("%4s%-18srun a sample includes %s\n", "", name, strings.ReplaceAll(name, "_", " ")) - } - return - } - if os.Args[1] == "version" { - fmt.Printf("version: %s commit: %s built at: %s\n", Version, Commit, Date) - return - } - logger.Infof("starting dtm....") - common.MustLoadConfig() - if common.Config.ExamplesDB.Driver != "" { - dtmcli.SetCurrentDBType(common.Config.ExamplesDB.Driver) - } - if os.Args[1] != "dtmsvr" { // 实际线上运行,只启动dtmsvr,不准备table相关的数据 - registry.WaitStoreUp() - dtmsvr.PopulateDB(true) - examples.PopulateDB(true) - } - dtmsvr.StartSvr() // 启动dtmsvr的api服务 - go dtmsvr.CronExpiredTrans(-1) // 启动dtmsvr的定时过期查询 - - switch os.Args[1] { - case "quick_start", "qs": - // quick_start 比较独立,单独作为一个例子运行,方便新人上手 - examples.QsStartSvr() - examples.QsFireRequest() - case "dev", "dtmsvr": // do nothing, not fallthrough - default: - // 下面是各类的例子 - examples.GrpcStartup() - examples.BaseAppStartup() - - sample := examples.Samples[os.Args[1]] - logger.FatalfIf(sample == nil, "no sample name for %s", os.Args[1]) - sample.Action() - } - select {} -} diff --git a/bench/main.go b/bench/main.go index ec2a78e..310af87 100644 --- a/bench/main.go +++ b/bench/main.go @@ -5,12 +5,12 @@ import ( "os" "github.com/dtm-labs/dtm/bench/svr" - "github.com/dtm-labs/dtm/common" "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/logger" "github.com/dtm-labs/dtm/dtmsvr" + "github.com/dtm-labs/dtm/dtmsvr/config" "github.com/dtm-labs/dtm/dtmsvr/storage/registry" - "github.com/dtm-labs/dtm/examples" + "github.com/dtm-labs/dtm/test/busi" ) var usage = `bench is a bench test server for dtmf @@ -25,23 +25,23 @@ func hintAndExit() { os.Exit(0) } -var conf = &common.Config +var conf = &config.Config func main() { if len(os.Args) <= 1 { hintAndExit() } logger.Infof("starting bench server") - common.MustLoadConfig() + config.MustLoadConfig("") logger.InitLog(conf.LogLevel) - if conf.ExamplesDB.Driver != "" { - dtmcli.SetCurrentDBType(conf.ExamplesDB.Driver) + if busi.BusiConf.Driver != "" { + dtmcli.SetCurrentDBType(busi.BusiConf.Driver) svr.PrepareBenchDB() } registry.WaitStoreUp() dtmsvr.PopulateDB(false) if os.Args[1] == "db" { - examples.PopulateDB(false) + busi.PopulateDB(false) } else if os.Args[1] == "redis" || os.Args[1] == "boltdb" { } else { diff --git a/bench/svr/http.go b/bench/svr/http.go index 0ff80a8..d1c8978 100644 --- a/bench/svr/http.go +++ b/bench/svr/http.go @@ -14,11 +14,12 @@ import ( "sync/atomic" "time" - "github.com/dtm-labs/dtm/common" "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" + "github.com/dtm-labs/dtm/dtmutil" + "github.com/dtm-labs/dtm/test/busi" "github.com/gin-gonic/gin" "github.com/lithammer/shortuuid" ) @@ -33,7 +34,7 @@ var benchPort = dtmimp.If(os.Getenv("BENCH_PORT") == "", "8083", os.Getenv("BENC var benchBusi = fmt.Sprintf("http://localhost:%s%s", benchPort, benchAPI) func sdbGet() *sql.DB { - db, err := dtmimp.PooledDB(common.Config.ExamplesDB) + db, err := dtmimp.PooledDB(busi.BusiConf) logger.FatalIfError(err) return db } @@ -91,7 +92,7 @@ func PrepareBenchDB() { // StartSvr 1 func StartSvr() { - app := common.GetGinApp() + app := dtmutil.GetGinApp() benchAddRoute(app) logger.Debugf("bench listening at %d", benchPort) go app.Run(fmt.Sprintf(":%s", benchPort)) @@ -127,20 +128,19 @@ func qsAdjustBalance(uid int, amount int, c *gin.Context) (interface{}, error) { } func benchAddRoute(app *gin.Engine) { - dtmHttpServer := fmt.Sprintf("http://localhost:%d/api/dtmsvr", common.Config.HttpPort) - app.POST(benchAPI+"/TransIn", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + app.POST(benchAPI+"/TransIn", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { return qsAdjustBalance(dtmimp.MustAtoi(c.Query("uid")), 1, c) })) - app.POST(benchAPI+"/TransInCompensate", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + app.POST(benchAPI+"/TransInCompensate", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { return qsAdjustBalance(dtmimp.MustAtoi(c.Query("uid")), -1, c) })) - app.POST(benchAPI+"/TransOut", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + app.POST(benchAPI+"/TransOut", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { return qsAdjustBalance(dtmimp.MustAtoi(c.Query("uid")), -1, c) })) - app.POST(benchAPI+"/TransOutCompensate", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + app.POST(benchAPI+"/TransOutCompensate", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { return qsAdjustBalance(dtmimp.MustAtoi(c.Query("uid")), 30, c) })) - app.Any(benchAPI+"/reloadData", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + app.Any(benchAPI+"/reloadData", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { reloadData() mode = c.Query("m") s := c.Query("sqls") @@ -149,7 +149,7 @@ func benchAddRoute(app *gin.Engine) { } return nil, nil })) - app.Any(benchAPI+"/bench", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + app.Any(benchAPI+"/bench", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { uid := (atomic.AddInt32(&uidCounter, 1)-1)%total + 1 suid := fmt.Sprintf("%d", uid) suid2 := fmt.Sprintf("%d", total+1-uid) @@ -158,7 +158,7 @@ func benchAddRoute(app *gin.Engine) { params2 := fmt.Sprintf("?uid=%s", suid2) logger.Debugf("mode: %s contains dtm: %t", mode, strings.Contains(mode, "dtm")) if strings.Contains(mode, "dtm") { - saga := dtmcli.NewSaga(dtmHttpServer, fmt.Sprintf("bench-%d", uid)). + saga := dtmcli.NewSaga(dtmutil.DefaultHttpServer, fmt.Sprintf("bench-%d", uid)). Add(benchBusi+"/TransOut"+params, benchBusi+"/TransOutCompensate"+params, req). Add(benchBusi+"/TransIn"+params2, benchBusi+"/TransInCompensate"+params2, req) saga.WaitResult = true @@ -172,10 +172,10 @@ func benchAddRoute(app *gin.Engine) { } return nil, nil })) - app.Any(benchAPI+"/benchEmptyUrl", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + app.Any(benchAPI+"/benchEmptyUrl", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { gid := shortuuid.New() req := gin.H{} - saga := dtmcli.NewSaga(dtmHttpServer, gid). + saga := dtmcli.NewSaga(dtmutil.DefaultHttpServer, gid). Add("", "", req). Add("", "", req) saga.WaitResult = true diff --git a/common/config.go b/common/config.go deleted file mode 100644 index 1c5af74..0000000 --- a/common/config.go +++ /dev/null @@ -1,128 +0,0 @@ -package common - -import ( - "encoding/json" - "errors" - "io/ioutil" - "path/filepath" - - "github.com/dtm-labs/dtm/dtmcli" - "github.com/dtm-labs/dtm/dtmcli/logger" - "gopkg.in/yaml.v2" -) - -const ( - DtmMetricsPort = 8889 - Mysql = "mysql" - Redis = "redis" - BoltDb = "boltdb" -) - -// MicroService config type for micro service -type MicroService struct { - Driver string `yaml:"Driver" default:"default"` - Target string `yaml:"Target"` - EndPoint string `yaml:"EndPoint"` -} - -type Store struct { - Driver string `yaml:"Driver" default:"boltdb"` - Host string `yaml:"Host"` - Port int64 `yaml:"Port"` - User string `yaml:"User"` - Password string `yaml:"Password"` - MaxOpenConns int64 `yaml:"MaxOpenConns" default:"500"` - MaxIdleConns int64 `yaml:"MaxIdleConns" default:"500"` - ConnMaxLifeTime int64 `yaml:"ConnMaxLifeTime" default:"5"` - DataExpire int64 `yaml:"DataExpire" default:"604800"` // Trans data will expire in 7 days. only for redis/boltdb. - RedisPrefix string `yaml:"RedisPrefix" default:"{a}"` // Redis storage prefix. store data to only one slot in cluster -} - -func (s *Store) IsDB() bool { - return s.Driver == dtmcli.DBTypeMysql || s.Driver == dtmcli.DBTypePostgres -} - -func (s *Store) GetDBConf() dtmcli.DBConf { - return dtmcli.DBConf{ - Driver: s.Driver, - Host: s.Host, - Port: s.Port, - User: s.User, - Password: s.Password, - } -} - -type configType struct { - Store Store `yaml:"Store"` - TransCronInterval int64 `yaml:"TransCronInterval" default:"3"` - TimeoutToFail int64 `yaml:"TimeoutToFail" default:"35"` - RetryInterval int64 `yaml:"RetryInterval" default:"10"` - HttpPort int64 `yaml:"HttpPort" default:"36789"` - GrpcPort int64 `yaml:"GrpcPort" default:"36790"` - MicroService MicroService `yaml:"MicroService"` - UpdateBranchSync int64 `yaml:"UpdateBranchSync"` - LogLevel string `yaml:"LogLevel" default:"info"` - ExamplesDB dtmcli.DBConf `yaml:"ExamplesDB"` -} - -// Config 配置 -var Config = configType{} - -func MustLoadConfig() { - loadFromEnv("", &Config) - cont := []byte{} - for d := MustGetwd(); d != "" && d != "/"; d = filepath.Dir(d) { - cont1, err := ioutil.ReadFile(d + "/conf.yml") - if err != nil { - cont1, err = ioutil.ReadFile(d + "/conf.sample.yml") - } - if cont1 != nil { - cont = cont1 - break - } - } - if len(cont) != 0 { - err := yaml.UnmarshalStrict(cont, &Config) - logger.FatalIfError(err) - } - scont, err := json.MarshalIndent(&Config, "", " ") - logger.FatalIfError(err) - logger.Debugf("config is: \n%s", scont) - err = checkConfig() - logger.FatalfIf(err != nil, `config error: '%v'. - check you env, and conf.yml/conf.sample.yml in current and parent path: %s. - please visit http://d.dtm.pub to see the config document. - loaded config is: - %v`, err, MustGetwd(), Config) -} - -func checkConfig() error { - if Config.RetryInterval < 10 { - return errors.New("RetryInterval should not be less than 10") - } - if Config.TimeoutToFail < Config.RetryInterval { - return errors.New("TimeoutToFail should not be less than RetryInterval") - } - switch Config.Store.Driver { - case BoltDb: - return nil - case Mysql: - if Config.Store.Host == "" { - return errors.New("Db host not valid ") - } - if Config.Store.Port == 0 { - return errors.New("Db port not valid ") - } - if Config.Store.User == "" { - return errors.New("Db user not valid ") - } - case Redis: - if Config.Store.Host == "" { - return errors.New("Redis host not valid ") - } - if Config.Store.Port == 0 { - return errors.New("Redis port not valid ") - } - } - return nil -} diff --git a/common/types_test.go b/common/types_test.go deleted file mode 100644 index 72203d0..0000000 --- a/common/types_test.go +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2021 yedf. All rights reserved. - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - */ - -package common - -import ( - "testing" - - "github.com/dtm-labs/dtm/dtmcli/dtmimp" - "github.com/stretchr/testify/assert" -) - -func TestGeneralDB(t *testing.T) { - MustLoadConfig() - if Config.Store.IsDB() { - testSql(t) - testDbAlone(t) - } -} - -func testSql(t *testing.T) { - db := DbGet(Config.Store.GetDBConf()) - err := func() (rerr error) { - defer dtmimp.P2E(&rerr) - db.Must().Exec("select a") - return nil - }() - assert.NotEqual(t, nil, err) -} - -func testDbAlone(t *testing.T) { - db, err := dtmimp.StandaloneDB(Config.Store.GetDBConf()) - assert.Nil(t, err) - _, err = dtmimp.DBExec(db, "select 1") - assert.Equal(t, nil, err) - _, err = dtmimp.DBExec(db, "") - assert.Equal(t, nil, err) - db.Close() - _, err = dtmimp.DBExec(db, "select 1") - assert.NotEqual(t, nil, err) -} - -func TestConfig(t *testing.T) { - testConfigStringField(&Config.Store.Driver, "", t) - testConfigStringField(&Config.Store.User, "", t) - testConfigIntField(&Config.RetryInterval, 9, t) - testConfigIntField(&Config.TimeoutToFail, 9, t) -} - -func testConfigStringField(fd *string, val string, t *testing.T) { - old := *fd - *fd = val - str := checkConfig() - assert.NotEqual(t, "", str) - *fd = old -} - -func testConfigIntField(fd *int64, val int64, t *testing.T) { - old := *fd - *fd = val - str := checkConfig() - assert.NotEqual(t, "", str) - *fd = old -} diff --git a/conf.sample.yml b/conf.sample.yml index cc7f447..e4f6348 100644 --- a/conf.sample.yml +++ b/conf.sample.yml @@ -41,10 +41,3 @@ Store: # specify which engine to store trans status # LogLevel: 'info' # default: info. can be debug|info|warn|error -### dtm can run examples, and examples will use following config to connect db -ExamplesDB: - Driver: 'mysql' - Host: 'localhost' - User: 'root' - Password: '' - Port: 3306 diff --git a/dtmcli/dtmimp/utils.go b/dtmcli/dtmimp/utils.go index 75b3fbd..e2576e2 100644 --- a/dtmcli/dtmimp/utils.go +++ b/dtmcli/dtmimp/utils.go @@ -168,7 +168,7 @@ func PooledDB(conf DBConf) (*sql.DB, error) { // StandaloneDB get a standalone db instance func StandaloneDB(conf DBConf) (*sql.DB, error) { dsn := GetDsn(conf) - logger.Errorf("opening standalone %s: %s", conf.Driver, strings.Replace(dsn, conf.Password, "****", 1)) + logger.Infof("opening standalone %s: %s", conf.Driver, strings.Replace(dsn, conf.Password, "****", 1)) return sql.Open(conf.Driver, dsn) } diff --git a/dtmgrpc/dtmgimp/types.go b/dtmgrpc/dtmgimp/types.go index 3b8048d..a11fe71 100644 --- a/dtmgrpc/dtmgimp/types.go +++ b/dtmgrpc/dtmgimp/types.go @@ -35,12 +35,13 @@ func GrpcServerLog(ctx context.Context, req interface{}, info *grpc.UnaryServerI return m, err } -// GrpcClientLog 打印grpc服务端的日志 +// GrpcClientLog 打印grpc调用的日志 func GrpcClientLog(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { - logger.Debugf("grpc client calling: %s%s %v", cc.Target(), method, req) + logger.Debugf("grpc client calling: %s%s %v", cc.Target(), method, dtmimp.MustMarshalString(req)) LogDtmCtx(ctx) err := invoker(ctx, method, req, reply, cc, opts...) - res := fmt.Sprintf("grpc client called: %s%s %v result: %v err: %v", cc.Target(), method, req, reply, err) + res := fmt.Sprintf("grpc client called: %s%s %s result: %s err: %v", + cc.Target(), method, dtmimp.MustMarshalString(req), dtmimp.MustMarshalString(reply), err) if err != nil { logger.Errorf("%s", res) } else { diff --git a/dtmsvr/api_http.go b/dtmsvr/api_http.go index bbd09de..fa98498 100644 --- a/dtmsvr/api_http.go +++ b/dtmsvr/api_http.go @@ -9,23 +9,23 @@ package dtmsvr import ( "errors" - "github.com/dtm-labs/dtm/common" "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" + "github.com/dtm-labs/dtm/dtmutil" "github.com/gin-gonic/gin" "github.com/prometheus/client_golang/prometheus/promhttp" ) func addRoute(engine *gin.Engine) { - engine.GET("/api/dtmsvr/newGid", common.WrapHandler(newGid)) - engine.POST("/api/dtmsvr/prepare", common.WrapHandler(prepare)) - engine.POST("/api/dtmsvr/submit", common.WrapHandler(submit)) - engine.POST("/api/dtmsvr/abort", common.WrapHandler(abort)) - engine.POST("/api/dtmsvr/registerBranch", common.WrapHandler(registerBranch)) - engine.POST("/api/dtmsvr/registerXaBranch", common.WrapHandler(registerBranch)) // compatible for old sdk - engine.POST("/api/dtmsvr/registerTccBranch", common.WrapHandler(registerBranch)) // compatible for old sdk - engine.GET("/api/dtmsvr/query", common.WrapHandler(query)) - engine.GET("/api/dtmsvr/all", common.WrapHandler(all)) + engine.GET("/api/dtmsvr/newGid", dtmutil.WrapHandler(newGid)) + engine.POST("/api/dtmsvr/prepare", dtmutil.WrapHandler(prepare)) + engine.POST("/api/dtmsvr/submit", dtmutil.WrapHandler(submit)) + engine.POST("/api/dtmsvr/abort", dtmutil.WrapHandler(abort)) + engine.POST("/api/dtmsvr/registerBranch", dtmutil.WrapHandler(registerBranch)) + engine.POST("/api/dtmsvr/registerXaBranch", dtmutil.WrapHandler(registerBranch)) // compatible for old sdk + engine.POST("/api/dtmsvr/registerTccBranch", dtmutil.WrapHandler(registerBranch)) // compatible for old sdk + engine.GET("/api/dtmsvr/query", dtmutil.WrapHandler(query)) + engine.GET("/api/dtmsvr/all", dtmutil.WrapHandler(all)) // add prometheus exporter h := promhttp.Handler() diff --git a/dtmsvr/config/config.go b/dtmsvr/config/config.go new file mode 100644 index 0000000..9acc8f5 --- /dev/null +++ b/dtmsvr/config/config.go @@ -0,0 +1,83 @@ +package config + +import ( + "encoding/json" + "io/ioutil" + + "github.com/dtm-labs/dtm/dtmcli" + "github.com/dtm-labs/dtm/dtmcli/logger" + "gopkg.in/yaml.v2" +) + +const ( + DtmMetricsPort = 8889 + Mysql = "mysql" + Redis = "redis" + BoltDb = "boltdb" +) + +// MicroService config type for micro service +type MicroService struct { + Driver string `yaml:"Driver" default:"default"` + Target string `yaml:"Target"` + EndPoint string `yaml:"EndPoint"` +} + +type Store struct { + Driver string `yaml:"Driver" default:"boltdb"` + Host string `yaml:"Host"` + Port int64 `yaml:"Port"` + User string `yaml:"User"` + Password string `yaml:"Password"` + MaxOpenConns int64 `yaml:"MaxOpenConns" default:"500"` + MaxIdleConns int64 `yaml:"MaxIdleConns" default:"500"` + ConnMaxLifeTime int64 `yaml:"ConnMaxLifeTime" default:"5"` + DataExpire int64 `yaml:"DataExpire" default:"604800"` // Trans data will expire in 7 days. only for redis/boltdb. + RedisPrefix string `yaml:"RedisPrefix" default:"{a}"` // Redis storage prefix. store data to only one slot in cluster +} + +func (s *Store) IsDB() bool { + return s.Driver == dtmcli.DBTypeMysql || s.Driver == dtmcli.DBTypePostgres +} + +func (s *Store) GetDBConf() dtmcli.DBConf { + return dtmcli.DBConf{ + Driver: s.Driver, + Host: s.Host, + Port: s.Port, + User: s.User, + Password: s.Password, + } +} + +type configType struct { + Store Store `yaml:"Store"` + TransCronInterval int64 `yaml:"TransCronInterval" default:"3"` + TimeoutToFail int64 `yaml:"TimeoutToFail" default:"35"` + RetryInterval int64 `yaml:"RetryInterval" default:"10"` + HttpPort int64 `yaml:"HttpPort" default:"36789"` + GrpcPort int64 `yaml:"GrpcPort" default:"36790"` + MicroService MicroService `yaml:"MicroService"` + UpdateBranchSync int64 `yaml:"UpdateBranchSync"` + LogLevel string `yaml:"LogLevel" default:"info"` +} + +// Config 配置 +var Config = configType{} + +// MustLoadConfig load config from env and file +func MustLoadConfig(confFile string) { + loadFromEnv("", &Config) + if confFile != "" { + cont, err := ioutil.ReadFile(confFile) + logger.FatalIfError(err) + err = yaml.UnmarshalStrict(cont, &Config) + logger.FatalIfError(err) + } + scont, err := json.MarshalIndent(&Config, "", " ") + logger.FatalIfError(err) + logger.Infof("config file: %s loaded config is: \n%s", confFile, scont) + err = checkConfig() + logger.FatalfIf(err != nil, `config error: '%v'. + please visit http://d.dtm.pub to see the config document.`, err) +} diff --git a/common/config_test.go b/dtmsvr/config/config_test.go similarity index 68% rename from common/config_test.go rename to dtmsvr/config/config_test.go index b3ea8dc..db62add 100644 --- a/common/config_test.go +++ b/dtmsvr/config/config_test.go @@ -1,11 +1,11 @@ -package common +package config import ( "errors" "os" "testing" - "github.com/go-playground/assert/v2" + "github.com/stretchr/testify/assert" ) func TestLoadFromEnv(t *testing.T) { @@ -47,3 +47,26 @@ func TestCheckConfig(t *testing.T) { userExpect := errors.New("Db user not valid ") assert.Equal(t, userErr, userExpect) } + +func TestConfig(t *testing.T) { + testConfigStringField(&Config.Store.Driver, "", t) + testConfigStringField(&Config.Store.User, "", t) + testConfigIntField(&Config.RetryInterval, 9, t) + testConfigIntField(&Config.TimeoutToFail, 9, t) +} + +func testConfigStringField(fd *string, val string, t *testing.T) { + old := *fd + *fd = val + str := checkConfig() + assert.NotEqual(t, "", str) + *fd = old +} + +func testConfigIntField(fd *int64, val int64, t *testing.T) { + old := *fd + *fd = val + str := checkConfig() + assert.NotEqual(t, "", str) + *fd = old +} diff --git a/common/config_utils.go b/dtmsvr/config/config_utils.go similarity index 64% rename from common/config_utils.go rename to dtmsvr/config/config_utils.go index 60069b8..1dc991f 100644 --- a/common/config_utils.go +++ b/dtmsvr/config/config_utils.go @@ -1,6 +1,7 @@ -package common +package config import ( + "errors" "fmt" "os" "reflect" @@ -53,3 +54,34 @@ func toUnderscoreUpper(key string) string { // logger.Debugf("loading from env: %s", strings.ToUpper(s2)) return strings.ToUpper(s2) } + +func checkConfig() error { + if Config.RetryInterval < 10 { + return errors.New("RetryInterval should not be less than 10") + } + if Config.TimeoutToFail < Config.RetryInterval { + return errors.New("TimeoutToFail should not be less than RetryInterval") + } + switch Config.Store.Driver { + case BoltDb: + return nil + case Mysql: + if Config.Store.Host == "" { + return errors.New("Db host not valid ") + } + if Config.Store.Port == 0 { + return errors.New("Db port not valid ") + } + if Config.Store.User == "" { + return errors.New("Db user not valid ") + } + case Redis: + if Config.Store.Host == "" { + return errors.New("Redis host not valid ") + } + if Config.Store.Port == 0 { + return errors.New("Redis port not valid ") + } + } + return nil +} diff --git a/dtmsvr/cron.go b/dtmsvr/cron.go index 5eec83c..8b1520a 100644 --- a/dtmsvr/cron.go +++ b/dtmsvr/cron.go @@ -65,7 +65,7 @@ func handlePanic(perr *error) { } func sleepCronTime() { - normal := time.Duration((float64(config.TransCronInterval) - rand.Float64()) * float64(time.Second)) + normal := time.Duration((float64(conf.TransCronInterval) - rand.Float64()) * float64(time.Second)) interval := dtmimp.If(CronForwardDuration > 0, 1*time.Millisecond, normal).(time.Duration) logger.Debugf("sleeping for %v milli", interval/time.Microsecond) time.Sleep(interval) diff --git a/dtmsvr/storage/boltdb/boltdb.go b/dtmsvr/storage/boltdb/boltdb.go index 439cfd0..d0cd912 100644 --- a/dtmsvr/storage/boltdb/boltdb.go +++ b/dtmsvr/storage/boltdb/boltdb.go @@ -15,13 +15,14 @@ import ( bolt "go.etcd.io/bbolt" "gorm.io/gorm" - "github.com/dtm-labs/dtm/common" "github.com/dtm-labs/dtm/dtmcli/dtmimp" "github.com/dtm-labs/dtm/dtmcli/logger" + "github.com/dtm-labs/dtm/dtmsvr/config" "github.com/dtm-labs/dtm/dtmsvr/storage" + "github.com/dtm-labs/dtm/dtmutil" ) -var config = &common.Config +var conf = &config.Config type BoltdbStore struct { } @@ -42,7 +43,7 @@ func boltGet() *bolt.DB { // 1. refactor this code // 2. make cleanup run period, to avoid the file growup when server long-running err = cleanupExpiredData( - time.Duration(common.Config.Store.DataExpire)*time.Second, + time.Duration(conf.Store.DataExpire)*time.Second, db, ) dtmimp.E2P(err) @@ -348,8 +349,8 @@ func (s *BoltdbStore) ChangeGlobalStatus(global *storage.TransGlobalStore, newSt func (s *BoltdbStore) TouchCronTime(global *storage.TransGlobalStore, nextCronInterval int64) { oldUnix := global.NextCronTime.Unix() - global.NextCronTime = common.GetNextTime(nextCronInterval) - global.UpdateTime = common.GetNextTime(0) + global.NextCronTime = dtmutil.GetNextTime(nextCronInterval) + global.UpdateTime = dtmutil.GetNextTime(0) global.NextCronInterval = nextCronInterval err := boltGet().Update(func(t *bolt.Tx) error { g := tGetGlobal(t, global.Gid) @@ -367,7 +368,7 @@ func (s *BoltdbStore) TouchCronTime(global *storage.TransGlobalStore, nextCronIn func (s *BoltdbStore) LockOneGlobalTrans(expireIn time.Duration) *storage.TransGlobalStore { var trans *storage.TransGlobalStore = nil min := fmt.Sprintf("%d", time.Now().Add(expireIn).Unix()) - next := time.Now().Add(time.Duration(config.RetryInterval) * time.Second) + next := time.Now().Add(time.Duration(conf.RetryInterval) * time.Second) err := boltGet().Update(func(t *bolt.Tx) error { cursor := t.Bucket(bucketIndex).Cursor() for trans == nil { diff --git a/dtmsvr/storage/redis/redis.go b/dtmsvr/storage/redis/redis.go index b32872b..f8cef4b 100644 --- a/dtmsvr/storage/redis/redis.go +++ b/dtmsvr/storage/redis/redis.go @@ -9,14 +9,15 @@ import ( "github.com/go-redis/redis/v8" "gorm.io/gorm" - "github.com/dtm-labs/dtm/common" "github.com/dtm-labs/dtm/dtmcli/dtmimp" "github.com/dtm-labs/dtm/dtmcli/logger" + "github.com/dtm-labs/dtm/dtmsvr/config" "github.com/dtm-labs/dtm/dtmsvr/storage" + "github.com/dtm-labs/dtm/dtmutil" ) -// TODO: optimize this, it's very strange to use pointer to common.Config -var config = &common.Config +// TODO: optimize this, it's very strange to use pointer to dtmutil.Config +var conf = &config.Config // TODO: optimize this, all function should have context as first parameter var ctx = context.Background() @@ -40,7 +41,7 @@ func (s *RedisStore) PopulateData(skipDrop bool) { func (s *RedisStore) FindTransGlobalStore(gid string) *storage.TransGlobalStore { logger.Debugf("calling FindTransGlobalStore: %s", gid) - r, err := redisGet().Get(ctx, config.Store.RedisPrefix+"_g_"+gid).Result() + r, err := redisGet().Get(ctx, conf.Store.RedisPrefix+"_g_"+gid).Result() if err == redis.Nil { return nil } @@ -56,7 +57,7 @@ func (s *RedisStore) ScanTransGlobalStores(position *string, limit int64) []stor if *position != "" { lid = uint64(dtmimp.MustAtoi(*position)) } - keys, cursor, err := redisGet().Scan(ctx, lid, config.Store.RedisPrefix+"_g_*", limit).Result() + keys, cursor, err := redisGet().Scan(ctx, lid, conf.Store.RedisPrefix+"_g_*", limit).Result() dtmimp.E2P(err) globals := []storage.TransGlobalStore{} if len(keys) > 0 { @@ -78,7 +79,7 @@ func (s *RedisStore) ScanTransGlobalStores(position *string, limit int64) []stor func (s *RedisStore) FindBranches(gid string) []storage.TransBranchStore { logger.Debugf("calling FindBranches: %s", gid) - sa, err := redisGet().LRange(ctx, config.Store.RedisPrefix+"_b_"+gid, 0, -1).Result() + sa, err := redisGet().LRange(ctx, conf.Store.RedisPrefix+"_b_"+gid, 0, -1).Result() dtmimp.E2P(err) branches := make([]storage.TransBranchStore, len(sa)) for k, v := range sa { @@ -98,14 +99,14 @@ type argList struct { func newArgList() *argList { a := &argList{} - return a.AppendRaw(config.Store.RedisPrefix).AppendObject(config.Store.DataExpire) + return a.AppendRaw(conf.Store.RedisPrefix).AppendObject(conf.Store.DataExpire) } func (a *argList) AppendGid(gid string) *argList { - a.Keys = append(a.Keys, config.Store.RedisPrefix+"_g_"+gid) - a.Keys = append(a.Keys, config.Store.RedisPrefix+"_b_"+gid) - a.Keys = append(a.Keys, config.Store.RedisPrefix+"_u") - a.Keys = append(a.Keys, config.Store.RedisPrefix+"_s_"+gid) + a.Keys = append(a.Keys, conf.Store.RedisPrefix+"_g_"+gid) + a.Keys = append(a.Keys, conf.Store.RedisPrefix+"_b_"+gid) + a.Keys = append(a.Keys, conf.Store.RedisPrefix+"_u") + a.Keys = append(a.Keys, conf.Store.RedisPrefix+"_s_"+gid) return a } @@ -221,9 +222,9 @@ end func (s *RedisStore) LockOneGlobalTrans(expireIn time.Duration) *storage.TransGlobalStore { expired := time.Now().Add(expireIn).Unix() - next := time.Now().Add(time.Duration(config.RetryInterval) * time.Second).Unix() + next := time.Now().Add(time.Duration(conf.RetryInterval) * time.Second).Unix() args := newArgList().AppendGid("").AppendRaw(expired).AppendRaw(next) - lua := `-- LocakOneGlobalTrans + lua := `-- LockOneGlobalTrans local r = redis.call('ZRANGE', KEYS[3], 0, 0, 'WITHSCORES') local gid = r[1] if gid == nil then @@ -250,8 +251,8 @@ return gid } func (s *RedisStore) TouchCronTime(global *storage.TransGlobalStore, nextCronInterval int64) { - global.NextCronTime = common.GetNextTime(nextCronInterval) - global.UpdateTime = common.GetNextTime(0) + global.NextCronTime = dtmutil.GetNextTime(nextCronInterval) + global.UpdateTime = dtmutil.GetNextTime(0) global.NextCronInterval = nextCronInterval args := newArgList(). AppendGid(global.Gid). @@ -277,11 +278,11 @@ var ( func redisGet() *redis.Client { once.Do(func() { - logger.Debugf("connecting to redis: %v", config.Store) + logger.Debugf("connecting to redis: %v", conf.Store) rdb = redis.NewClient(&redis.Options{ - Addr: fmt.Sprintf("%s:%d", config.Store.Host, config.Store.Port), - Username: config.Store.User, - Password: config.Store.Password, + Addr: fmt.Sprintf("%s:%d", conf.Store.Host, conf.Store.Port), + Username: conf.Store.User, + Password: conf.Store.Password, }) }) return rdb diff --git a/dtmsvr/storage/registry/registry.go b/dtmsvr/storage/registry/registry.go index 2fc349c..d65f2e1 100644 --- a/dtmsvr/storage/registry/registry.go +++ b/dtmsvr/storage/registry/registry.go @@ -3,14 +3,14 @@ package registry import ( "time" - "github.com/dtm-labs/dtm/common" + "github.com/dtm-labs/dtm/dtmsvr/config" "github.com/dtm-labs/dtm/dtmsvr/storage" "github.com/dtm-labs/dtm/dtmsvr/storage/boltdb" "github.com/dtm-labs/dtm/dtmsvr/storage/redis" "github.com/dtm-labs/dtm/dtmsvr/storage/sql" ) -var config = &common.Config +var conf = &config.Config var stores map[string]storage.Store = map[string]storage.Store{ "redis": &redis.RedisStore{}, @@ -20,7 +20,7 @@ var stores map[string]storage.Store = map[string]storage.Store{ } func GetStore() storage.Store { - return stores[config.Store.Driver] + return stores[conf.Store.Driver] } // WaitStoreUp wait for db to go up diff --git a/dtmsvr/storage/sql/sql.go b/dtmsvr/storage/sql/sql.go index fd3fe56..45d03b3 100644 --- a/dtmsvr/storage/sql/sql.go +++ b/dtmsvr/storage/sql/sql.go @@ -9,26 +9,27 @@ import ( "gorm.io/gorm" "gorm.io/gorm/clause" - "github.com/dtm-labs/dtm/common" "github.com/dtm-labs/dtm/dtmcli/dtmimp" + "github.com/dtm-labs/dtm/dtmsvr/config" "github.com/dtm-labs/dtm/dtmsvr/storage" + "github.com/dtm-labs/dtm/dtmutil" ) -var config = &common.Config +var conf = &config.Config type SqlStore struct { } func (s *SqlStore) Ping() error { - db, err := dtmimp.StandaloneDB(config.Store.GetDBConf()) + db, err := dtmimp.StandaloneDB(conf.Store.GetDBConf()) dtmimp.E2P(err) _, err = db.Exec("select 1") return err } func (s *SqlStore) PopulateData(skipDrop bool) { - file := fmt.Sprintf("%s/dtmsvr.storage.%s.sql", common.GetSqlDir(), config.Store.Driver) - common.RunSQLScript(config.Store.GetDBConf(), file, skipDrop) + file := fmt.Sprintf("%s/dtmsvr.storage.%s.sql", dtmutil.GetSqlDir(), conf.Store.Driver) + dtmutil.RunSQLScript(conf.Store.GetDBConf(), file, skipDrop) } func (s *SqlStore) FindTransGlobalStore(gid string) *storage.TransGlobalStore { @@ -83,7 +84,7 @@ func (s *SqlStore) LockGlobalSaveBranches(gid string, status string, branches [] func (s *SqlStore) MaySaveNewTrans(global *storage.TransGlobalStore, branches []storage.TransBranchStore) error { return dbGet().Transaction(func(db1 *gorm.DB) error { - db := &common.DB{DB: db1} + db := &dtmutil.DB{DB: db1} dbr := db.Must().Clauses(clause.OnConflict{ DoNothing: true, }).Create(global) @@ -109,8 +110,8 @@ func (s *SqlStore) ChangeGlobalStatus(global *storage.TransGlobalStore, newStatu } func (s *SqlStore) TouchCronTime(global *storage.TransGlobalStore, nextCronInterval int64) { - global.NextCronTime = common.GetNextTime(nextCronInterval) - global.UpdateTime = common.GetNextTime(0) + global.NextCronTime = dtmutil.GetNextTime(nextCronInterval) + global.UpdateTime = dtmutil.GetNextTime(0) global.NextCronInterval = nextCronInterval dbGet().Must().Model(global).Where("status=? and gid=?", global.Status, global.Gid). Select([]string{"next_cron_time", "update_time", "next_cron_interval"}).Updates(global) @@ -122,7 +123,7 @@ func (s *SqlStore) LockOneGlobalTrans(expireIn time.Duration) *storage.TransGlob return map[string]string{ "mysql": fmt.Sprintf("date_add(now(), interval %d second)", second), "postgres": fmt.Sprintf("current_timestamp + interval '%d second'", second), - }[config.Store.Driver] + }[conf.Store.Driver] } expire := int(expireIn / time.Second) whereTime := fmt.Sprintf("next_cron_time < %s", getTime(expire)) @@ -134,7 +135,7 @@ func (s *SqlStore) LockOneGlobalTrans(expireIn time.Duration) *storage.TransGlob Select([]string{"owner", "next_cron_time"}). Updates(&storage.TransGlobalStore{ Owner: owner, - NextCronTime: common.GetNextTime(common.Config.RetryInterval), + NextCronTime: dtmutil.GetNextTime(conf.RetryInterval), }) if dbr.RowsAffected == 0 { return nil @@ -143,8 +144,15 @@ func (s *SqlStore) LockOneGlobalTrans(expireIn time.Duration) *storage.TransGlob return global } -func dbGet() *common.DB { - return common.DbGet(config.Store.GetDBConf()) +func setDBConn(db *gorm.DB) { + sqldb, _ := db.DB() + sqldb.SetMaxOpenConns(int(conf.Store.MaxOpenConns)) + sqldb.SetMaxIdleConns(int(conf.Store.MaxIdleConns)) + sqldb.SetConnMaxLifetime(time.Duration(conf.Store.ConnMaxLifeTime) * time.Minute) +} + +func dbGet() *dtmutil.DB { + return dtmutil.DbGet(conf.Store.GetDBConf(), setDBConn) } func wrapError(err error) error { diff --git a/dtmsvr/storage/trans.go b/dtmsvr/storage/trans.go index cb85ee1..e1f3fa3 100644 --- a/dtmsvr/storage/trans.go +++ b/dtmsvr/storage/trans.go @@ -3,13 +3,13 @@ package storage import ( "time" - "github.com/dtm-labs/dtm/common" "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" + "github.com/dtm-labs/dtm/dtmutil" ) type TransGlobalStore struct { - common.ModelBase + dtmutil.ModelBase Gid string `json:"gid,omitempty"` TransType string `json:"trans_type,omitempty"` Steps []map[string]string `json:"steps,omitempty" gorm:"-"` @@ -40,7 +40,7 @@ func (g *TransGlobalStore) String() string { // TransBranchStore branch transaction type TransBranchStore struct { - common.ModelBase + dtmutil.ModelBase Gid string `json:"gid,omitempty"` URL string `json:"url,omitempty"` BinData []byte diff --git a/dtmsvr/svr.go b/dtmsvr/svr.go index e2c739d..f241e18 100644 --- a/dtmsvr/svr.go +++ b/dtmsvr/svr.go @@ -11,10 +11,10 @@ import ( "net" "time" - "github.com/dtm-labs/dtm/common" "github.com/dtm-labs/dtm/dtmcli/logger" "github.com/dtm-labs/dtm/dtmgrpc/dtmgimp" "github.com/dtm-labs/dtm/dtmgrpc/dtmgpb" + "github.com/dtm-labs/dtm/dtmutil" "github.com/dtm-labs/dtmdriver" grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" "google.golang.org/grpc" @@ -23,13 +23,13 @@ import ( // StartSvr StartSvr func StartSvr() { logger.Infof("start dtmsvr") - app := common.GetGinApp() + app := dtmutil.GetGinApp() app = httpMetrics(app) addRoute(app) - logger.Infof("dtmsvr listen at: %d", config.HttpPort) - go app.Run(fmt.Sprintf(":%d", config.HttpPort)) + logger.Infof("dtmsvr listen at: %d", conf.HttpPort) + go app.Run(fmt.Sprintf(":%d", conf.HttpPort)) - lis, err := net.Listen("tcp", fmt.Sprintf(":%d", config.GrpcPort)) + lis, err := net.Listen("tcp", fmt.Sprintf(":%d", conf.GrpcPort)) logger.FatalIfError(err) s := grpc.NewServer( grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer( @@ -44,9 +44,9 @@ func StartSvr() { go updateBranchAsync() time.Sleep(100 * time.Millisecond) - err = dtmdriver.Use(config.MicroService.Driver) + err = dtmdriver.Use(conf.MicroService.Driver) logger.FatalIfError(err) - err = dtmdriver.GetDriver().RegisterGrpcService(config.MicroService.Target, config.MicroService.EndPoint) + err = dtmdriver.GetDriver().RegisterGrpcService(conf.MicroService.Target, conf.MicroService.EndPoint) logger.FatalIfError(err) } @@ -61,7 +61,7 @@ var updateBranchAsyncChan chan branchStatus = make(chan branchStatus, 1000) func updateBranchAsync() { for { // flush branches every second - defer common.RecoverPanic(nil) + defer dtmutil.RecoverPanic(nil) updates := []TransBranch{} started := time.Now() checkInterval := 20 * time.Millisecond @@ -69,7 +69,7 @@ func updateBranchAsync() { select { case updateBranch := <-updateBranchAsyncChan: updates = append(updates, TransBranch{ - ModelBase: common.ModelBase{ID: updateBranch.id}, + ModelBase: dtmutil.ModelBase{ID: updateBranch.id}, Status: updateBranch.status, FinishTime: updateBranch.finishTime, }) diff --git a/dtmsvr/svr_imports.go b/dtmsvr/svr_imports.go deleted file mode 100644 index 7cc1bea..0000000 --- a/dtmsvr/svr_imports.go +++ /dev/null @@ -1,7 +0,0 @@ -package dtmsvr - -import ( - _ "github.com/dtm-labs/dtmdriver-gozero" - _ "github.com/dtm-labs/dtmdriver-polaris" - _ "github.com/dtm-labs/dtmdriver-protocol1" -) diff --git a/dtmsvr/trans_process.go b/dtmsvr/trans_process.go index 22c2fab..cac4c96 100644 --- a/dtmsvr/trans_process.go +++ b/dtmsvr/trans_process.go @@ -9,10 +9,10 @@ package dtmsvr import ( "time" - "github.com/dtm-labs/dtm/common" "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/dtmutil" ) // Process process global transaction once @@ -62,7 +62,7 @@ func (t *TransGlobal) processInner(branches []TransBranch) (rerr error) { func (t *TransGlobal) saveNew() ([]TransBranch, error) { t.NextCronInterval = t.getNextCronInterval(cronReset) - t.NextCronTime = common.GetNextTime(t.NextCronInterval) + t.NextCronTime = dtmutil.GetNextTime(t.NextCronInterval) t.Options = dtmimp.MustMarshalString(t.TransOptions) if t.Options == "{}" { t.Options = "" diff --git a/dtmsvr/trans_status.go b/dtmsvr/trans_status.go index bf14e43..6f1dea0 100644 --- a/dtmsvr/trans_status.go +++ b/dtmsvr/trans_status.go @@ -47,7 +47,7 @@ func (t *TransGlobal) changeBranchStatus(b *TransBranch, status string, branchPo b.Status = status b.FinishTime = &now b.UpdateTime = &now - if config.Store.Driver != dtmimp.DBTypeMysql && config.Store.Driver != dtmimp.DBTypePostgres || config.UpdateBranchSync > 0 || t.updateBranchSync { + if conf.Store.Driver != dtmimp.DBTypeMysql && conf.Store.Driver != dtmimp.DBTypePostgres || conf.UpdateBranchSync > 0 || t.updateBranchSync { GetStore().LockGlobalSaveBranches(t.Gid, t.Status, []TransBranch{*b}, branchPos) logger.Infof("LockGlobalSaveBranches ok: gid: %s old status: %s branches: %s", b.Gid, dtmcli.StatusPrepared, b.String()) @@ -59,7 +59,7 @@ func (t *TransGlobal) changeBranchStatus(b *TransBranch, status string, branchPo func (t *TransGlobal) isTimeout() bool { timeout := t.TimeoutToFail if t.TimeoutToFail == 0 && t.TransType != "saga" { - timeout = config.TimeoutToFail + timeout = conf.TimeoutToFail } if timeout == 0 { return false @@ -136,7 +136,7 @@ func (t *TransGlobal) execBranch(branch *TransBranch, branchPos int) error { branchMetrics(t, branch, status == dtmcli.StatusSucceed) // if time pass 1500ms and NextCronInterval is not default, then reset NextCronInterval if err == nil && time.Since(t.lastTouched)+NowForwardDuration >= 1500*time.Millisecond || - t.NextCronInterval > config.RetryInterval && t.NextCronInterval > t.RetryInterval { + t.NextCronInterval > conf.RetryInterval && t.NextCronInterval > t.RetryInterval { t.touchCronTime(cronReset) } else if err == dtmimp.ErrOngoing { t.touchCronTime(cronKeep) @@ -154,6 +154,6 @@ func (t *TransGlobal) getNextCronInterval(ctype cronType) int64 { } else if t.RetryInterval != 0 { return t.RetryInterval } else { - return config.RetryInterval + return conf.RetryInterval } } diff --git a/dtmsvr/utils.go b/dtmsvr/utils.go index 3b296cc..37d938c 100644 --- a/dtmsvr/utils.go +++ b/dtmsvr/utils.go @@ -10,8 +10,8 @@ import ( "fmt" "time" - "github.com/dtm-labs/dtm/common" "github.com/dtm-labs/dtm/dtmcli/dtmimp" + "github.com/dtm-labs/dtm/dtmsvr/config" "github.com/dtm-labs/dtm/dtmsvr/storage" "github.com/dtm-labs/dtm/dtmsvr/storage/registry" "github.com/lithammer/shortuuid/v3" @@ -26,7 +26,7 @@ type branchStatus struct { var p2e = dtmimp.P2E var e2p = dtmimp.E2P -var config = &common.Config +var conf = &config.Config func GetStore() storage.Store { return registry.GetStore() diff --git a/dtmsvr/utils_test.go b/dtmsvr/utils_test.go index 6c6f371..2c24571 100644 --- a/dtmsvr/utils_test.go +++ b/dtmsvr/utils_test.go @@ -22,6 +22,6 @@ func TestSetNextCron(t *testing.T) { tg.RetryInterval = 15 assert.Equal(t, int64(15), tg.getNextCronInterval(cronReset)) tg.RetryInterval = 0 - assert.Equal(t, config.RetryInterval, tg.getNextCronInterval(cronReset)) - assert.Equal(t, config.RetryInterval*2, tg.getNextCronInterval(cronBackoff)) + assert.Equal(t, conf.RetryInterval, tg.getNextCronInterval(cronReset)) + assert.Equal(t, conf.RetryInterval*2, tg.getNextCronInterval(cronBackoff)) } diff --git a/dtmutil/consts.go b/dtmutil/consts.go new file mode 100644 index 0000000..5dfd9a6 --- /dev/null +++ b/dtmutil/consts.go @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021 yedf. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + */ + +package dtmutil + +const ( + // DefaultHttpServer default url for http server. used by test and examples + DefaultHttpServer = "http://localhost:36789/api/dtmsvr" + // DefaultGrpcServer default url for grpc server. used by test and examples + DefaultGrpcServer = "localhost:36790" +) diff --git a/common/db.go b/dtmutil/db.go similarity index 90% rename from common/db.go rename to dtmutil/db.go index d479078..da41468 100644 --- a/common/db.go +++ b/dtmutil/db.go @@ -1,4 +1,4 @@ -package common +package dtmutil import ( "database/sql" @@ -96,16 +96,8 @@ func (op *tracePlugin) Initialize(db *gorm.DB) (err error) { return } -// SetDBConn set db connection conf -func SetDBConn(db *DB) { - sqldb, _ := db.DB.DB() - sqldb.SetMaxOpenConns(int(Config.Store.MaxOpenConns)) - sqldb.SetMaxIdleConns(int(Config.Store.MaxIdleConns)) - sqldb.SetConnMaxLifetime(time.Duration(Config.Store.ConnMaxLifeTime) * time.Minute) -} - // DbGet get db connection for specified conf -func DbGet(conf dtmcli.DBConf) *DB { +func DbGet(conf dtmcli.DBConf, ops ...func(*gorm.DB)) *DB { dsn := dtmimp.GetDsn(conf) db, ok := dbs.Load(dsn) if !ok { @@ -116,7 +108,9 @@ func DbGet(conf dtmcli.DBConf) *DB { dtmimp.E2P(err) db1.Use(&tracePlugin{}) db = &DB{DB: db1} - SetDBConn(db.(*DB)) + for _, op := range ops { + op(db1) + } dbs.Store(dsn, db) } return db.(*DB) diff --git a/common/utils.go b/dtmutil/utils.go similarity index 99% rename from common/utils.go rename to dtmutil/utils.go index 4af5c1b..4fbbc7d 100644 --- a/common/utils.go +++ b/dtmutil/utils.go @@ -4,7 +4,7 @@ * license that can be found in the LICENSE file. */ -package common +package dtmutil import ( "bytes" diff --git a/common/utils_test.go b/dtmutil/utils_test.go similarity index 96% rename from common/utils_test.go rename to dtmutil/utils_test.go index 303a8ab..6900796 100644 --- a/common/utils_test.go +++ b/dtmutil/utils_test.go @@ -4,7 +4,7 @@ * license that can be found in the LICENSE file. */ -package common +package dtmutil import ( "errors" @@ -16,7 +16,7 @@ import ( "testing" "github.com/gin-gonic/gin" - "github.com/go-playground/assert/v2" + "github.com/stretchr/testify/assert" ) func TestGin(t *testing.T) { diff --git a/examples/base.go b/examples/base.go deleted file mode 100644 index d9b8fcf..0000000 --- a/examples/base.go +++ /dev/null @@ -1,14 +0,0 @@ -package examples - -import "fmt" - -func Startup() { - InitConfig() - GrpcStartup() - BaseAppStartup() -} - -func InitConfig() { - DtmHttpServer = fmt.Sprintf("http://localhost:%d/api/dtmsvr", config.HttpPort) - DtmGrpcServer = fmt.Sprintf("localhost:%d", config.GrpcPort) -} diff --git a/examples/busi.pb.go b/examples/busi.pb.go deleted file mode 100644 index 7746311..0000000 --- a/examples/busi.pb.go +++ /dev/null @@ -1,330 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.17.3 -// source: examples/busi.proto - -package examples - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - emptypb "google.golang.org/protobuf/types/known/emptypb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// DtmRequest request sent to dtm server -type BusiReq struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Amount int64 `protobuf:"varint,1,opt,name=Amount,proto3" json:"Amount,omitempty"` - TransOutResult string `protobuf:"bytes,2,opt,name=TransOutResult,proto3" json:"TransOutResult,omitempty"` - TransInResult string `protobuf:"bytes,3,opt,name=TransInResult,proto3" json:"TransInResult,omitempty"` -} - -func (x *BusiReq) Reset() { - *x = BusiReq{} - if protoimpl.UnsafeEnabled { - mi := &file_examples_busi_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BusiReq) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BusiReq) ProtoMessage() {} - -func (x *BusiReq) ProtoReflect() protoreflect.Message { - mi := &file_examples_busi_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BusiReq.ProtoReflect.Descriptor instead. -func (*BusiReq) Descriptor() ([]byte, []int) { - return file_examples_busi_proto_rawDescGZIP(), []int{0} -} - -func (x *BusiReq) GetAmount() int64 { - if x != nil { - return x.Amount - } - return 0 -} - -func (x *BusiReq) GetTransOutResult() string { - if x != nil { - return x.TransOutResult - } - return "" -} - -func (x *BusiReq) GetTransInResult() string { - if x != nil { - return x.TransInResult - } - return "" -} - -type BusiReply struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` -} - -func (x *BusiReply) Reset() { - *x = BusiReply{} - if protoimpl.UnsafeEnabled { - mi := &file_examples_busi_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BusiReply) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BusiReply) ProtoMessage() {} - -func (x *BusiReply) ProtoReflect() protoreflect.Message { - mi := &file_examples_busi_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BusiReply.ProtoReflect.Descriptor instead. -func (*BusiReply) Descriptor() ([]byte, []int) { - return file_examples_busi_proto_rawDescGZIP(), []int{1} -} - -func (x *BusiReply) GetMessage() string { - if x != nil { - return x.Message - } - return "" -} - -var File_examples_busi_proto protoreflect.FileDescriptor - -var file_examples_busi_proto_rawDesc = []byte{ - 0x0a, 0x13, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x62, 0x75, 0x73, 0x69, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 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, 0x6f, 0x0a, 0x07, - 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 0x12, 0x16, 0x0a, 0x06, 0x41, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, - 0x26, 0x0a, 0x0e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x75, - 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x49, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x49, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x25, 0x0a, - 0x09, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x32, 0x97, 0x08, 0x0a, 0x04, 0x42, 0x75, 0x73, 0x69, 0x12, 0x35, 0x0a, - 0x09, 0x43, 0x61, 0x6e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x12, 0x11, 0x2e, 0x65, 0x78, 0x61, - 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, - 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x70, - 0x6c, 0x79, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x07, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x49, 0x6e, 0x12, - 0x11, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, - 0x65, 0x71, 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, 0x37, 0x0a, 0x08, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x75, 0x74, 0x12, 0x11, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, - 0x6c, 0x65, 0x73, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x3c, 0x0a, 0x0d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x49, 0x6e, - 0x52, 0x65, 0x76, 0x65, 0x72, 0x74, 0x12, 0x11, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, - 0x73, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x3d, 0x0a, 0x0e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x75, 0x74, 0x52, - 0x65, 0x76, 0x65, 0x72, 0x74, 0x12, 0x11, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, - 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x3d, 0x0a, 0x0e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x49, 0x6e, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x72, 0x6d, 0x12, 0x11, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, - 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x3e, 0x0a, 0x0f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x75, 0x74, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x72, 0x6d, 0x12, 0x11, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, - 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x3c, 0x0a, 0x08, 0x58, 0x61, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 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, 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, 0x09, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x49, 0x6e, 0x58, 0x61, 0x12, 0x11, 0x2e, 0x65, - 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x39, 0x0a, 0x0a, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x4f, 0x75, 0x74, 0x58, 0x61, 0x12, 0x11, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, - 0x65, 0x73, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x39, 0x0a, 0x0a, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x49, 0x6e, 0x54, - 0x63, 0x63, 0x12, 0x11, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x42, 0x75, - 0x73, 0x69, 0x52, 0x65, 0x71, 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, - 0x3a, 0x0a, 0x0b, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x75, 0x74, 0x54, 0x63, 0x63, 0x12, 0x11, - 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, - 0x71, 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, 0x3f, 0x0a, 0x10, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x49, 0x6e, 0x54, 0x63, 0x63, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, - 0x11, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, - 0x65, 0x71, 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, 0x3b, 0x0a, 0x0c, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x49, 0x6e, 0x42, 0x53, 0x61, 0x67, 0x61, 0x12, 0x11, 0x2e, 0x65, - 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x3c, 0x0a, 0x0d, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x4f, 0x75, 0x74, 0x42, 0x53, 0x61, 0x67, 0x61, 0x12, 0x11, 0x2e, 0x65, 0x78, 0x61, - 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x41, 0x0a, 0x12, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x49, 0x6e, 0x52, 0x65, 0x76, 0x65, 0x72, 0x74, 0x42, 0x53, 0x61, 0x67, 0x61, 0x12, 0x11, 0x2e, - 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, - 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, 0x42, 0x0a, 0x13, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x76, 0x65, 0x72, 0x74, 0x42, 0x53, 0x61, 0x67, - 0x61, 0x12, 0x11, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x42, 0x75, 0x73, - 0x69, 0x52, 0x65, 0x71, 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, 0x0c, - 0x5a, 0x0a, 0x2e, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_examples_busi_proto_rawDescOnce sync.Once - file_examples_busi_proto_rawDescData = file_examples_busi_proto_rawDesc -) - -func file_examples_busi_proto_rawDescGZIP() []byte { - file_examples_busi_proto_rawDescOnce.Do(func() { - file_examples_busi_proto_rawDescData = protoimpl.X.CompressGZIP(file_examples_busi_proto_rawDescData) - }) - return file_examples_busi_proto_rawDescData -} - -var file_examples_busi_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_examples_busi_proto_goTypes = []interface{}{ - (*BusiReq)(nil), // 0: examples.BusiReq - (*BusiReply)(nil), // 1: examples.BusiReply - (*emptypb.Empty)(nil), // 2: google.protobuf.Empty -} -var file_examples_busi_proto_depIdxs = []int32{ - 0, // 0: examples.Busi.CanSubmit:input_type -> examples.BusiReq - 0, // 1: examples.Busi.TransIn:input_type -> examples.BusiReq - 0, // 2: examples.Busi.TransOut:input_type -> examples.BusiReq - 0, // 3: examples.Busi.TransInRevert:input_type -> examples.BusiReq - 0, // 4: examples.Busi.TransOutRevert:input_type -> examples.BusiReq - 0, // 5: examples.Busi.TransInConfirm:input_type -> examples.BusiReq - 0, // 6: examples.Busi.TransOutConfirm:input_type -> examples.BusiReq - 2, // 7: examples.Busi.XaNotify:input_type -> google.protobuf.Empty - 0, // 8: examples.Busi.TransInXa:input_type -> examples.BusiReq - 0, // 9: examples.Busi.TransOutXa:input_type -> examples.BusiReq - 0, // 10: examples.Busi.TransInTcc:input_type -> examples.BusiReq - 0, // 11: examples.Busi.TransOutTcc:input_type -> examples.BusiReq - 0, // 12: examples.Busi.TransInTccNested:input_type -> examples.BusiReq - 0, // 13: examples.Busi.TransInBSaga:input_type -> examples.BusiReq - 0, // 14: examples.Busi.TransOutBSaga:input_type -> examples.BusiReq - 0, // 15: examples.Busi.TransInRevertBSaga:input_type -> examples.BusiReq - 0, // 16: examples.Busi.TransOutRevertBSaga:input_type -> examples.BusiReq - 1, // 17: examples.Busi.CanSubmit:output_type -> examples.BusiReply - 2, // 18: examples.Busi.TransIn:output_type -> google.protobuf.Empty - 2, // 19: examples.Busi.TransOut:output_type -> google.protobuf.Empty - 2, // 20: examples.Busi.TransInRevert:output_type -> google.protobuf.Empty - 2, // 21: examples.Busi.TransOutRevert:output_type -> google.protobuf.Empty - 2, // 22: examples.Busi.TransInConfirm:output_type -> google.protobuf.Empty - 2, // 23: examples.Busi.TransOutConfirm:output_type -> google.protobuf.Empty - 2, // 24: examples.Busi.XaNotify:output_type -> google.protobuf.Empty - 2, // 25: examples.Busi.TransInXa:output_type -> google.protobuf.Empty - 2, // 26: examples.Busi.TransOutXa:output_type -> google.protobuf.Empty - 2, // 27: examples.Busi.TransInTcc:output_type -> google.protobuf.Empty - 2, // 28: examples.Busi.TransOutTcc:output_type -> google.protobuf.Empty - 2, // 29: examples.Busi.TransInTccNested:output_type -> google.protobuf.Empty - 2, // 30: examples.Busi.TransInBSaga:output_type -> google.protobuf.Empty - 2, // 31: examples.Busi.TransOutBSaga:output_type -> google.protobuf.Empty - 2, // 32: examples.Busi.TransInRevertBSaga:output_type -> google.protobuf.Empty - 2, // 33: examples.Busi.TransOutRevertBSaga:output_type -> google.protobuf.Empty - 17, // [17:34] is the sub-list for method output_type - 0, // [0:17] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_examples_busi_proto_init() } -func file_examples_busi_proto_init() { - if File_examples_busi_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_examples_busi_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BusiReq); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_examples_busi_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BusiReply); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_examples_busi_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_examples_busi_proto_goTypes, - DependencyIndexes: file_examples_busi_proto_depIdxs, - MessageInfos: file_examples_busi_proto_msgTypes, - }.Build() - File_examples_busi_proto = out.File - file_examples_busi_proto_rawDesc = nil - file_examples_busi_proto_goTypes = nil - file_examples_busi_proto_depIdxs = nil -} diff --git a/examples/data.go b/examples/data.go deleted file mode 100644 index c865ba7..0000000 --- a/examples/data.go +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2021 yedf. All rights reserved. - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - */ - -package examples - -import ( - "fmt" - - "github.com/dtm-labs/dtm/common" - "github.com/dtm-labs/dtm/dtmcli/logger" -) - -var config = &common.Config - -func resetXaData() { - if config.ExamplesDB.Driver != "mysql" { - return - } - - db := dbGet() - type XaRow struct { - Data string - } - xas := []XaRow{} - db.Must().Raw("xa recover").Scan(&xas) - for _, xa := range xas { - db.Must().Exec(fmt.Sprintf("xa rollback '%s'", xa.Data)) - } -} - -// PopulateDB populate example mysql data -func PopulateDB(skipDrop bool) { - resetXaData() - file := fmt.Sprintf("%s/examples.%s.sql", common.GetSqlDir(), config.ExamplesDB.Driver) - common.RunSQLScript(config.ExamplesDB, file, skipDrop) - file = fmt.Sprintf("%s/dtmcli.barrier.%s.sql", common.GetSqlDir(), config.ExamplesDB.Driver) - common.RunSQLScript(config.ExamplesDB, file, skipDrop) -} - -type sampleInfo struct { - Arg string - Action func() string - Desc string -} - -// Samples 所有的示例都会注册到这里 -var Samples = map[string]*sampleInfo{} - -func addSample(name string, fn func() string) { - logger.FatalfIf(Samples[name] != nil, "%s already exists", name) - Samples[name] = &sampleInfo{Arg: name, Action: fn} -} diff --git a/examples/grpc_msg.go b/examples/grpc_msg.go deleted file mode 100644 index 5e89058..0000000 --- a/examples/grpc_msg.go +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2021 yedf. All rights reserved. - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - */ - -package examples - -import ( - "github.com/dtm-labs/dtm/dtmcli/logger" - dtmgrpc "github.com/dtm-labs/dtm/dtmgrpc" -) - -func init() { - addSample("grpc_msg", func() string { - req := &BusiReq{Amount: 30} - gid := dtmgrpc.MustGenGid(DtmGrpcServer) - msg := dtmgrpc.NewMsgGrpc(DtmGrpcServer, gid). - Add(BusiGrpc+"/examples.Busi/TransOut", req). - Add(BusiGrpc+"/examples.Busi/TransIn", req) - err := msg.Submit() - logger.FatalIfError(err) - return msg.Gid - }) -} diff --git a/examples/grpc_saga.go b/examples/grpc_saga.go deleted file mode 100644 index eb2c6b0..0000000 --- a/examples/grpc_saga.go +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2021 yedf. All rights reserved. - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - */ - -package examples - -import ( - "github.com/dtm-labs/dtm/dtmcli/logger" - dtmgrpc "github.com/dtm-labs/dtm/dtmgrpc" -) - -func init() { - addSample("grpc_saga", func() string { - req := &BusiReq{Amount: 30} - gid := dtmgrpc.MustGenGid(DtmGrpcServer) - saga := dtmgrpc.NewSagaGrpc(DtmGrpcServer, gid). - Add(BusiGrpc+"/examples.Busi/TransOut", BusiGrpc+"/examples.Busi/TransOutRevert", req). - Add(BusiGrpc+"/examples.Busi/TransIn", BusiGrpc+"/examples.Busi/TransInRevert", req) - err := saga.Submit() - logger.FatalIfError(err) - return saga.Gid - }) - addSample("grpc_saga_wait", func() string { - req := &BusiReq{Amount: 30} - gid := dtmgrpc.MustGenGid(DtmGrpcServer) - saga := dtmgrpc.NewSagaGrpc(DtmGrpcServer, gid). - Add(BusiGrpc+"/examples.Busi/TransOut", BusiGrpc+"/examples.Busi/TransOutRevert", req). - Add(BusiGrpc+"/examples.Busi/TransIn", BusiGrpc+"/examples.Busi/TransInRevert", req) - saga.WaitResult = true - err := saga.Submit() - logger.FatalIfError(err) - return saga.Gid - }) -} diff --git a/examples/grpc_saga_barrier.go b/examples/grpc_saga_barrier.go deleted file mode 100644 index d838181..0000000 --- a/examples/grpc_saga_barrier.go +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2021 yedf. All rights reserved. - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - */ - -package examples - -import ( - "context" - "database/sql" - - "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/dtmgrpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - emptypb "google.golang.org/protobuf/types/known/emptypb" -) - -func init() { - addSample("grpc_saga_barrier", func() string { - req := &BusiReq{Amount: 30} - gid := dtmgrpc.MustGenGid(DtmGrpcServer) - saga := dtmgrpc.NewSagaGrpc(DtmGrpcServer, gid). - Add(BusiGrpc+"/examples.Busi/TransOutBSaga", BusiGrpc+"/examples.Busi/TransOutRevertBSaga", req). - Add(BusiGrpc+"/examples.Busi/TransInBSaga", BusiGrpc+"/examples.Busi/TransInRevertBSaga", req) - err := saga.Submit() - logger.FatalIfError(err) - return saga.Gid - }) -} - -func sagaGrpcBarrierAdjustBalance(db dtmcli.DB, uid int, amount int64, result string) error { - if result == dtmcli.ResultFailure { - return status.New(codes.Aborted, dtmcli.ResultFailure).Err() - } - _, err := dtmimp.DBExec(db, "update dtm_busi.user_account set balance = balance + ? where user_id = ?", amount, uid) - return err - -} - -func (s *busiServer) TransInBSaga(ctx context.Context, in *BusiReq) (*emptypb.Empty, error) { - barrier := MustBarrierFromGrpc(ctx) - return &emptypb.Empty{}, barrier.Call(txGet(), func(tx *sql.Tx) error { - return sagaGrpcBarrierAdjustBalance(tx, 2, in.Amount, in.TransInResult) - }) -} - -func (s *busiServer) TransOutBSaga(ctx context.Context, in *BusiReq) (*emptypb.Empty, error) { - barrier := MustBarrierFromGrpc(ctx) - return &emptypb.Empty{}, barrier.Call(txGet(), func(tx *sql.Tx) error { - return sagaGrpcBarrierAdjustBalance(tx, 1, -in.Amount, in.TransOutResult) - }) -} - -func (s *busiServer) TransInRevertBSaga(ctx context.Context, in *BusiReq) (*emptypb.Empty, error) { - barrier := MustBarrierFromGrpc(ctx) - return &emptypb.Empty{}, barrier.Call(txGet(), func(tx *sql.Tx) error { - return sagaGrpcBarrierAdjustBalance(tx, 2, -in.Amount, "") - }) -} - -func (s *busiServer) TransOutRevertBSaga(ctx context.Context, in *BusiReq) (*emptypb.Empty, error) { - barrier := MustBarrierFromGrpc(ctx) - return &emptypb.Empty{}, barrier.Call(txGet(), func(tx *sql.Tx) error { - return sagaGrpcBarrierAdjustBalance(tx, 1, in.Amount, "") - }) -} diff --git a/examples/grpc_tcc.go b/examples/grpc_tcc.go deleted file mode 100644 index 411a3e8..0000000 --- a/examples/grpc_tcc.go +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2021 yedf. All rights reserved. - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - */ - -package examples - -import ( - "github.com/dtm-labs/dtm/dtmcli/logger" - dtmgrpc "github.com/dtm-labs/dtm/dtmgrpc" - emptypb "google.golang.org/protobuf/types/known/emptypb" -) - -func init() { - addSample("grpc_tcc", func() string { - logger.Debugf("tcc simple transaction begin") - gid := dtmgrpc.MustGenGid(DtmGrpcServer) - err := dtmgrpc.TccGlobalTransaction(DtmGrpcServer, gid, func(tcc *dtmgrpc.TccGrpc) error { - data := &BusiReq{Amount: 30} - r := &emptypb.Empty{} - err := tcc.CallBranch(data, BusiGrpc+"/examples.Busi/TransOutTcc", BusiGrpc+"/examples.Busi/TransOutConfirm", BusiGrpc+"/examples.Busi/TransOutRevert", r) - if err != nil { - return err - } - err = tcc.CallBranch(data, BusiGrpc+"/examples.Busi/TransInTcc", BusiGrpc+"/examples.Busi/TransInConfirm", BusiGrpc+"/examples.Busi/TransInRevert", r) - return err - }) - logger.FatalIfError(err) - return gid - }) -} diff --git a/examples/grpc_xa.go b/examples/grpc_xa.go deleted file mode 100644 index c55e953..0000000 --- a/examples/grpc_xa.go +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2021 yedf. All rights reserved. - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - */ - -package examples - -import ( - context "context" - - "github.com/dtm-labs/dtm/dtmcli/logger" - "github.com/dtm-labs/dtm/dtmgrpc" - "google.golang.org/protobuf/types/known/emptypb" -) - -func init() { - addSample("grpc_xa", func() string { - gid := dtmgrpc.MustGenGid(DtmGrpcServer) - req := &BusiReq{Amount: 30} - err := XaGrpcClient.XaGlobalTransaction(gid, func(xa *dtmgrpc.XaGrpc) error { - r := &emptypb.Empty{} - err := xa.CallBranch(req, BusiGrpc+"/examples.Busi/TransOutXa", r) - if err != nil { - return err - } - err = xa.CallBranch(req, BusiGrpc+"/examples.Busi/TransInXa", r) - return err - }) - logger.FatalIfError(err) - return gid - }) -} - -func (s *busiServer) XaNotify(ctx context.Context, in *emptypb.Empty) (*emptypb.Empty, error) { - return XaGrpcClient.HandleCallback(ctx) -} diff --git a/examples/http_gorm_xa.go b/examples/http_gorm_xa.go deleted file mode 100644 index b77e7dd..0000000 --- a/examples/http_gorm_xa.go +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2021 yedf. All rights reserved. - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - */ - -package examples - -import ( - "github.com/dtm-labs/dtm/dtmcli" - "github.com/dtm-labs/dtm/dtmcli/logger" - "github.com/go-resty/resty/v2" -) - -func init() { - addSample("xa_gorm", func() string { - gid := dtmcli.MustGenGid(DtmHttpServer) - err := XaClient.XaGlobalTransaction(gid, func(xa *dtmcli.Xa) (*resty.Response, error) { - resp, err := xa.CallBranch(&TransReq{Amount: 30}, Busi+"/TransOutXaGorm") - if err != nil { - return resp, err - } - return xa.CallBranch(&TransReq{Amount: 30}, Busi+"/TransInXa") - }) - logger.FatalIfError(err) - return gid - }) - -} diff --git a/examples/http_msg.go b/examples/http_msg.go deleted file mode 100644 index 34bbc82..0000000 --- a/examples/http_msg.go +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2021 yedf. All rights reserved. - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - */ - -package examples - -import ( - "github.com/dtm-labs/dtm/dtmcli" - "github.com/dtm-labs/dtm/dtmcli/logger" -) - -func init() { - addSample("msg", func() string { - logger.Debugf("a busi transaction begin") - req := &TransReq{Amount: 30} - msg := dtmcli.NewMsg(DtmHttpServer, dtmcli.MustGenGid(DtmHttpServer)). - Add(Busi+"/TransOut", req). - Add(Busi+"/TransIn", req) - err := msg.Prepare(Busi + "/query") - logger.FatalIfError(err) - logger.Debugf("busi trans submit") - err = msg.Submit() - logger.FatalIfError(err) - return msg.Gid - }) -} diff --git a/examples/http_saga.go b/examples/http_saga.go deleted file mode 100644 index 398f045..0000000 --- a/examples/http_saga.go +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2021 yedf. All rights reserved. - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - */ - -package examples - -import ( - "github.com/dtm-labs/dtm/dtmcli" - "github.com/dtm-labs/dtm/dtmcli/logger" -) - -func init() { - addSample("saga", func() string { - logger.Debugf("a saga busi transaction begin") - req := &TransReq{Amount: 30} - saga := dtmcli.NewSaga(DtmHttpServer, dtmcli.MustGenGid(DtmHttpServer)). - Add(Busi+"/TransOut", Busi+"/TransOutRevert", req). - Add(Busi+"/TransIn", Busi+"/TransInRevert", req) - logger.Debugf("saga busi trans submit") - err := saga.Submit() - logger.Debugf("result gid is: %s", saga.Gid) - logger.FatalIfError(err) - return saga.Gid - }) - addSample("saga_wait", func() string { - logger.Debugf("a saga busi transaction begin") - req := &TransReq{Amount: 30} - saga := dtmcli.NewSaga(DtmHttpServer, dtmcli.MustGenGid(DtmHttpServer)). - Add(Busi+"/TransOut", Busi+"/TransOutRevert", req). - Add(Busi+"/TransIn", Busi+"/TransInRevert", req) - saga.SetOptions(&dtmcli.TransOptions{WaitResult: true}) - err := saga.Submit() - logger.Debugf("result gid is: %s", saga.Gid) - logger.FatalIfError(err) - return saga.Gid - }) - addSample("concurrent_saga", func() string { - logger.Debugf("a concurrent saga busi transaction begin") - req := &TransReq{Amount: 30} - csaga := dtmcli.NewSaga(DtmHttpServer, dtmcli.MustGenGid(DtmHttpServer)). - Add(Busi+"/TransOut", Busi+"/TransOutRevert", req). - Add(Busi+"/TransOut", Busi+"/TransOutRevert", req). - Add(Busi+"/TransIn", Busi+"/TransInRevert", req). - Add(Busi+"/TransIn", Busi+"/TransInRevert", req). - EnableConcurrent(). - AddBranchOrder(2, []int{0, 1}). - AddBranchOrder(3, []int{0, 1}) - logger.Debugf("concurrent saga busi trans submit") - err := csaga.Submit() - logger.Debugf("result gid is: %s", csaga.Gid) - logger.FatalIfError(err) - return csaga.Gid - }) -} diff --git a/examples/http_saga_barrier.go b/examples/http_saga_barrier.go deleted file mode 100644 index 53af51d..0000000 --- a/examples/http_saga_barrier.go +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2021 yedf. All rights reserved. - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - */ - -package examples - -import ( - "database/sql" - - "github.com/dtm-labs/dtm/common" - "github.com/dtm-labs/dtm/dtmcli" - "github.com/dtm-labs/dtm/dtmcli/dtmimp" - "github.com/dtm-labs/dtm/dtmcli/logger" - "github.com/gin-gonic/gin" -) - -func init() { - setupFuncs["SagaBarrierSetup"] = func(app *gin.Engine) { - app.POST(BusiAPI+"/SagaBTransIn", common.WrapHandler(sagaBarrierTransIn)) - app.POST(BusiAPI+"/SagaBTransInCompensate", common.WrapHandler(sagaBarrierTransInCompensate)) - app.POST(BusiAPI+"/SagaBTransOut", common.WrapHandler(sagaBarrierTransOut)) - app.POST(BusiAPI+"/SagaBTransOutCompensate", common.WrapHandler(sagaBarrierTransOutCompensate)) - } - addSample("saga_barrier", func() string { - logger.Debugf("a busi transaction begin") - req := &TransReq{Amount: 30} - saga := dtmcli.NewSaga(DtmHttpServer, dtmcli.MustGenGid(DtmHttpServer)). - Add(Busi+"/SagaBTransOut", Busi+"/SagaBTransOutCompensate", req). - Add(Busi+"/SagaBTransIn", Busi+"/SagaBTransInCompensate", req) - logger.Debugf("busi trans submit") - err := saga.Submit() - logger.FatalIfError(err) - return saga.Gid - }) -} - -func sagaBarrierAdjustBalance(db dtmcli.DB, uid int, amount int) error { - _, err := dtmimp.DBExec(db, "update dtm_busi.user_account set balance = balance + ? where user_id = ?", amount, uid) - return err - -} - -func sagaBarrierTransIn(c *gin.Context) (interface{}, error) { - req := reqFrom(c) - if req.TransInResult != "" { - return req.TransInResult, nil - } - barrier := MustBarrierFromGin(c) - return dtmcli.MapSuccess, barrier.Call(txGet(), func(tx *sql.Tx) error { - return sagaBarrierAdjustBalance(tx, 1, req.Amount) - }) -} - -func sagaBarrierTransInCompensate(c *gin.Context) (interface{}, error) { - barrier := MustBarrierFromGin(c) - return dtmcli.MapSuccess, barrier.Call(txGet(), func(tx *sql.Tx) error { - return sagaBarrierAdjustBalance(tx, 1, -reqFrom(c).Amount) - }) -} - -func sagaBarrierTransOut(c *gin.Context) (interface{}, error) { - req := reqFrom(c) - if req.TransOutResult != "" { - return req.TransOutResult, nil - } - barrier := MustBarrierFromGin(c) - return dtmcli.MapSuccess, barrier.Call(txGet(), func(tx *sql.Tx) error { - return sagaBarrierAdjustBalance(tx, 2, -req.Amount) - }) -} - -func sagaBarrierTransOutCompensate(c *gin.Context) (interface{}, error) { - barrier := MustBarrierFromGin(c) - return dtmcli.MapSuccess, barrier.Call(txGet(), func(tx *sql.Tx) error { - return sagaBarrierAdjustBalance(tx, 2, reqFrom(c).Amount) - }) -} diff --git a/examples/http_saga_gorm_barrier.go b/examples/http_saga_gorm_barrier.go deleted file mode 100644 index 0eda05e..0000000 --- a/examples/http_saga_gorm_barrier.go +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2021 yedf. All rights reserved. - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - */ - -package examples - -import ( - "database/sql" - - "github.com/dtm-labs/dtm/common" - "github.com/dtm-labs/dtm/dtmcli" - "github.com/dtm-labs/dtm/dtmcli/logger" - "github.com/gin-gonic/gin" -) - -func init() { - setupFuncs["SagaGormBarrierSetup"] = func(app *gin.Engine) { - app.POST(BusiAPI+"/SagaBTransOutGorm", common.WrapHandler(sagaGormBarrierTransOut)) - } - addSample("saga_gorm_barrier", func() string { - logger.Debugf("a busi transaction begin") - req := &TransReq{Amount: 30} - saga := dtmcli.NewSaga(DtmHttpServer, dtmcli.MustGenGid(DtmHttpServer)). - Add(Busi+"/SagaBTransOutGorm", Busi+"/SagaBTransOutCompensate", req). - Add(Busi+"/SagaBTransIn", Busi+"/SagaBTransInCompensate", req) - logger.Debugf("busi trans submit") - err := saga.Submit() - logger.FatalIfError(err) - return saga.Gid - }) - -} - -func sagaGormBarrierTransOut(c *gin.Context) (interface{}, error) { - req := reqFrom(c) - barrier := MustBarrierFromGin(c) - tx := dbGet().DB.Begin() - return dtmcli.MapSuccess, barrier.Call(tx.Statement.ConnPool.(*sql.Tx), func(tx1 *sql.Tx) error { - return tx.Exec("update dtm_busi.user_account set balance = balance + ? where user_id = ?", -req.Amount, 2).Error - }) -} diff --git a/examples/http_tcc.go b/examples/http_tcc.go deleted file mode 100644 index 3055d44..0000000 --- a/examples/http_tcc.go +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2021 yedf. All rights reserved. - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - */ - -package examples - -import ( - "github.com/dtm-labs/dtm/common" - "github.com/dtm-labs/dtm/dtmcli" - "github.com/dtm-labs/dtm/dtmcli/logger" - "github.com/gin-gonic/gin" - "github.com/go-resty/resty/v2" -) - -func init() { - setupFuncs["TccSetupSetup"] = func(app *gin.Engine) { - app.POST(BusiAPI+"/TransInTccParent", common.WrapHandler(func(c *gin.Context) (interface{}, error) { - tcc, err := dtmcli.TccFromQuery(c.Request.URL.Query()) - logger.FatalIfError(err) - logger.Debugf("TransInTccParent ") - return tcc.CallBranch(&TransReq{Amount: reqFrom(c).Amount}, Busi+"/TransIn", Busi+"/TransInConfirm", Busi+"/TransInRevert") - })) - } - addSample("tcc_nested", func() string { - gid := dtmcli.MustGenGid(DtmHttpServer) - err := dtmcli.TccGlobalTransaction(DtmHttpServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { - resp, err := tcc.CallBranch(&TransReq{Amount: 30}, Busi+"/TransOut", Busi+"/TransOutConfirm", Busi+"/TransOutRevert") - if err != nil { - return resp, err - } - return tcc.CallBranch(&TransReq{Amount: 30}, Busi+"/TransInTccParent", Busi+"/TransInConfirm", Busi+"/TransInRevert") - }) - logger.FatalIfError(err) - return gid - }) - addSample("tcc", func() string { - logger.Debugf("tcc simple transaction begin") - gid := dtmcli.MustGenGid(DtmHttpServer) - err := dtmcli.TccGlobalTransaction(DtmHttpServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { - resp, err := tcc.CallBranch(&TransReq{Amount: 30}, Busi+"/TransOut", Busi+"/TransOutConfirm", Busi+"/TransOutRevert") - if err != nil { - return resp, err - } - return tcc.CallBranch(&TransReq{Amount: 30}, Busi+"/TransIn", Busi+"/TransInConfirm", Busi+"/TransInRevert") - }) - logger.FatalIfError(err) - return gid - }) -} diff --git a/examples/http_tcc_barrier.go b/examples/http_tcc_barrier.go deleted file mode 100644 index 70b018a..0000000 --- a/examples/http_tcc_barrier.go +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2021 yedf. All rights reserved. - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - */ - -package examples - -import ( - "database/sql" - "fmt" - - "github.com/dtm-labs/dtm/common" - "github.com/dtm-labs/dtm/dtmcli" - "github.com/dtm-labs/dtm/dtmcli/dtmimp" - "github.com/dtm-labs/dtm/dtmcli/logger" - "github.com/gin-gonic/gin" - "github.com/go-resty/resty/v2" -) - -func init() { - setupFuncs["TccBarrierSetup"] = func(app *gin.Engine) { - app.POST(BusiAPI+"/TccBTransInTry", common.WrapHandler(tccBarrierTransInTry)) - app.POST(BusiAPI+"/TccBTransInConfirm", common.WrapHandler(tccBarrierTransInConfirm)) - app.POST(BusiAPI+"/TccBTransInCancel", common.WrapHandler(tccBarrierTransInCancel)) - app.POST(BusiAPI+"/TccBTransOutTry", common.WrapHandler(tccBarrierTransOutTry)) - app.POST(BusiAPI+"/TccBTransOutConfirm", common.WrapHandler(tccBarrierTransOutConfirm)) - app.POST(BusiAPI+"/TccBTransOutCancel", common.WrapHandler(TccBarrierTransOutCancel)) - } - addSample("tcc_barrier", func() string { - logger.Debugf("tcc transaction begin") - gid := dtmcli.MustGenGid(DtmHttpServer) - err := dtmcli.TccGlobalTransaction(DtmHttpServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { - resp, err := tcc.CallBranch(&TransReq{Amount: 30}, Busi+"/TccBTransOutTry", - Busi+"/TccBTransOutConfirm", Busi+"/TccBTransOutCancel") - if err != nil { - return resp, err - } - return tcc.CallBranch(&TransReq{Amount: 30}, Busi+"/TccBTransInTry", Busi+"/TccBTransInConfirm", Busi+"/TccBTransInCancel") - }) - logger.FatalIfError(err) - return gid - }) -} - -const transInUID = 1 -const transOutUID = 2 - -func adjustTrading(db dtmcli.DB, uid int, amount int) error { - affected, err := dtmimp.DBExec(db, `update dtm_busi.user_account set trading_balance=trading_balance+? - where user_id=? and trading_balance + ? + balance >= 0`, amount, uid, amount) - if err == nil && affected == 0 { - return fmt.Errorf("update error, maybe balance not enough") - } - return err -} - -func adjustBalance(db dtmcli.DB, uid int, amount int) error { - affected, err := dtmimp.DBExec(db, `update dtm_busi.user_account set trading_balance=trading_balance-?, - balance=balance+? where user_id=?`, amount, amount, uid) - if err == nil && affected == 0 { - return fmt.Errorf("update user_account 0 rows") - } - return err -} - -// TCC下,转入 -func tccBarrierTransInTry(c *gin.Context) (interface{}, error) { - req := reqFrom(c) // 去重构一下,改成可以重复使用的输入 - if req.TransInResult != "" { - return req.TransInResult, nil - } - return dtmcli.MapSuccess, MustBarrierFromGin(c).Call(txGet(), func(tx *sql.Tx) error { - return adjustTrading(tx, transInUID, req.Amount) - }) -} - -func tccBarrierTransInConfirm(c *gin.Context) (interface{}, error) { - return dtmcli.MapSuccess, MustBarrierFromGin(c).Call(txGet(), func(tx *sql.Tx) error { - return adjustBalance(tx, transInUID, reqFrom(c).Amount) - }) -} - -func tccBarrierTransInCancel(c *gin.Context) (interface{}, error) { - return dtmcli.MapSuccess, MustBarrierFromGin(c).Call(txGet(), func(tx *sql.Tx) error { - return adjustTrading(tx, transInUID, -reqFrom(c).Amount) - }) -} - -func tccBarrierTransOutTry(c *gin.Context) (interface{}, error) { - req := reqFrom(c) - if req.TransOutResult != "" { - return req.TransOutResult, nil - } - return dtmcli.MapSuccess, MustBarrierFromGin(c).Call(txGet(), func(tx *sql.Tx) error { - return adjustTrading(tx, transOutUID, -req.Amount) - }) -} - -func tccBarrierTransOutConfirm(c *gin.Context) (interface{}, error) { - return dtmcli.MapSuccess, MustBarrierFromGin(c).Call(txGet(), func(tx *sql.Tx) error { - return adjustBalance(tx, transOutUID, -reqFrom(c).Amount) - }) -} - -// TccBarrierTransOutCancel will be use in test -func TccBarrierTransOutCancel(c *gin.Context) (interface{}, error) { - return dtmcli.MapSuccess, MustBarrierFromGin(c).Call(txGet(), func(tx *sql.Tx) error { - return adjustTrading(tx, transOutUID, reqFrom(c).Amount) - }) -} diff --git a/examples/http_xa.go b/examples/http_xa.go deleted file mode 100644 index 6ba6f2d..0000000 --- a/examples/http_xa.go +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2021 yedf. All rights reserved. - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - */ - -package examples - -import ( - "github.com/dtm-labs/dtm/common" - "github.com/dtm-labs/dtm/dtmcli" - "github.com/dtm-labs/dtm/dtmcli/logger" - "github.com/gin-gonic/gin" - "github.com/go-resty/resty/v2" -) - -// XaClient XA client connection -var XaClient *dtmcli.XaClient = nil - -func init() { - setupFuncs["XaSetup"] = func(app *gin.Engine) { - var err error - XaClient, err = dtmcli.NewXaClient(DtmHttpServer, config.ExamplesDB, Busi+"/xa", func(path string, xa *dtmcli.XaClient) { - app.POST(path, common.WrapHandler(func(c *gin.Context) (interface{}, error) { - return xa.HandleCallback(c.Query("gid"), c.Query("branch_id"), c.Query("op")) - })) - }) - logger.FatalIfError(err) - } - addSample("xa", func() string { - gid := dtmcli.MustGenGid(DtmHttpServer) - err := XaClient.XaGlobalTransaction(gid, func(xa *dtmcli.Xa) (*resty.Response, error) { - resp, err := xa.CallBranch(&TransReq{Amount: 30}, Busi+"/TransOutXa") - if err != nil { - return resp, err - } - return xa.CallBranch(&TransReq{Amount: 30}, Busi+"/TransInXa") - }) - logger.FatalIfError(err) - return gid - }) -} diff --git a/go.mod b/go.mod index 778bc7a..9c897a0 100644 --- a/go.mod +++ b/go.mod @@ -32,6 +32,7 @@ require ( gorm.io/driver/mysql v1.0.3 gorm.io/driver/postgres v1.2.1 gorm.io/gorm v1.22.2 + honnef.co/go/tools v0.0.1-2020.1.3 // gotest.tools v2.2.0+incompatible ) diff --git a/go.sum b/go.sum index 2c9c5a0..09eb829 100644 --- a/go.sum +++ b/go.sum @@ -877,6 +877,7 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.20.12 h1:LfRpmRkJLwPP8eaYehsVVmIIfg1yCBIIUHaSsdqCgHA= k8s.io/api v0.20.12/go.mod h1:A2brwyEkVLM3wQGNnzoAa5JsQRzHK0uoOQ+bsnv7V68= diff --git a/helper/test-cover.sh b/helper/test-cover.sh index c462626..ca14aa6 100644 --- a/helper/test-cover.sh +++ b/helper/test-cover.sh @@ -2,7 +2,7 @@ set -x echo "" > coverage.txt for store in redis mysql boltdb; do for d in $(go list ./... | grep -v vendor); do - TEST_STORE=$store go test -covermode count -coverprofile=profile.out -coverpkg=github.com/dtm-labs/dtm/common,github.com/dtm-labs/dtm/dtmcli,github.com/dtm-labs/dtm/dtmcli/dtmimp,github.com/dtm-labs/dtm/dtmgrpc,github.com/dtm-labs/dtm/dtmgrpc/dtmgimp,github.com/dtm-labs/dtm/dtmsvr,github.com/dtm-labs/dtm/dtmsvr/storage,github.com/dtm-labs/dtm/dtmsvr/storage/boltdb,github.com/dtm-labs/dtm/dtmsvr/storage/redis,github.com/dtm-labs/dtm/dtmsvr/storage/registry,github.com/dtm-labs/dtm/dtmsvr/storage/sql,github.com/dtm-labs/dtm/dtmsvr/storage/boltdb,github.com/dtm-labs/dtm/dtmsvr/storage/registry -gcflags=-l $d + TEST_STORE=$store go test -covermode count -coverprofile=profile.out -coverpkg=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/dtmgrpc,github.com/dtm-labs/dtm/dtmgrpc/dtmgimp,github.com/dtm-labs/dtm/dtmsvr,github.com/dtm-labs/dtm/dtmsvr/config,github.com/dtm-labs/dtm/dtmsvr/storage,github.com/dtm-labs/dtm/dtmsvr/storage/boltdb,github.com/dtm-labs/dtm/dtmsvr/storage/redis,github.com/dtm-labs/dtm/dtmsvr/storage/registry,github.com/dtm-labs/dtm/dtmsvr/storage/sql,github.com/dtm-labs/dtm/dtmutil -gcflags=-l $d if [ -f profile.out ]; then cat profile.out >> coverage.txt echo > profile.out diff --git a/main.go b/main.go new file mode 100644 index 0000000..4308f4a --- /dev/null +++ b/main.go @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021 yedf. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + */ + +package main + +import ( + "flag" + "fmt" + "os" + "path/filepath" + + "go.uber.org/automaxprocs/maxprocs" + + "github.com/dtm-labs/dtm/dtmcli/logger" + "github.com/dtm-labs/dtm/dtmsvr" + "github.com/dtm-labs/dtm/dtmsvr/config" + "github.com/dtm-labs/dtm/dtmsvr/storage/registry" + + // load the microserver driver + _ "github.com/dtm-labs/dtmdriver-gozero" + _ "github.com/dtm-labs/dtmdriver-polaris" + _ "github.com/dtm-labs/dtmdriver-protocol1" +) + +var Version, Commit, Date string + +func version() { + if Version == "" { + Version = "0.0.0-dev" + Commit = "NA" + Date = "NA" + } + if len(Commit) > 8 { + Commit = Commit[:8] + } + fmt.Printf("version: %s commit: %s built at: %s\n", Version, Commit, Date) +} + +func usage() { + cmd := filepath.Base(os.Args[0]) + s := "Usage: %s [options]\n\n" + fmt.Fprintf(os.Stderr, s, cmd) + flag.PrintDefaults() +} + +var isVersion = flag.Bool("v", false, "Show the version of dtm.") +var isDebug = flag.Bool("d", false, "Set log level to debug.") +var isHelp = flag.Bool("h", false, "Show the help information about etcd.") +var confFile = flag.String("c", "", "Path to the server configuration file.") + +func main() { + flag.Parse() + if flag.NArg() > 0 || *isHelp { + usage() + return + } else if *isVersion { + version() + return + } + config.MustLoadConfig(*confFile) + if *isDebug { + config.Config.LogLevel = "debug" + } + maxprocs.Set(maxprocs.Logger(logger.Infof)) + registry.WaitStoreUp() + dtmsvr.StartSvr() // 启动dtmsvr的api服务 + go dtmsvr.CronExpiredTrans(-1) // 启动dtmsvr的定时过期查询 + select {} +} diff --git a/qs/main.go b/qs/main.go new file mode 100644 index 0000000..f31d83a --- /dev/null +++ b/qs/main.go @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021 yedf. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + */ + +package main + +import ( + "time" + + "github.com/dtm-labs/dtm/test/busi" +) + +func main() { + busi.QsStartSvr() + busi.QsFireRequest() + time.Sleep(1 * time.Second) +} diff --git a/sqls/examples.mysql.sql b/sqls/busi.mysql.sql similarity index 100% rename from sqls/examples.mysql.sql rename to sqls/busi.mysql.sql diff --git a/sqls/examples.postgres.sql b/sqls/busi.postgres.sql similarity index 100% rename from sqls/examples.postgres.sql rename to sqls/busi.postgres.sql diff --git a/test/api_test.go b/test/api_test.go index 5997a58..92d3058 100644 --- a/test/api_test.go +++ b/test/api_test.go @@ -11,7 +11,7 @@ import ( "testing" "github.com/dtm-labs/dtm/dtmcli/dtmimp" - "github.com/dtm-labs/dtm/examples" + "github.com/dtm-labs/dtm/dtmutil" "github.com/stretchr/testify/assert" ) @@ -20,7 +20,7 @@ func TestAPIQuery(t *testing.T) { err := genMsg(gid).Submit() assert.Nil(t, err) waitTransProcessed(gid) - resp, err := dtmimp.RestyClient.R().SetQueryParam("gid", gid).Get(examples.DtmHttpServer + "/query") + resp, err := dtmimp.RestyClient.R().SetQueryParam("gid", gid).Get(dtmutil.DefaultHttpServer + "/query") assert.Nil(t, err) m := map[string]interface{}{} assert.Equal(t, resp.StatusCode(), 200) @@ -28,11 +28,11 @@ func TestAPIQuery(t *testing.T) { assert.NotEqual(t, nil, m["transaction"]) assert.Equal(t, 2, len(m["branches"].([]interface{}))) - resp, err = dtmimp.RestyClient.R().SetQueryParam("gid", "").Get(examples.DtmHttpServer + "/query") + resp, err = dtmimp.RestyClient.R().SetQueryParam("gid", "").Get(dtmutil.DefaultHttpServer + "/query") e2p(err) assert.Equal(t, resp.StatusCode(), 500) - resp, err = dtmimp.RestyClient.R().SetQueryParam("gid", "1").Get(examples.DtmHttpServer + "/query") + resp, err = dtmimp.RestyClient.R().SetQueryParam("gid", "1").Get(dtmutil.DefaultHttpServer + "/query") e2p(err) assert.Equal(t, resp.StatusCode(), 200) dtmimp.MustUnmarshalString(resp.String(), &m) @@ -47,7 +47,7 @@ func TestAPIAll(t *testing.T) { assert.Nil(t, err) waitTransProcessed(gid) } - resp, err := dtmimp.RestyClient.R().SetQueryParam("limit", "1").Get(examples.DtmHttpServer + "/all") + resp, err := dtmimp.RestyClient.R().SetQueryParam("limit", "1").Get(dtmutil.DefaultHttpServer + "/all") assert.Nil(t, err) m := map[string]interface{}{} dtmimp.MustUnmarshalString(resp.String(), &m) @@ -57,7 +57,7 @@ func TestAPIAll(t *testing.T) { resp, err = dtmimp.RestyClient.R().SetQueryParams(map[string]string{ "limit": "1", "position": nextPos, - }).Get(examples.DtmHttpServer + "/all") + }).Get(dtmutil.DefaultHttpServer + "/all") assert.Nil(t, err) dtmimp.MustUnmarshalString(resp.String(), &m) nextPos2 := m["next_position"].(string) @@ -67,7 +67,7 @@ func TestAPIAll(t *testing.T) { resp, err = dtmimp.RestyClient.R().SetQueryParams(map[string]string{ "limit": "1000", "position": nextPos, - }).Get(examples.DtmHttpServer + "/all") + }).Get(dtmutil.DefaultHttpServer + "/all") assert.Nil(t, err) dtmimp.MustUnmarshalString(resp.String(), &m) nextPos3 := m["next_position"].(string) diff --git a/test/base_test.go b/test/base_test.go index 3748802..b33bfd8 100644 --- a/test/base_test.go +++ b/test/base_test.go @@ -11,17 +11,17 @@ import ( "fmt" "testing" - "github.com/dtm-labs/dtm/common" "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/examples" + "github.com/dtm-labs/dtm/dtmutil" + "github.com/dtm-labs/dtm/test/busi" "github.com/stretchr/testify/assert" ) // BarrierModel barrier model for gorm type BarrierModel struct { - common.ModelBase + dtmutil.ModelBase dtmcli.BranchBarrier } @@ -30,7 +30,7 @@ func (BarrierModel) TableName() string { return "dtm_barrier.barrier" } func TestBaseSqlDB(t *testing.T) { asserts := assert.New(t) - db := common.DbGet(config.ExamplesDB) + db := dtmutil.DbGet(busi.BusiConf) barrier := &dtmcli.BranchBarrier{ TransType: "saga", Gid: "gid2", @@ -60,10 +60,10 @@ func TestBaseSqlDB(t *testing.T) { } func TestBaseHttp(t *testing.T) { - resp, err := dtmimp.RestyClient.R().SetQueryParam("panic_string", "1").Post(examples.Busi + "/TestPanic") + resp, err := dtmimp.RestyClient.R().SetQueryParam("panic_string", "1").Post(busi.Busi + "/TestPanic") assert.Nil(t, err) assert.Contains(t, resp.String(), "panic_string") - resp, err = dtmimp.RestyClient.R().SetQueryParam("panic_error", "1").Post(examples.Busi + "/TestPanic") + resp, err = dtmimp.RestyClient.R().SetQueryParam("panic_error", "1").Post(busi.Busi + "/TestPanic") assert.Nil(t, err) assert.Contains(t, resp.String(), "panic_error") } diff --git a/test/busi/barrier.go b/test/busi/barrier.go new file mode 100644 index 0000000..df30145 --- /dev/null +++ b/test/busi/barrier.go @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2021 yedf. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + */ + +package busi + +import ( + "context" + "database/sql" + + "github.com/dtm-labs/dtm/dtmcli" + "github.com/dtm-labs/dtm/dtmutil" + "github.com/gin-gonic/gin" + emptypb "google.golang.org/protobuf/types/known/emptypb" +) + +func init() { + setupFuncs["TccBarrierSetup"] = func(app *gin.Engine) { + app.POST(BusiAPI+"/SagaBTransIn", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { + barrier := MustBarrierFromGin(c) + return dtmcli.MapSuccess, barrier.Call(txGet(), func(tx *sql.Tx) error { + return sagaAdjustBalance(tx, transInUID, reqFrom(c).Amount, reqFrom(c).TransInResult) + }) + })) + app.POST(BusiAPI+"/SagaBTransInCompensate", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { + barrier := MustBarrierFromGin(c) + return dtmcli.MapSuccess, barrier.Call(txGet(), func(tx *sql.Tx) error { + return sagaAdjustBalance(tx, transInUID, -reqFrom(c).Amount, "") + }) + })) + app.POST(BusiAPI+"/SagaBTransOut", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { + barrier := MustBarrierFromGin(c) + return dtmcli.MapSuccess, barrier.Call(txGet(), func(tx *sql.Tx) error { + return sagaAdjustBalance(tx, transOutUID, -reqFrom(c).Amount, reqFrom(c).TransOutResult) + }) + })) + app.POST(BusiAPI+"/SagaBTransOutCompensate", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { + barrier := MustBarrierFromGin(c) + return dtmcli.MapSuccess, barrier.Call(txGet(), func(tx *sql.Tx) error { + return sagaAdjustBalance(tx, transOutUID, reqFrom(c).Amount, "") + }) + })) + app.POST(BusiAPI+"/SagaBTransOutGorm", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { + req := reqFrom(c) + barrier := MustBarrierFromGin(c) + tx := dbGet().DB.Begin() + return dtmcli.MapSuccess, barrier.Call(tx.Statement.ConnPool.(*sql.Tx), func(tx1 *sql.Tx) error { + return tx.Exec("update dtm_busi.user_account set balance = balance + ? where user_id = ?", -req.Amount, transOutUID).Error + }) + })) + + app.POST(BusiAPI+"/TccBTransInTry", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { + req := reqFrom(c) // 去重构一下,改成可以重复使用的输入 + if req.TransInResult != "" { + return req.TransInResult, nil + } + return dtmcli.MapSuccess, MustBarrierFromGin(c).Call(txGet(), func(tx *sql.Tx) error { + return tccAdjustTrading(tx, transInUID, req.Amount) + }) + })) + app.POST(BusiAPI+"/TccBTransInConfirm", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { + return dtmcli.MapSuccess, MustBarrierFromGin(c).Call(txGet(), func(tx *sql.Tx) error { + return tccAdjustBalance(tx, transInUID, reqFrom(c).Amount) + }) + })) + app.POST(BusiAPI+"/TccBTransInCancel", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { + return dtmcli.MapSuccess, MustBarrierFromGin(c).Call(txGet(), func(tx *sql.Tx) error { + return tccAdjustTrading(tx, transInUID, -reqFrom(c).Amount) + }) + })) + app.POST(BusiAPI+"/TccBTransOutTry", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { + req := reqFrom(c) + if req.TransOutResult != "" { + return req.TransOutResult, nil + } + return dtmcli.MapSuccess, MustBarrierFromGin(c).Call(txGet(), func(tx *sql.Tx) error { + return tccAdjustTrading(tx, transOutUID, -req.Amount) + }) + })) + app.POST(BusiAPI+"/TccBTransOutConfirm", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { + return dtmcli.MapSuccess, MustBarrierFromGin(c).Call(txGet(), func(tx *sql.Tx) error { + return tccAdjustBalance(tx, transOutUID, -reqFrom(c).Amount) + }) + })) + app.POST(BusiAPI+"/TccBTransOutCancel", dtmutil.WrapHandler(TccBarrierTransOutCancel)) + } +} + +// TccBarrierTransOutCancel will be use in test +func TccBarrierTransOutCancel(c *gin.Context) (interface{}, error) { + return dtmcli.MapSuccess, MustBarrierFromGin(c).Call(txGet(), func(tx *sql.Tx) error { + return tccAdjustTrading(tx, transOutUID, reqFrom(c).Amount) + }) +} + +func (s *busiServer) TransInBSaga(ctx context.Context, in *BusiReq) (*emptypb.Empty, error) { + barrier := MustBarrierFromGrpc(ctx) + return &emptypb.Empty{}, barrier.Call(txGet(), func(tx *sql.Tx) error { + return sagaGrpcAdjustBalance(tx, transInUID, in.Amount, in.TransInResult) + }) +} + +func (s *busiServer) TransOutBSaga(ctx context.Context, in *BusiReq) (*emptypb.Empty, error) { + barrier := MustBarrierFromGrpc(ctx) + return &emptypb.Empty{}, barrier.Call(txGet(), func(tx *sql.Tx) error { + return sagaGrpcAdjustBalance(tx, transOutUID, -in.Amount, in.TransOutResult) + }) +} + +func (s *busiServer) TransInRevertBSaga(ctx context.Context, in *BusiReq) (*emptypb.Empty, error) { + barrier := MustBarrierFromGrpc(ctx) + return &emptypb.Empty{}, barrier.Call(txGet(), func(tx *sql.Tx) error { + return sagaGrpcAdjustBalance(tx, transInUID, -in.Amount, "") + }) +} + +func (s *busiServer) TransOutRevertBSaga(ctx context.Context, in *BusiReq) (*emptypb.Empty, error) { + barrier := MustBarrierFromGrpc(ctx) + return &emptypb.Empty{}, barrier.Call(txGet(), func(tx *sql.Tx) error { + return sagaGrpcAdjustBalance(tx, transOutUID, in.Amount, "") + }) +} diff --git a/examples/base_grpc.go b/test/busi/base_grpc.go similarity index 71% rename from examples/base_grpc.go rename to test/busi/base_grpc.go index 38cda95..dcfca4e 100644 --- a/examples/base_grpc.go +++ b/test/busi/base_grpc.go @@ -4,26 +4,23 @@ * license that can be found in the LICENSE file. */ -package examples +package busi import ( "context" "database/sql" "fmt" "net" - "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/dtmgrpc" + "github.com/dtm-labs/dtm/dtmutil" "github.com/gin-gonic/gin" "github.com/dtm-labs/dtm/dtmgrpc/dtmgimp" "github.com/dtm-labs/dtm/dtmgrpc/dtmgpb" grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" emptypb "google.golang.org/protobuf/types/known/emptypb" ) @@ -38,13 +35,13 @@ var XaGrpcClient *dtmgrpc.XaGrpcClient = nil func init() { setupFuncs["XaGrpcSetup"] = func(app *gin.Engine) { - XaGrpcClient = dtmgrpc.NewXaGrpcClient(DtmGrpcServer, config.ExamplesDB, BusiGrpc+"/examples.Busi/XaNotify") + XaGrpcClient = dtmgrpc.NewXaGrpcClient(dtmutil.DefaultGrpcServer, BusiConf, BusiGrpc+"/busi.Busi/XaNotify") } } // GrpcStartup for grpc func GrpcStartup() { - conn, err := grpc.Dial(DtmGrpcServer, grpc.WithInsecure(), grpc.WithUnaryInterceptor(dtmgimp.GrpcClientLog)) + conn, err := grpc.Dial(dtmutil.DefaultGrpcServer, grpc.WithInsecure(), grpc.WithUnaryInterceptor(dtmgimp.GrpcClientLog)) logger.FatalIfError(err) DtmClient = dtmgpb.NewDtmClient(conn) logger.Debugf("dtm client inited") @@ -58,23 +55,9 @@ func GrpcStartup() { err := s.Serve(lis) logger.FatalIfError(err) }() - time.Sleep(100 * time.Millisecond) -} - -func handleGrpcBusiness(in *BusiReq, result1 string, result2 string, busi string) error { - res := dtmimp.OrString(result1, result2, dtmcli.ResultSuccess) - logger.Debugf("grpc busi %s %v %s %s result: %s", busi, in, result1, result2, res) - if res == dtmcli.ResultSuccess { - return nil - } else if res == dtmcli.ResultFailure { - return status.New(codes.Aborted, dtmcli.ResultFailure).Err() - } else if res == dtmcli.ResultOngoing { - return status.New(codes.Aborted, dtmcli.ResultOngoing).Err() - } - return status.New(codes.Internal, fmt.Sprintf("unknow result %s", res)).Err() } -// busiServer is used to implement examples.BusiServer. +// busiServer is used to implement busi.BusiServer. type busiServer struct { UnimplementedBusiServer } @@ -118,21 +101,13 @@ func (s *busiServer) TransOutTcc(ctx context.Context, in *BusiReq) (*emptypb.Emp func (s *busiServer) TransInXa(ctx context.Context, in *BusiReq) (*emptypb.Empty, error) { return &emptypb.Empty{}, XaGrpcClient.XaLocalTransaction(ctx, in, func(db *sql.DB, xa *dtmgrpc.XaGrpc) error { - if in.TransInResult == dtmcli.ResultFailure { - return status.New(codes.Aborted, dtmcli.ResultFailure).Err() - } - _, err := dtmimp.DBExec(db, "update dtm_busi.user_account set balance=balance+? where user_id=?", in.Amount, 2) - return err + return sagaGrpcAdjustBalance(db, transInUID, in.Amount, in.TransInResult) }) } func (s *busiServer) TransOutXa(ctx context.Context, in *BusiReq) (*emptypb.Empty, error) { return &emptypb.Empty{}, XaGrpcClient.XaLocalTransaction(ctx, in, func(db *sql.DB, xa *dtmgrpc.XaGrpc) error { - if in.TransOutResult == dtmcli.ResultFailure { - return status.New(codes.Aborted, dtmcli.ResultFailure).Err() - } - _, err := dtmimp.DBExec(db, "update dtm_busi.user_account set balance=balance-? where user_id=?", in.Amount, 1) - return err + return sagaGrpcAdjustBalance(db, transOutUID, in.Amount, in.TransOutResult) }) } @@ -140,7 +115,11 @@ func (s *busiServer) TransInTccNested(ctx context.Context, in *BusiReq) (*emptyp tcc, err := dtmgrpc.TccFromGrpc(ctx) logger.FatalIfError(err) r := &emptypb.Empty{} - err = tcc.CallBranch(in, BusiGrpc+"/examples.Busi/TransIn", BusiGrpc+"/examples.Busi/TransInConfirm", BusiGrpc+"/examples.Busi/TransInRevert", r) + err = tcc.CallBranch(in, BusiGrpc+"/busi.Busi/TransIn", BusiGrpc+"/busi.Busi/TransInConfirm", BusiGrpc+"/busi.Busi/TransInRevert", r) logger.FatalIfError(err) return r, handleGrpcBusiness(in, MainSwitch.TransInResult.Fetch(), in.TransInResult, dtmimp.GetFuncName()) } + +func (s *busiServer) XaNotify(ctx context.Context, in *emptypb.Empty) (*emptypb.Empty, error) { + return XaGrpcClient.HandleCallback(ctx) +} diff --git a/examples/base_http.go b/test/busi/base_http.go similarity index 53% rename from examples/base_http.go rename to test/busi/base_http.go index cad5834..4518d0e 100644 --- a/examples/base_http.go +++ b/test/busi/base_http.go @@ -4,19 +4,17 @@ * license that can be found in the LICENSE file. */ -package examples +package busi import ( "database/sql" "errors" "fmt" - "strings" - "time" - "github.com/dtm-labs/dtm/common" "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/dtmutil" "github.com/gin-gonic/gin" "gorm.io/driver/mysql" "gorm.io/driver/postgres" @@ -39,10 +37,20 @@ var setupFuncs = map[string]setupFunc{} // Busi busi service url prefix var Busi string = fmt.Sprintf("http://localhost:%d%s", BusiPort, BusiAPI) +var XaClient *dtmcli.XaClient = nil + +type SleepCancelHandler func(c *gin.Context) (interface{}, error) + +var sleepCancelHandler SleepCancelHandler = nil + +func SetSleepCancelHandler(handler SleepCancelHandler) { + sleepCancelHandler = handler +} + // BaseAppStartup base app startup func BaseAppStartup() *gin.Engine { - logger.Debugf("examples starting") - app := common.GetGinApp() + logger.Infof("examples starting") + app := dtmutil.GetGinApp() app.Use(func(c *gin.Context) { v := MainSwitch.NextResult.Fetch() if v != "" { @@ -52,6 +60,13 @@ func BaseAppStartup() *gin.Engine { } c.Next() }) + var err error + XaClient, err = dtmcli.NewXaClient(dtmutil.DefaultHttpServer, BusiConf, Busi+"/xa", func(path string, xa *dtmcli.XaClient) { + app.POST(path, dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { + return xa.HandleCallback(c.Query("gid"), c.Query("branch_id"), c.Query("op")) + })) + }) + logger.FatalIfError(err) BaseAddRoute(app) for k, v := range setupFuncs { @@ -61,107 +76,53 @@ func BaseAppStartup() *gin.Engine { logger.Debugf("Starting busi at: %d", BusiPort) go app.Run(fmt.Sprintf(":%d", BusiPort)) - time.Sleep(100 * time.Millisecond) return app } -// AutoEmptyString auto reset to empty when used once -type AutoEmptyString struct { - value string -} - -// SetOnce set a value once -func (s *AutoEmptyString) SetOnce(v string) { - s.value = v -} - -// Fetch fetch the stored value, then reset the value to empty -func (s *AutoEmptyString) Fetch() string { - v := s.value - s.value = "" - return v -} - -type mainSwitchType struct { - TransInResult AutoEmptyString - TransOutResult AutoEmptyString - TransInConfirmResult AutoEmptyString - TransOutConfirmResult AutoEmptyString - TransInRevertResult AutoEmptyString - TransOutRevertResult AutoEmptyString - CanSubmitResult AutoEmptyString - NextResult AutoEmptyString -} - -// MainSwitch controls busi success or fail -var MainSwitch mainSwitchType - -func handleGeneralBusiness(c *gin.Context, result1 string, result2 string, busi string) (interface{}, error) { - info := infoFromContext(c) - res := dtmimp.OrString(result1, result2, dtmcli.ResultSuccess) - logger.Debugf("%s %s result: %s", busi, info.String(), res) - if res == "ERROR" { - return nil, errors.New("ERROR from user") - } - return map[string]interface{}{"dtm_result": res}, nil -} - -func error2Resp(err error) (interface{}, error) { - if err != nil { - s := err.Error() - if strings.Contains(s, dtmcli.ResultFailure) || strings.Contains(s, dtmcli.ResultOngoing) { - return gin.H{"dtm_result": s}, nil - } - } - return nil, err -} - // BaseAddRoute add base route handler func BaseAddRoute(app *gin.Engine) { - app.POST(BusiAPI+"/TransIn", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + app.POST(BusiAPI+"/TransIn", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { return handleGeneralBusiness(c, MainSwitch.TransInResult.Fetch(), reqFrom(c).TransInResult, "transIn") })) - app.POST(BusiAPI+"/TransOut", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + app.POST(BusiAPI+"/TransOut", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { return handleGeneralBusiness(c, MainSwitch.TransOutResult.Fetch(), reqFrom(c).TransOutResult, "TransOut") })) - app.POST(BusiAPI+"/TransInConfirm", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + app.POST(BusiAPI+"/TransInConfirm", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { return handleGeneralBusiness(c, MainSwitch.TransInConfirmResult.Fetch(), "", "TransInConfirm") })) - app.POST(BusiAPI+"/TransOutConfirm", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + app.POST(BusiAPI+"/TransOutConfirm", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { return handleGeneralBusiness(c, MainSwitch.TransOutConfirmResult.Fetch(), "", "TransOutConfirm") })) - app.POST(BusiAPI+"/TransInRevert", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + app.POST(BusiAPI+"/TransInRevert", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { return handleGeneralBusiness(c, MainSwitch.TransInRevertResult.Fetch(), "", "TransInRevert") })) - app.POST(BusiAPI+"/TransOutRevert", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + app.POST(BusiAPI+"/TransOutRevert", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { return handleGeneralBusiness(c, MainSwitch.TransOutRevertResult.Fetch(), "", "TransOutRevert") })) - app.GET(BusiAPI+"/CanSubmit", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + app.GET(BusiAPI+"/CanSubmit", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { logger.Debugf("%s CanSubmit", c.Query("gid")) return dtmimp.OrString(MainSwitch.CanSubmitResult.Fetch(), dtmcli.ResultSuccess), nil })) - app.POST(BusiAPI+"/TransInXa", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + app.POST(BusiAPI+"/TransInXa", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { err := XaClient.XaLocalTransaction(c.Request.URL.Query(), func(db *sql.DB, xa *dtmcli.Xa) error { - if reqFrom(c).TransInResult == dtmcli.ResultFailure { - return dtmcli.ErrFailure - } - _, err := dtmimp.DBExec(db, "update dtm_busi.user_account set balance=balance+? where user_id=?", reqFrom(c).Amount, 2) - return err + return sagaAdjustBalance(db, transInUID, reqFrom(c).Amount, reqFrom(c).TransInResult) }) return error2Resp(err) })) - app.POST(BusiAPI+"/TransOutXa", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + app.POST(BusiAPI+"/TransOutXa", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { err := XaClient.XaLocalTransaction(c.Request.URL.Query(), func(db *sql.DB, xa *dtmcli.Xa) error { - if reqFrom(c).TransOutResult == dtmcli.ResultFailure { - return dtmcli.ErrFailure - } - _, err := dtmimp.DBExec(db, "update dtm_busi.user_account set balance=balance-? where user_id=?", reqFrom(c).Amount, 1) - return err + return sagaAdjustBalance(db, transOutUID, reqFrom(c).Amount, reqFrom(c).TransOutResult) }) return error2Resp(err) })) - app.POST(BusiAPI+"/TransOutXaGorm", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + app.POST(BusiAPI+"/TransInTccParent", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { + tcc, err := dtmcli.TccFromQuery(c.Request.URL.Query()) + logger.FatalIfError(err) + logger.Debugf("TransInTccParent ") + return tcc.CallBranch(&TransReq{Amount: reqFrom(c).Amount}, Busi+"/TransIn", Busi+"/TransInConfirm", Busi+"/TransInRevert") + })) + app.POST(BusiAPI+"/TransOutXaGorm", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { err := XaClient.XaLocalTransaction(c.Request.URL.Query(), func(db *sql.DB, xa *dtmcli.Xa) error { if reqFrom(c).TransOutResult == dtmcli.ResultFailure { return dtmcli.ErrFailure @@ -176,13 +137,13 @@ func BaseAddRoute(app *gin.Engine) { if err != nil { return err } - dbr := gdb.Exec("update dtm_busi.user_account set balance=balance-? where user_id=?", reqFrom(c).Amount, 1) + dbr := gdb.Exec("update dtm_busi.user_account set balance=balance-? where user_id=?", reqFrom(c).Amount, transOutUID) return dbr.Error }) return error2Resp(err) })) - app.POST(BusiAPI+"/TestPanic", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + app.POST(BusiAPI+"/TestPanic", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { if c.Query("panic_error") != "" { panic(errors.New("panic_error")) } else if c.Query("panic_string") != "" { @@ -190,4 +151,7 @@ func BaseAddRoute(app *gin.Engine) { } return "SUCCESS", nil })) + app.POST(BusiAPI+"/TccBSleepCancel", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { + return sleepCancelHandler(c) + })) } diff --git a/examples/base_types.go b/test/busi/base_types.go similarity index 52% rename from examples/base_types.go rename to test/busi/base_types.go index f7a4392..471bbe3 100644 --- a/examples/base_types.go +++ b/test/busi/base_types.go @@ -4,32 +4,50 @@ * license that can be found in the LICENSE file. */ -package examples +package busi import ( - "context" - "database/sql" "fmt" - "github.com/dtm-labs/dtm/common" "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/dtmgrpc" "github.com/gin-gonic/gin" ) -// DtmHttpServer dtm service address -var DtmHttpServer = fmt.Sprintf("http://localhost:%d/api/dtmsvr", 36789) +var BusiConf = dtmcli.DBConf{ + Driver: "mysql", + Host: "localhost", + Port: 3306, + User: "root", +} -// DtmGrpcServer dtm grpc service address -var DtmGrpcServer = fmt.Sprintf("localhost:%d", 36790) +type UserAccount struct { + UserId int + Balance string + TradingBalance string +} + +func (*UserAccount) TableName() string { + return "dtm_busi.user_account" +} + +func GetUserAccountByUid(uid int) *UserAccount { + ua := UserAccount{} + dbr := dbGet().Must().Model(&ua).Where("user_id=?", uid).First(&ua) + dtmimp.E2P(dbr.Error) + return &ua +} + +func IsEqual(ua1, ua2 *UserAccount) bool { + return ua1.UserId == ua2.UserId && ua1.Balance == ua2.Balance && ua1.TradingBalance == ua2.TradingBalance +} // TransReq transaction request payload type TransReq struct { Amount int `json:"amount"` - TransInResult string `json:"transInResult"` - TransOutResult string `json:"transOutResult"` + TransInResult string `json:"trans_in_result"` + TransOutResult string `json:"trans_out_Result"` } func (t *TransReq) String() string { @@ -76,33 +94,33 @@ func infoFromContext(c *gin.Context) *dtmcli.BranchBarrier { return &info } -func dbGet() *common.DB { - return common.DbGet(config.ExamplesDB) +// AutoEmptyString auto reset to empty when used once +type AutoEmptyString struct { + value string } -func sdbGet() *sql.DB { - db, err := dtmimp.PooledDB(config.ExamplesDB) - logger.FatalIfError(err) - return db +// SetOnce set a value once +func (s *AutoEmptyString) SetOnce(v string) { + s.value = v } -func txGet() *sql.Tx { - db := sdbGet() - tx, err := db.Begin() - logger.FatalIfError(err) - return tx +// Fetch fetch the stored value, then reset the value to empty +func (s *AutoEmptyString) Fetch() string { + v := s.value + s.value = "" + return v } -// MustBarrierFromGin 1 -func MustBarrierFromGin(c *gin.Context) *dtmcli.BranchBarrier { - ti, err := dtmcli.BarrierFromQuery(c.Request.URL.Query()) - logger.FatalIfError(err) - return ti +type mainSwitchType struct { + TransInResult AutoEmptyString + TransOutResult AutoEmptyString + TransInConfirmResult AutoEmptyString + TransOutConfirmResult AutoEmptyString + TransInRevertResult AutoEmptyString + TransOutRevertResult AutoEmptyString + CanSubmitResult AutoEmptyString + NextResult AutoEmptyString } -// MustBarrierFromGrpc 1 -func MustBarrierFromGrpc(ctx context.Context) *dtmcli.BranchBarrier { - ti, err := dtmgrpc.BarrierFromGrpc(ctx) - logger.FatalIfError(err) - return ti -} +// MainSwitch controls busi success or fail +var MainSwitch mainSwitchType diff --git a/test/busi/busi.go b/test/busi/busi.go new file mode 100644 index 0000000..13eb7e8 --- /dev/null +++ b/test/busi/busi.go @@ -0,0 +1,85 @@ +package busi + +import ( + "errors" + "fmt" + "strings" + + "github.com/dtm-labs/dtm/dtmcli" + "github.com/dtm-labs/dtm/dtmcli/dtmimp" + "github.com/dtm-labs/dtm/dtmcli/logger" + "github.com/gin-gonic/gin" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +const transOutUID = 1 +const transInUID = 2 + +func handleGrpcBusiness(in *BusiReq, result1 string, result2 string, busi string) error { + res := dtmimp.OrString(result1, result2, dtmcli.ResultSuccess) + logger.Debugf("grpc busi %s %v %s %s result: %s", busi, in, result1, result2, res) + if res == dtmcli.ResultSuccess { + return nil + } else if res == dtmcli.ResultFailure { + return status.New(codes.Aborted, dtmcli.ResultFailure).Err() + } else if res == dtmcli.ResultOngoing { + return status.New(codes.Aborted, dtmcli.ResultOngoing).Err() + } + return status.New(codes.Internal, fmt.Sprintf("unknow result %s", res)).Err() +} + +func handleGeneralBusiness(c *gin.Context, result1 string, result2 string, busi string) (interface{}, error) { + info := infoFromContext(c) + res := dtmimp.OrString(result1, result2, dtmcli.ResultSuccess) + logger.Debugf("%s %s result: %s", busi, info.String(), res) + if res == "ERROR" { + return nil, errors.New("ERROR from user") + } + return map[string]interface{}{"dtm_result": res}, nil +} + +func error2Resp(err error) (interface{}, error) { + if err != nil { + s := err.Error() + if strings.Contains(s, dtmcli.ResultFailure) || strings.Contains(s, dtmcli.ResultOngoing) { + return gin.H{"dtm_result": s}, nil + } + return nil, err + } + return gin.H{"dtm_result": dtmcli.ResultSuccess}, nil +} + +func sagaGrpcAdjustBalance(db dtmcli.DB, uid int, amount int64, result string) error { + if result == dtmcli.ResultFailure { + return status.New(codes.Aborted, dtmcli.ResultFailure).Err() + } + _, err := dtmimp.DBExec(db, "update dtm_busi.user_account set balance = balance + ? where user_id = ?", amount, uid) + return err + +} + +func sagaAdjustBalance(db dtmcli.DB, uid int, amount int, result string) error { + if strings.Contains(result, dtmcli.ResultFailure) { + return dtmcli.ErrFailure + } + _, err := dtmimp.DBExec(db, "update dtm_busi.user_account set balance = balance + ? where user_id = ?", amount, uid) + return err +} +func tccAdjustTrading(db dtmcli.DB, uid int, amount int) error { + affected, err := dtmimp.DBExec(db, `update dtm_busi.user_account set trading_balance=trading_balance+? + where user_id=? and trading_balance + ? + balance >= 0`, amount, uid, amount) + if err == nil && affected == 0 { + return fmt.Errorf("update error, maybe balance not enough") + } + return err +} + +func tccAdjustBalance(db dtmcli.DB, uid int, amount int) error { + affected, err := dtmimp.DBExec(db, `update dtm_busi.user_account set trading_balance=trading_balance-?, + balance=balance+? where user_id=?`, amount, amount, uid) + if err == nil && affected == 0 { + return fmt.Errorf("update user_account 0 rows") + } + return err +} diff --git a/test/busi/busi.pb.go b/test/busi/busi.pb.go new file mode 100644 index 0000000..fa73c00 --- /dev/null +++ b/test/busi/busi.pb.go @@ -0,0 +1,325 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v3.17.3 +// source: test/busi/busi.proto + +package busi + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + emptypb "google.golang.org/protobuf/types/known/emptypb" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// DtmRequest request sent to dtm server +type BusiReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Amount int64 `protobuf:"varint,1,opt,name=Amount,proto3" json:"Amount,omitempty"` + TransOutResult string `protobuf:"bytes,2,opt,name=TransOutResult,proto3" json:"TransOutResult,omitempty"` + TransInResult string `protobuf:"bytes,3,opt,name=TransInResult,proto3" json:"TransInResult,omitempty"` +} + +func (x *BusiReq) Reset() { + *x = BusiReq{} + if protoimpl.UnsafeEnabled { + mi := &file_test_busi_busi_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BusiReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BusiReq) ProtoMessage() {} + +func (x *BusiReq) ProtoReflect() protoreflect.Message { + mi := &file_test_busi_busi_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BusiReq.ProtoReflect.Descriptor instead. +func (*BusiReq) Descriptor() ([]byte, []int) { + return file_test_busi_busi_proto_rawDescGZIP(), []int{0} +} + +func (x *BusiReq) GetAmount() int64 { + if x != nil { + return x.Amount + } + return 0 +} + +func (x *BusiReq) GetTransOutResult() string { + if x != nil { + return x.TransOutResult + } + return "" +} + +func (x *BusiReq) GetTransInResult() string { + if x != nil { + return x.TransInResult + } + return "" +} + +type BusiReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *BusiReply) Reset() { + *x = BusiReply{} + if protoimpl.UnsafeEnabled { + mi := &file_test_busi_busi_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BusiReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BusiReply) ProtoMessage() {} + +func (x *BusiReply) ProtoReflect() protoreflect.Message { + mi := &file_test_busi_busi_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BusiReply.ProtoReflect.Descriptor instead. +func (*BusiReply) Descriptor() ([]byte, []int) { + return file_test_busi_busi_proto_rawDescGZIP(), []int{1} +} + +func (x *BusiReply) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +var File_test_busi_busi_proto protoreflect.FileDescriptor + +var file_test_busi_busi_proto_rawDesc = []byte{ + 0x0a, 0x14, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x62, 0x75, 0x73, 0x69, 0x2f, 0x62, 0x75, 0x73, 0x69, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x62, 0x75, 0x73, 0x69, 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, 0x6f, 0x0a, 0x07, 0x42, 0x75, 0x73, + 0x69, 0x52, 0x65, 0x71, 0x12, 0x16, 0x0a, 0x06, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x26, 0x0a, 0x0e, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x75, 0x74, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x49, 0x6e, 0x52, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x49, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x25, 0x0a, 0x09, 0x42, 0x75, + 0x73, 0x69, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x32, 0xd3, 0x07, 0x0a, 0x04, 0x42, 0x75, 0x73, 0x69, 0x12, 0x2d, 0x0a, 0x09, 0x43, 0x61, + 0x6e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x12, 0x0d, 0x2e, 0x62, 0x75, 0x73, 0x69, 0x2e, 0x42, + 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x62, 0x75, 0x73, 0x69, 0x2e, 0x42, 0x75, + 0x73, 0x69, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x32, 0x0a, 0x07, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x49, 0x6e, 0x12, 0x0d, 0x2e, 0x62, 0x75, 0x73, 0x69, 0x2e, 0x42, 0x75, 0x73, 0x69, + 0x52, 0x65, 0x71, 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, 0x33, 0x0a, + 0x08, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x75, 0x74, 0x12, 0x0d, 0x2e, 0x62, 0x75, 0x73, 0x69, + 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x0d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x49, 0x6e, 0x52, 0x65, 0x76, + 0x65, 0x72, 0x74, 0x12, 0x0d, 0x2e, 0x62, 0x75, 0x73, 0x69, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, + 0x65, 0x71, 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, 0x39, 0x0a, 0x0e, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x76, 0x65, 0x72, 0x74, 0x12, 0x0d, + 0x2e, 0x62, 0x75, 0x73, 0x69, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x39, 0x0a, 0x0e, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x49, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x12, 0x0d, 0x2e, 0x62, 0x75, 0x73, 0x69, + 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x3a, 0x0a, 0x0f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x75, 0x74, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x12, 0x0d, 0x2e, 0x62, 0x75, 0x73, 0x69, 0x2e, 0x42, 0x75, 0x73, + 0x69, 0x52, 0x65, 0x71, 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, 0x3c, + 0x0a, 0x08, 0x58, 0x61, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 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, 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, 0x34, 0x0a, 0x09, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x49, 0x6e, 0x58, 0x61, 0x12, 0x0d, 0x2e, 0x62, 0x75, 0x73, 0x69, + 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x35, 0x0a, 0x0a, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x75, 0x74, 0x58, 0x61, + 0x12, 0x0d, 0x2e, 0x62, 0x75, 0x73, 0x69, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x35, 0x0a, 0x0a, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x49, 0x6e, 0x54, 0x63, 0x63, 0x12, 0x0d, 0x2e, 0x62, 0x75, 0x73, 0x69, 0x2e, 0x42, + 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x0b, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x75, 0x74, 0x54, 0x63, 0x63, 0x12, + 0x0d, 0x2e, 0x62, 0x75, 0x73, 0x69, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x3b, 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x49, 0x6e, 0x54, 0x63, 0x63, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x0d, 0x2e, 0x62, + 0x75, 0x73, 0x69, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x37, 0x0a, 0x0c, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x49, 0x6e, + 0x42, 0x53, 0x61, 0x67, 0x61, 0x12, 0x0d, 0x2e, 0x62, 0x75, 0x73, 0x69, 0x2e, 0x42, 0x75, 0x73, + 0x69, 0x52, 0x65, 0x71, 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, 0x0d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x75, 0x74, 0x42, 0x53, 0x61, 0x67, 0x61, 0x12, + 0x0d, 0x2e, 0x62, 0x75, 0x73, 0x69, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x3d, 0x0a, 0x12, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x49, 0x6e, 0x52, 0x65, 0x76, 0x65, 0x72, 0x74, 0x42, 0x53, 0x61, 0x67, 0x61, 0x12, 0x0d, + 0x2e, 0x62, 0x75, 0x73, 0x69, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x3e, 0x0a, 0x13, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x4f, 0x75, 0x74, 0x52, 0x65, 0x76, 0x65, 0x72, 0x74, 0x42, 0x53, 0x61, 0x67, 0x61, 0x12, 0x0d, + 0x2e, 0x62, 0x75, 0x73, 0x69, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x62, 0x75, 0x73, + 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_test_busi_busi_proto_rawDescOnce sync.Once + file_test_busi_busi_proto_rawDescData = file_test_busi_busi_proto_rawDesc +) + +func file_test_busi_busi_proto_rawDescGZIP() []byte { + file_test_busi_busi_proto_rawDescOnce.Do(func() { + file_test_busi_busi_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_busi_busi_proto_rawDescData) + }) + return file_test_busi_busi_proto_rawDescData +} + +var file_test_busi_busi_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_test_busi_busi_proto_goTypes = []interface{}{ + (*BusiReq)(nil), // 0: busi.BusiReq + (*BusiReply)(nil), // 1: busi.BusiReply + (*emptypb.Empty)(nil), // 2: google.protobuf.Empty +} +var file_test_busi_busi_proto_depIdxs = []int32{ + 0, // 0: busi.Busi.CanSubmit:input_type -> busi.BusiReq + 0, // 1: busi.Busi.TransIn:input_type -> busi.BusiReq + 0, // 2: busi.Busi.TransOut:input_type -> busi.BusiReq + 0, // 3: busi.Busi.TransInRevert:input_type -> busi.BusiReq + 0, // 4: busi.Busi.TransOutRevert:input_type -> busi.BusiReq + 0, // 5: busi.Busi.TransInConfirm:input_type -> busi.BusiReq + 0, // 6: busi.Busi.TransOutConfirm:input_type -> busi.BusiReq + 2, // 7: busi.Busi.XaNotify:input_type -> google.protobuf.Empty + 0, // 8: busi.Busi.TransInXa:input_type -> busi.BusiReq + 0, // 9: busi.Busi.TransOutXa:input_type -> busi.BusiReq + 0, // 10: busi.Busi.TransInTcc:input_type -> busi.BusiReq + 0, // 11: busi.Busi.TransOutTcc:input_type -> busi.BusiReq + 0, // 12: busi.Busi.TransInTccNested:input_type -> busi.BusiReq + 0, // 13: busi.Busi.TransInBSaga:input_type -> busi.BusiReq + 0, // 14: busi.Busi.TransOutBSaga:input_type -> busi.BusiReq + 0, // 15: busi.Busi.TransInRevertBSaga:input_type -> busi.BusiReq + 0, // 16: busi.Busi.TransOutRevertBSaga:input_type -> busi.BusiReq + 1, // 17: busi.Busi.CanSubmit:output_type -> busi.BusiReply + 2, // 18: busi.Busi.TransIn:output_type -> google.protobuf.Empty + 2, // 19: busi.Busi.TransOut:output_type -> google.protobuf.Empty + 2, // 20: busi.Busi.TransInRevert:output_type -> google.protobuf.Empty + 2, // 21: busi.Busi.TransOutRevert:output_type -> google.protobuf.Empty + 2, // 22: busi.Busi.TransInConfirm:output_type -> google.protobuf.Empty + 2, // 23: busi.Busi.TransOutConfirm:output_type -> google.protobuf.Empty + 2, // 24: busi.Busi.XaNotify:output_type -> google.protobuf.Empty + 2, // 25: busi.Busi.TransInXa:output_type -> google.protobuf.Empty + 2, // 26: busi.Busi.TransOutXa:output_type -> google.protobuf.Empty + 2, // 27: busi.Busi.TransInTcc:output_type -> google.protobuf.Empty + 2, // 28: busi.Busi.TransOutTcc:output_type -> google.protobuf.Empty + 2, // 29: busi.Busi.TransInTccNested:output_type -> google.protobuf.Empty + 2, // 30: busi.Busi.TransInBSaga:output_type -> google.protobuf.Empty + 2, // 31: busi.Busi.TransOutBSaga:output_type -> google.protobuf.Empty + 2, // 32: busi.Busi.TransInRevertBSaga:output_type -> google.protobuf.Empty + 2, // 33: busi.Busi.TransOutRevertBSaga:output_type -> google.protobuf.Empty + 17, // [17:34] is the sub-list for method output_type + 0, // [0:17] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_test_busi_busi_proto_init() } +func file_test_busi_busi_proto_init() { + if File_test_busi_busi_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_test_busi_busi_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BusiReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_busi_busi_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BusiReply); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_test_busi_busi_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_test_busi_busi_proto_goTypes, + DependencyIndexes: file_test_busi_busi_proto_depIdxs, + MessageInfos: file_test_busi_busi_proto_msgTypes, + }.Build() + File_test_busi_busi_proto = out.File + file_test_busi_busi_proto_rawDesc = nil + file_test_busi_busi_proto_goTypes = nil + file_test_busi_busi_proto_depIdxs = nil +} diff --git a/examples/busi.proto b/test/busi/busi.proto similarity index 96% rename from examples/busi.proto rename to test/busi/busi.proto index 8e34fa8..0e421b0 100644 --- a/examples/busi.proto +++ b/test/busi/busi.proto @@ -1,9 +1,9 @@ syntax = "proto3"; -package examples; +package busi; import "google/protobuf/empty.proto"; -option go_package = "./examples"; +option go_package = "./busi"; // DtmRequest request sent to dtm server message BusiReq { diff --git a/examples/busi_grpc.pb.go b/test/busi/busi_grpc.pb.go similarity index 91% rename from examples/busi_grpc.pb.go rename to test/busi/busi_grpc.pb.go index f9e9427..bc612b1 100644 --- a/examples/busi_grpc.pb.go +++ b/test/busi/busi_grpc.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. -package examples +package busi import ( context "context" @@ -48,7 +48,7 @@ func NewBusiClient(cc grpc.ClientConnInterface) BusiClient { func (c *busiClient) CanSubmit(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*BusiReply, error) { out := new(BusiReply) - err := c.cc.Invoke(ctx, "/examples.Busi/CanSubmit", in, out, opts...) + err := c.cc.Invoke(ctx, "/busi.Busi/CanSubmit", in, out, opts...) if err != nil { return nil, err } @@ -57,7 +57,7 @@ func (c *busiClient) CanSubmit(ctx context.Context, in *BusiReq, opts ...grpc.Ca func (c *busiClient) TransIn(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/examples.Busi/TransIn", in, out, opts...) + err := c.cc.Invoke(ctx, "/busi.Busi/TransIn", in, out, opts...) if err != nil { return nil, err } @@ -66,7 +66,7 @@ func (c *busiClient) TransIn(ctx context.Context, in *BusiReq, opts ...grpc.Call func (c *busiClient) TransOut(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/examples.Busi/TransOut", in, out, opts...) + err := c.cc.Invoke(ctx, "/busi.Busi/TransOut", in, out, opts...) if err != nil { return nil, err } @@ -75,7 +75,7 @@ func (c *busiClient) TransOut(ctx context.Context, in *BusiReq, opts ...grpc.Cal func (c *busiClient) TransInRevert(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/examples.Busi/TransInRevert", in, out, opts...) + err := c.cc.Invoke(ctx, "/busi.Busi/TransInRevert", in, out, opts...) if err != nil { return nil, err } @@ -84,7 +84,7 @@ func (c *busiClient) TransInRevert(ctx context.Context, in *BusiReq, opts ...grp func (c *busiClient) TransOutRevert(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/examples.Busi/TransOutRevert", in, out, opts...) + err := c.cc.Invoke(ctx, "/busi.Busi/TransOutRevert", in, out, opts...) if err != nil { return nil, err } @@ -93,7 +93,7 @@ func (c *busiClient) TransOutRevert(ctx context.Context, in *BusiReq, opts ...gr func (c *busiClient) TransInConfirm(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/examples.Busi/TransInConfirm", in, out, opts...) + err := c.cc.Invoke(ctx, "/busi.Busi/TransInConfirm", in, out, opts...) if err != nil { return nil, err } @@ -102,7 +102,7 @@ func (c *busiClient) TransInConfirm(ctx context.Context, in *BusiReq, opts ...gr func (c *busiClient) TransOutConfirm(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/examples.Busi/TransOutConfirm", in, out, opts...) + err := c.cc.Invoke(ctx, "/busi.Busi/TransOutConfirm", in, out, opts...) if err != nil { return nil, err } @@ -111,7 +111,7 @@ func (c *busiClient) TransOutConfirm(ctx context.Context, in *BusiReq, opts ...g func (c *busiClient) XaNotify(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/examples.Busi/XaNotify", in, out, opts...) + err := c.cc.Invoke(ctx, "/busi.Busi/XaNotify", in, out, opts...) if err != nil { return nil, err } @@ -120,7 +120,7 @@ func (c *busiClient) XaNotify(ctx context.Context, in *emptypb.Empty, opts ...gr func (c *busiClient) TransInXa(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/examples.Busi/TransInXa", in, out, opts...) + err := c.cc.Invoke(ctx, "/busi.Busi/TransInXa", in, out, opts...) if err != nil { return nil, err } @@ -129,7 +129,7 @@ func (c *busiClient) TransInXa(ctx context.Context, in *BusiReq, opts ...grpc.Ca func (c *busiClient) TransOutXa(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/examples.Busi/TransOutXa", in, out, opts...) + err := c.cc.Invoke(ctx, "/busi.Busi/TransOutXa", in, out, opts...) if err != nil { return nil, err } @@ -138,7 +138,7 @@ func (c *busiClient) TransOutXa(ctx context.Context, in *BusiReq, opts ...grpc.C func (c *busiClient) TransInTcc(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/examples.Busi/TransInTcc", in, out, opts...) + err := c.cc.Invoke(ctx, "/busi.Busi/TransInTcc", in, out, opts...) if err != nil { return nil, err } @@ -147,7 +147,7 @@ func (c *busiClient) TransInTcc(ctx context.Context, in *BusiReq, opts ...grpc.C func (c *busiClient) TransOutTcc(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/examples.Busi/TransOutTcc", in, out, opts...) + err := c.cc.Invoke(ctx, "/busi.Busi/TransOutTcc", in, out, opts...) if err != nil { return nil, err } @@ -156,7 +156,7 @@ func (c *busiClient) TransOutTcc(ctx context.Context, in *BusiReq, opts ...grpc. func (c *busiClient) TransInTccNested(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/examples.Busi/TransInTccNested", in, out, opts...) + err := c.cc.Invoke(ctx, "/busi.Busi/TransInTccNested", in, out, opts...) if err != nil { return nil, err } @@ -165,7 +165,7 @@ func (c *busiClient) TransInTccNested(ctx context.Context, in *BusiReq, opts ... func (c *busiClient) TransInBSaga(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/examples.Busi/TransInBSaga", in, out, opts...) + err := c.cc.Invoke(ctx, "/busi.Busi/TransInBSaga", in, out, opts...) if err != nil { return nil, err } @@ -174,7 +174,7 @@ func (c *busiClient) TransInBSaga(ctx context.Context, in *BusiReq, opts ...grpc func (c *busiClient) TransOutBSaga(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/examples.Busi/TransOutBSaga", in, out, opts...) + err := c.cc.Invoke(ctx, "/busi.Busi/TransOutBSaga", in, out, opts...) if err != nil { return nil, err } @@ -183,7 +183,7 @@ func (c *busiClient) TransOutBSaga(ctx context.Context, in *BusiReq, opts ...grp func (c *busiClient) TransInRevertBSaga(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/examples.Busi/TransInRevertBSaga", in, out, opts...) + err := c.cc.Invoke(ctx, "/busi.Busi/TransInRevertBSaga", in, out, opts...) if err != nil { return nil, err } @@ -192,7 +192,7 @@ func (c *busiClient) TransInRevertBSaga(ctx context.Context, in *BusiReq, opts . func (c *busiClient) TransOutRevertBSaga(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/examples.Busi/TransOutRevertBSaga", in, out, opts...) + err := c.cc.Invoke(ctx, "/busi.Busi/TransOutRevertBSaga", in, out, opts...) if err != nil { return nil, err } @@ -301,7 +301,7 @@ func _Busi_CanSubmit_Handler(srv interface{}, ctx context.Context, dec func(inte } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/examples.Busi/CanSubmit", + FullMethod: "/busi.Busi/CanSubmit", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(BusiServer).CanSubmit(ctx, req.(*BusiReq)) @@ -319,7 +319,7 @@ func _Busi_TransIn_Handler(srv interface{}, ctx context.Context, dec func(interf } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/examples.Busi/TransIn", + FullMethod: "/busi.Busi/TransIn", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(BusiServer).TransIn(ctx, req.(*BusiReq)) @@ -337,7 +337,7 @@ func _Busi_TransOut_Handler(srv interface{}, ctx context.Context, dec func(inter } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/examples.Busi/TransOut", + FullMethod: "/busi.Busi/TransOut", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(BusiServer).TransOut(ctx, req.(*BusiReq)) @@ -355,7 +355,7 @@ func _Busi_TransInRevert_Handler(srv interface{}, ctx context.Context, dec func( } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/examples.Busi/TransInRevert", + FullMethod: "/busi.Busi/TransInRevert", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(BusiServer).TransInRevert(ctx, req.(*BusiReq)) @@ -373,7 +373,7 @@ func _Busi_TransOutRevert_Handler(srv interface{}, ctx context.Context, dec func } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/examples.Busi/TransOutRevert", + FullMethod: "/busi.Busi/TransOutRevert", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(BusiServer).TransOutRevert(ctx, req.(*BusiReq)) @@ -391,7 +391,7 @@ func _Busi_TransInConfirm_Handler(srv interface{}, ctx context.Context, dec func } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/examples.Busi/TransInConfirm", + FullMethod: "/busi.Busi/TransInConfirm", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(BusiServer).TransInConfirm(ctx, req.(*BusiReq)) @@ -409,7 +409,7 @@ func _Busi_TransOutConfirm_Handler(srv interface{}, ctx context.Context, dec fun } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/examples.Busi/TransOutConfirm", + FullMethod: "/busi.Busi/TransOutConfirm", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(BusiServer).TransOutConfirm(ctx, req.(*BusiReq)) @@ -427,7 +427,7 @@ func _Busi_XaNotify_Handler(srv interface{}, ctx context.Context, dec func(inter } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/examples.Busi/XaNotify", + FullMethod: "/busi.Busi/XaNotify", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(BusiServer).XaNotify(ctx, req.(*emptypb.Empty)) @@ -445,7 +445,7 @@ func _Busi_TransInXa_Handler(srv interface{}, ctx context.Context, dec func(inte } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/examples.Busi/TransInXa", + FullMethod: "/busi.Busi/TransInXa", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(BusiServer).TransInXa(ctx, req.(*BusiReq)) @@ -463,7 +463,7 @@ func _Busi_TransOutXa_Handler(srv interface{}, ctx context.Context, dec func(int } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/examples.Busi/TransOutXa", + FullMethod: "/busi.Busi/TransOutXa", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(BusiServer).TransOutXa(ctx, req.(*BusiReq)) @@ -481,7 +481,7 @@ func _Busi_TransInTcc_Handler(srv interface{}, ctx context.Context, dec func(int } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/examples.Busi/TransInTcc", + FullMethod: "/busi.Busi/TransInTcc", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(BusiServer).TransInTcc(ctx, req.(*BusiReq)) @@ -499,7 +499,7 @@ func _Busi_TransOutTcc_Handler(srv interface{}, ctx context.Context, dec func(in } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/examples.Busi/TransOutTcc", + FullMethod: "/busi.Busi/TransOutTcc", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(BusiServer).TransOutTcc(ctx, req.(*BusiReq)) @@ -517,7 +517,7 @@ func _Busi_TransInTccNested_Handler(srv interface{}, ctx context.Context, dec fu } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/examples.Busi/TransInTccNested", + FullMethod: "/busi.Busi/TransInTccNested", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(BusiServer).TransInTccNested(ctx, req.(*BusiReq)) @@ -535,7 +535,7 @@ func _Busi_TransInBSaga_Handler(srv interface{}, ctx context.Context, dec func(i } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/examples.Busi/TransInBSaga", + FullMethod: "/busi.Busi/TransInBSaga", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(BusiServer).TransInBSaga(ctx, req.(*BusiReq)) @@ -553,7 +553,7 @@ func _Busi_TransOutBSaga_Handler(srv interface{}, ctx context.Context, dec func( } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/examples.Busi/TransOutBSaga", + FullMethod: "/busi.Busi/TransOutBSaga", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(BusiServer).TransOutBSaga(ctx, req.(*BusiReq)) @@ -571,7 +571,7 @@ func _Busi_TransInRevertBSaga_Handler(srv interface{}, ctx context.Context, dec } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/examples.Busi/TransInRevertBSaga", + FullMethod: "/busi.Busi/TransInRevertBSaga", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(BusiServer).TransInRevertBSaga(ctx, req.(*BusiReq)) @@ -589,7 +589,7 @@ func _Busi_TransOutRevertBSaga_Handler(srv interface{}, ctx context.Context, dec } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/examples.Busi/TransOutRevertBSaga", + FullMethod: "/busi.Busi/TransOutRevertBSaga", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(BusiServer).TransOutRevertBSaga(ctx, req.(*BusiReq)) @@ -601,7 +601,7 @@ func _Busi_TransOutRevertBSaga_Handler(srv interface{}, ctx context.Context, dec // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) var Busi_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "examples.Busi", + ServiceName: "busi.Busi", HandlerType: (*BusiServer)(nil), Methods: []grpc.MethodDesc{ { @@ -674,5 +674,5 @@ var Busi_ServiceDesc = grpc.ServiceDesc{ }, }, Streams: []grpc.StreamDesc{}, - Metadata: "examples/busi.proto", + Metadata: "test/busi/busi.proto", } diff --git a/examples/quick_start.go b/test/busi/quick_start.go similarity index 58% rename from examples/quick_start.go rename to test/busi/quick_start.go index 8115c89..3fd9616 100644 --- a/examples/quick_start.go +++ b/test/busi/quick_start.go @@ -4,16 +4,15 @@ * license that can be found in the LICENSE file. */ -package examples +package busi import ( "fmt" "time" - "github.com/dtm-labs/dtm/common" "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/dtmutil" "github.com/gin-gonic/gin" ) @@ -25,20 +24,18 @@ const qsBusiPort = 8082 var qsBusi = fmt.Sprintf("http://localhost:%d%s", qsBusiPort, qsBusiAPI) -// QsStartSvr 1 func QsStartSvr() { - app := common.GetGinApp() + app := dtmutil.GetGinApp() qsAddRoute(app) - logger.Debugf("quick qs examples listening at %d", qsBusiPort) + logger.Infof("quick start examples listening at %d", qsBusiPort) go app.Run(fmt.Sprintf(":%d", qsBusiPort)) time.Sleep(100 * time.Millisecond) } -// QsFireRequest 1 func QsFireRequest() string { req := &gin.H{"amount": 30} // 微服务的载荷 // DtmServer为DTM服务的地址 - saga := dtmcli.NewSaga(DtmHttpServer, dtmcli.MustGenGid(DtmHttpServer)). + saga := dtmcli.NewSaga(dtmutil.DefaultHttpServer, dtmcli.MustGenGid(dtmutil.DefaultHttpServer)). // 添加一个TransOut的子事务,正向操作为url: qsBusi+"/TransOut", 逆向操作为url: qsBusi+"/TransOutCompensate" Add(qsBusi+"/TransOut", qsBusi+"/TransOutCompensate", req). // 添加一个TransIn的子事务,正向操作为url: qsBusi+"/TransOut", 逆向操作为url: qsBusi+"/TransInCompensate" @@ -49,22 +46,21 @@ func QsFireRequest() string { return saga.Gid } -func qsAdjustBalance(uid int, amount int) (interface{}, error) { - _, err := dtmimp.DBExec(sdbGet(), "update dtm_busi.user_account set balance = balance + ? where user_id = ?", amount, uid) - return dtmcli.MapSuccess, err -} - func qsAddRoute(app *gin.Engine) { - app.POST(qsBusiAPI+"/TransIn", common.WrapHandler(func(c *gin.Context) (interface{}, error) { - return qsAdjustBalance(2, 30) + app.POST(qsBusiAPI+"/TransIn", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { + logger.Infof("TransIn") + return dtmcli.MapSuccess, nil })) - app.POST(qsBusiAPI+"/TransInCompensate", common.WrapHandler(func(c *gin.Context) (interface{}, error) { - return qsAdjustBalance(2, -30) + app.POST(qsBusiAPI+"/TransInCompensate", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { + logger.Infof("TransInCompensate") + return dtmcli.MapSuccess, nil })) - app.POST(qsBusiAPI+"/TransOut", common.WrapHandler(func(c *gin.Context) (interface{}, error) { - return qsAdjustBalance(1, -30) + app.POST(qsBusiAPI+"/TransOut", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { + logger.Infof("TransOut") + return dtmcli.MapSuccess, nil })) - app.POST(qsBusiAPI+"/TransOutCompensate", common.WrapHandler(func(c *gin.Context) (interface{}, error) { - return qsAdjustBalance(1, 30) + app.POST(qsBusiAPI+"/TransOutCompensate", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { + logger.Infof("TransOutCompensate") + return dtmcli.MapSuccess, nil })) } diff --git a/test/busi/startup.go b/test/busi/startup.go new file mode 100644 index 0000000..7b85772 --- /dev/null +++ b/test/busi/startup.go @@ -0,0 +1,23 @@ +package busi + +import ( + "fmt" + + "github.com/dtm-labs/dtm/dtmutil" + "github.com/gin-gonic/gin" +) + +// Startup startup the busi's grpc and http service +func Startup() *gin.Engine { + GrpcStartup() + return BaseAppStartup() +} + +// PopulateDB populate example mysql data +func PopulateDB(skipDrop bool) { + resetXaData() + file := fmt.Sprintf("%s/busi.%s.sql", dtmutil.GetSqlDir(), BusiConf.Driver) + dtmutil.RunSQLScript(BusiConf, file, skipDrop) + file = fmt.Sprintf("%s/dtmcli.barrier.%s.sql", dtmutil.GetSqlDir(), BusiConf.Driver) + dtmutil.RunSQLScript(BusiConf, file, skipDrop) +} diff --git a/test/busi/utils.go b/test/busi/utils.go new file mode 100644 index 0000000..2b13712 --- /dev/null +++ b/test/busi/utils.go @@ -0,0 +1,61 @@ +package busi + +import ( + "context" + "database/sql" + "fmt" + + "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/dtmgrpc" + "github.com/dtm-labs/dtm/dtmutil" + "github.com/gin-gonic/gin" +) + +func dbGet() *dtmutil.DB { + return dtmutil.DbGet(BusiConf) +} + +func sdbGet() *sql.DB { + db, err := dtmimp.PooledDB(BusiConf) + logger.FatalIfError(err) + return db +} + +func txGet() *sql.Tx { + db := sdbGet() + tx, err := db.Begin() + logger.FatalIfError(err) + return tx +} + +func resetXaData() { + if BusiConf.Driver != "mysql" { + return + } + + db := dbGet() + type XaRow struct { + Data string + } + xas := []XaRow{} + db.Must().Raw("xa recover").Scan(&xas) + for _, xa := range xas { + db.Must().Exec(fmt.Sprintf("xa rollback '%s'", xa.Data)) + } +} + +// MustBarrierFromGin 1 +func MustBarrierFromGin(c *gin.Context) *dtmcli.BranchBarrier { + ti, err := dtmcli.BarrierFromQuery(c.Request.URL.Query()) + logger.FatalIfError(err) + return ti +} + +// MustBarrierFromGrpc 1 +func MustBarrierFromGrpc(ctx context.Context) *dtmcli.BranchBarrier { + ti, err := dtmgrpc.BarrierFromGrpc(ctx) + logger.FatalIfError(err) + return ti +} diff --git a/test/common_test.go b/test/common_test.go new file mode 100644 index 0000000..3b14e8d --- /dev/null +++ b/test/common_test.go @@ -0,0 +1,38 @@ +package test + +import ( + "testing" + + "github.com/dtm-labs/dtm/dtmcli/dtmimp" + "github.com/dtm-labs/dtm/dtmutil" + "github.com/stretchr/testify/assert" +) + +func TestGeneralDB(t *testing.T) { + if conf.Store.IsDB() { + testSql(t) + testDbAlone(t) + } +} + +func testSql(t *testing.T) { + db := dtmutil.DbGet(conf.Store.GetDBConf()) + err := func() (rerr error) { + defer dtmimp.P2E(&rerr) + db.Must().Exec("select a") + return nil + }() + assert.NotEqual(t, nil, err) +} + +func testDbAlone(t *testing.T) { + db, err := dtmimp.StandaloneDB(conf.Store.GetDBConf()) + assert.Nil(t, err) + _, err = dtmimp.DBExec(db, "select 1") + assert.Equal(t, nil, err) + _, err = dtmimp.DBExec(db, "") + assert.Equal(t, nil, err) + db.Close() + _, err = dtmimp.DBExec(db, "select 1") + assert.NotEqual(t, nil, err) +} diff --git a/test/dtmsvr_test.go b/test/dtmsvr_test.go index b855e79..7af9144 100644 --- a/test/dtmsvr_test.go +++ b/test/dtmsvr_test.go @@ -10,18 +10,16 @@ import ( "testing" "time" - "github.com/dtm-labs/dtm/common" "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" "github.com/dtm-labs/dtm/dtmsvr" - "github.com/dtm-labs/dtm/examples" - "github.com/gin-gonic/gin" + "github.com/dtm-labs/dtm/dtmutil" + "github.com/dtm-labs/dtm/test/busi" "github.com/stretchr/testify/assert" ) -var DtmServer = examples.DtmHttpServer -var Busi = examples.Busi -var app *gin.Engine +var DtmServer = dtmutil.DefaultHttpServer +var Busi = busi.Busi func getTransStatus(gid string) string { return dtmsvr.GetTransGlobal(gid).Status @@ -42,10 +40,10 @@ func assertSucceed(t *testing.T, gid string) { } func TestUpdateBranchAsync(t *testing.T) { - if config.Store.Driver != "mysql" { + if conf.Store.Driver != "mysql" { return } - common.Config.UpdateBranchSync = 0 + conf.UpdateBranchSync = 0 saga := genSaga1(dtmimp.GetFuncName(), false, false) saga.SetOptions(&dtmcli.TransOptions{WaitResult: true}) err := saga.Submit() @@ -54,5 +52,5 @@ func TestUpdateBranchAsync(t *testing.T) { time.Sleep(dtmsvr.UpdateBranchAsyncInterval) assert.Equal(t, []string{StatusPrepared, StatusSucceed}, getBranchesStatus(saga.Gid)) assert.Equal(t, StatusSucceed, getTransStatus(saga.Gid)) - common.Config.UpdateBranchSync = 1 + conf.UpdateBranchSync = 1 } diff --git a/test/examples_test.go b/test/examples_test.go deleted file mode 100644 index 0ed0ca2..0000000 --- a/test/examples_test.go +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2021 yedf. All rights reserved. - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - */ - -package test - -import ( - "testing" - - "github.com/dtm-labs/dtm/examples" -) - -func TestExamples(t *testing.T) { - examples.QsStartSvr() - for _, s := range examples.Samples { - assertSucceed(t, s.Action()) - } -} diff --git a/test/main_test.go b/test/main_test.go index 95c5836..e7d7ca9 100644 --- a/test/main_test.go +++ b/test/main_test.go @@ -11,12 +11,11 @@ import ( "testing" "time" - "github.com/dtm-labs/dtm/common" "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/logger" "github.com/dtm-labs/dtm/dtmsvr" - "github.com/dtm-labs/dtm/examples" - "github.com/gin-gonic/gin" + "github.com/dtm-labs/dtm/dtmsvr/config" + "github.com/dtm-labs/dtm/test/busi" ) func exitIf(code int) { @@ -26,39 +25,35 @@ func exitIf(code int) { } func TestMain(m *testing.M) { - common.MustLoadConfig() - logger.InitLog(config.LogLevel) - dtmcli.SetCurrentDBType(common.Config.ExamplesDB.Driver) + config.MustLoadConfig("") + logger.InitLog("debug") + dtmcli.SetCurrentDBType(busi.BusiConf.Driver) dtmsvr.TransProcessedTestChan = make(chan string, 1) dtmsvr.NowForwardDuration = 0 * time.Second dtmsvr.CronForwardDuration = 180 * time.Second - common.Config.UpdateBranchSync = 1 + conf.UpdateBranchSync = 1 - // 启动组件 - go dtmsvr.StartSvr() - examples.GrpcStartup() - app = examples.BaseAppStartup() - app.POST(examples.BusiAPI+"/TccBSleepCancel", common.WrapHandler(func(c *gin.Context) (interface{}, error) { - return disorderHandler(c) - })) tenv := os.Getenv("TEST_STORE") if tenv == "boltdb" { - config.Store.Driver = "boltdb" + conf.Store.Driver = "boltdb" } else if tenv == "mysql" { - config.Store.Driver = "mysql" - config.Store.Host = "localhost" - config.Store.Port = 3306 - config.Store.User = "root" - config.Store.Password = "" + conf.Store.Driver = "mysql" + conf.Store.Host = "localhost" + conf.Store.Port = 3306 + conf.Store.User = "root" + conf.Store.Password = "" } else { - config.Store.Driver = "redis" - config.Store.Host = "localhost" - config.Store.User = "" - config.Store.Password = "" - config.Store.Port = 6379 + conf.Store.Driver = "redis" + conf.Store.Host = "localhost" + conf.Store.User = "" + conf.Store.Password = "" + conf.Store.Port = 6379 } dtmsvr.PopulateDB(false) - examples.PopulateDB(false) + go dtmsvr.StartSvr() + + busi.PopulateDB(false) + _ = busi.Startup() exitIf(m.Run()) } diff --git a/test/msg_grpc_test.go b/test/msg_grpc_test.go index 1869be9..44af2ab 100644 --- a/test/msg_grpc_test.go +++ b/test/msg_grpc_test.go @@ -13,7 +13,8 @@ import ( "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" "github.com/dtm-labs/dtm/dtmgrpc" - "github.com/dtm-labs/dtm/examples" + "github.com/dtm-labs/dtm/dtmutil" + "github.com/dtm-labs/dtm/test/busi" "github.com/stretchr/testify/assert" ) @@ -30,10 +31,10 @@ func TestMsgGrpcTimeoutSuccess(t *testing.T) { msg := genGrpcMsg(dtmimp.GetFuncName()) err := msg.Prepare("") assert.Nil(t, err) - examples.MainSwitch.CanSubmitResult.SetOnce(dtmcli.ResultOngoing) + busi.MainSwitch.CanSubmitResult.SetOnce(dtmcli.ResultOngoing) cronTransOnceForwardNow(180) assert.Equal(t, StatusPrepared, getTransStatus(msg.Gid)) - examples.MainSwitch.TransOutResult.SetOnce(dtmcli.ResultOngoing) + busi.MainSwitch.TransOutResult.SetOnce(dtmcli.ResultOngoing) cronTransOnceForwardNow(180) assert.Equal(t, StatusSubmitted, getTransStatus(msg.Gid)) assert.Equal(t, []string{StatusPrepared, StatusPrepared}, getBranchesStatus(msg.Gid)) @@ -46,20 +47,20 @@ func TestMsgGrpcTimeoutFailed(t *testing.T) { msg := genGrpcMsg(dtmimp.GetFuncName()) msg.Prepare("") assert.Equal(t, StatusPrepared, getTransStatus(msg.Gid)) - examples.MainSwitch.CanSubmitResult.SetOnce(dtmcli.ResultOngoing) + busi.MainSwitch.CanSubmitResult.SetOnce(dtmcli.ResultOngoing) cronTransOnceForwardNow(180) assert.Equal(t, StatusPrepared, getTransStatus(msg.Gid)) - examples.MainSwitch.CanSubmitResult.SetOnce(dtmcli.ResultFailure) + busi.MainSwitch.CanSubmitResult.SetOnce(dtmcli.ResultFailure) cronTransOnceForwardNow(180) assert.Equal(t, StatusFailed, getTransStatus(msg.Gid)) assert.Equal(t, []string{StatusPrepared, StatusPrepared}, getBranchesStatus(msg.Gid)) } func genGrpcMsg(gid string) *dtmgrpc.MsgGrpc { - req := &examples.BusiReq{Amount: 30} - msg := dtmgrpc.NewMsgGrpc(examples.DtmGrpcServer, gid). - Add(examples.BusiGrpc+"/examples.Busi/TransOut", req). - Add(examples.BusiGrpc+"/examples.Busi/TransIn", req) - msg.QueryPrepared = fmt.Sprintf("%s/examples.Busi/CanSubmit", examples.BusiGrpc) + req := &busi.BusiReq{Amount: 30} + msg := dtmgrpc.NewMsgGrpc(dtmutil.DefaultGrpcServer, gid). + Add(busi.BusiGrpc+"/busi.Busi/TransOut", req). + Add(busi.BusiGrpc+"/busi.Busi/TransIn", req) + msg.QueryPrepared = fmt.Sprintf("%s/busi.Busi/CanSubmit", busi.BusiGrpc) return msg } diff --git a/test/msg_options_test.go b/test/msg_options_test.go index 49e6265..f69b8c9 100644 --- a/test/msg_options_test.go +++ b/test/msg_options_test.go @@ -11,7 +11,7 @@ import ( "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" - "github.com/dtm-labs/dtm/examples" + "github.com/dtm-labs/dtm/test/busi" "github.com/stretchr/testify/assert" ) @@ -44,7 +44,7 @@ func TestMsgOptionsTimeoutFailed(t *testing.T) { assert.Equal(t, StatusPrepared, getTransStatus(msg.Gid)) cronTransOnceForwardNow(60) assert.Equal(t, StatusPrepared, getTransStatus(msg.Gid)) - examples.MainSwitch.CanSubmitResult.SetOnce(dtmcli.ResultFailure) + busi.MainSwitch.CanSubmitResult.SetOnce(dtmcli.ResultFailure) cronTransOnceForwardNow(180) assert.Equal(t, StatusFailed, getTransStatus(msg.Gid)) } diff --git a/test/msg_test.go b/test/msg_test.go index 40d5dc2..fa29923 100644 --- a/test/msg_test.go +++ b/test/msg_test.go @@ -11,7 +11,8 @@ import ( "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" - "github.com/dtm-labs/dtm/examples" + "github.com/dtm-labs/dtm/dtmutil" + "github.com/dtm-labs/dtm/test/busi" "github.com/stretchr/testify/assert" ) @@ -28,10 +29,10 @@ func TestMsgTimeoutSuccess(t *testing.T) { msg := genMsg(dtmimp.GetFuncName()) msg.Prepare("") assert.Equal(t, StatusPrepared, getTransStatus(msg.Gid)) - examples.MainSwitch.CanSubmitResult.SetOnce(dtmcli.ResultOngoing) + busi.MainSwitch.CanSubmitResult.SetOnce(dtmcli.ResultOngoing) cronTransOnceForwardNow(180) assert.Equal(t, StatusPrepared, getTransStatus(msg.Gid)) - examples.MainSwitch.TransInResult.SetOnce(dtmcli.ResultOngoing) + busi.MainSwitch.TransInResult.SetOnce(dtmcli.ResultOngoing) cronTransOnceForwardNow(180) assert.Equal(t, StatusSubmitted, getTransStatus(msg.Gid)) cronTransOnce() @@ -43,10 +44,10 @@ func TestMsgTimeoutFailed(t *testing.T) { msg := genMsg(dtmimp.GetFuncName()) msg.Prepare("") assert.Equal(t, StatusPrepared, getTransStatus(msg.Gid)) - examples.MainSwitch.CanSubmitResult.SetOnce(dtmcli.ResultOngoing) + busi.MainSwitch.CanSubmitResult.SetOnce(dtmcli.ResultOngoing) cronTransOnceForwardNow(180) assert.Equal(t, StatusPrepared, getTransStatus(msg.Gid)) - examples.MainSwitch.CanSubmitResult.SetOnce(dtmcli.ResultFailure) + busi.MainSwitch.CanSubmitResult.SetOnce(dtmcli.ResultFailure) cronTransOnceForwardNow(180) assert.Equal(t, []string{StatusPrepared, StatusPrepared}, getBranchesStatus(msg.Gid)) assert.Equal(t, StatusFailed, getTransStatus(msg.Gid)) @@ -65,10 +66,10 @@ func TestMsgAbnormal(t *testing.T) { } func genMsg(gid string) *dtmcli.Msg { - req := examples.GenTransReq(30, false, false) - msg := dtmcli.NewMsg(examples.DtmHttpServer, gid). - Add(examples.Busi+"/TransOut", &req). - Add(examples.Busi+"/TransIn", &req) - msg.QueryPrepared = examples.Busi + "/CanSubmit" + req := busi.GenTransReq(30, false, false) + msg := dtmcli.NewMsg(dtmutil.DefaultHttpServer, gid). + Add(busi.Busi+"/TransOut", &req). + Add(busi.Busi+"/TransIn", &req) + msg.QueryPrepared = busi.Busi + "/CanSubmit" return msg } diff --git a/test/saga_barrier_test.go b/test/saga_barrier_test.go index 59a84dd..ecb2194 100644 --- a/test/saga_barrier_test.go +++ b/test/saga_barrier_test.go @@ -11,7 +11,7 @@ import ( "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" - "github.com/dtm-labs/dtm/examples" + "github.com/dtm-labs/dtm/test/busi" "github.com/stretchr/testify/assert" ) @@ -34,7 +34,7 @@ func TestSagaBarrierRollback(t *testing.T) { } func genSagaBarrier(gid string, outFailed, inFailed bool) *dtmcli.Saga { - req := examples.GenTransReq(30, outFailed, inFailed) + req := busi.GenTransReq(30, outFailed, inFailed) return dtmcli.NewSaga(DtmServer, gid). Add(Busi+"/SagaBTransOut", Busi+"/SagaBTransOutCompensate", req). Add(Busi+"/SagaBTransIn", Busi+"/SagaBTransInCompensate", req) diff --git a/test/saga_compatible_test.go b/test/saga_compatible_test.go index 20ea21f..fbf81cd 100644 --- a/test/saga_compatible_test.go +++ b/test/saga_compatible_test.go @@ -11,15 +11,16 @@ import ( "testing" "github.com/dtm-labs/dtm/dtmcli/dtmimp" - "github.com/dtm-labs/dtm/examples" + "github.com/dtm-labs/dtm/dtmutil" + "github.com/dtm-labs/dtm/test/busi" "github.com/stretchr/testify/assert" ) func TestSagaCompatibleNormal(t *testing.T) { // compatible with old http, which put payload in steps.data gid := dtmimp.GetFuncName() body := fmt.Sprintf(`{"gid":"%s","trans_type":"saga","steps":[{"action":"%s/TransOut","compensate":"%s/TransOutRevert","data":"{\"amount\":30,\"transInResult\":\"SUCCESS\",\"transOutResult\":\"SUCCESS\"}"},{"action":"%s/TransIn","compensate":"%s/TransInRevert","data":"{\"amount\":30,\"transInResult\":\"SUCCESS\",\"transOutResult\":\"SUCCESS\"}"}]}`, - gid, examples.Busi, examples.Busi, examples.Busi, examples.Busi) - dtmimp.RestyClient.R().SetBody(body).Post(fmt.Sprintf("%s/submit", examples.DtmHttpServer)) + gid, busi.Busi, busi.Busi, busi.Busi, busi.Busi) + dtmimp.RestyClient.R().SetBody(body).Post(fmt.Sprintf("%s/submit", dtmutil.DefaultHttpServer)) waitTransProcessed(gid) assert.Equal(t, []string{StatusPrepared, StatusSucceed, StatusPrepared, StatusSucceed}, getBranchesStatus(gid)) assert.Equal(t, StatusSucceed, getTransStatus(gid)) diff --git a/test/saga_concurrent_test.go b/test/saga_concurrent_test.go index a629510..7ae5635 100644 --- a/test/saga_concurrent_test.go +++ b/test/saga_concurrent_test.go @@ -11,7 +11,7 @@ import ( "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" - "github.com/dtm-labs/dtm/examples" + "github.com/dtm-labs/dtm/test/busi" "github.com/stretchr/testify/assert" ) @@ -29,7 +29,7 @@ func TestSagaConNormal(t *testing.T) { func TestSagaConRollbackNormal(t *testing.T) { sagaCon := genSagaCon(dtmimp.GetFuncName(), true, false) - examples.MainSwitch.TransOutRevertResult.SetOnce(dtmcli.ResultOngoing) + busi.MainSwitch.TransOutRevertResult.SetOnce(dtmcli.ResultOngoing) err := sagaCon.Submit() assert.Nil(t, err) waitTransProcessed(sagaCon.Gid) @@ -52,7 +52,7 @@ func TestSagaConRollbackOrder(t *testing.T) { func TestSagaConCommittedOngoing(t *testing.T) { sagaCon := genSagaCon(dtmimp.GetFuncName(), false, false) - examples.MainSwitch.TransOutResult.SetOnce(dtmcli.ResultOngoing) + busi.MainSwitch.TransOutResult.SetOnce(dtmcli.ResultOngoing) sagaCon.Submit() waitTransProcessed(sagaCon.Gid) assert.Equal(t, []string{StatusPrepared, StatusPrepared, StatusPrepared, StatusSucceed}, getBranchesStatus(sagaCon.Gid)) diff --git a/test/saga_grpc_barrier_test.go b/test/saga_grpc_barrier_test.go index 1078368..ebb5e8a 100644 --- a/test/saga_grpc_barrier_test.go +++ b/test/saga_grpc_barrier_test.go @@ -11,7 +11,8 @@ import ( "github.com/dtm-labs/dtm/dtmcli/dtmimp" "github.com/dtm-labs/dtm/dtmgrpc" - "github.com/dtm-labs/dtm/examples" + "github.com/dtm-labs/dtm/dtmutil" + "github.com/dtm-labs/dtm/test/busi" "github.com/stretchr/testify/assert" ) @@ -34,9 +35,9 @@ func TestSagaGrpcBarrierRollback(t *testing.T) { } func genSagaGrpcBarrier(gid string, outFailed bool, inFailed bool) *dtmgrpc.SagaGrpc { - saga := dtmgrpc.NewSagaGrpc(examples.DtmGrpcServer, gid) - req := examples.GenBusiReq(30, outFailed, inFailed) - saga.Add(examples.BusiGrpc+"/examples.Busi/TransOutBSaga", examples.BusiGrpc+"/examples.Busi/TransOutRevertBSaga", req) - saga.Add(examples.BusiGrpc+"/examples.Busi/TransInBSaga", examples.BusiGrpc+"/examples.Busi/TransInRevertBSaga", req) + saga := dtmgrpc.NewSagaGrpc(dtmutil.DefaultGrpcServer, gid) + req := busi.GenBusiReq(30, outFailed, inFailed) + saga.Add(busi.BusiGrpc+"/busi.Busi/TransOutBSaga", busi.BusiGrpc+"/busi.Busi/TransOutRevertBSaga", req) + saga.Add(busi.BusiGrpc+"/busi.Busi/TransInBSaga", busi.BusiGrpc+"/busi.Busi/TransInRevertBSaga", req) return saga } diff --git a/test/saga_grpc_test.go b/test/saga_grpc_test.go index 61a114c..831c649 100644 --- a/test/saga_grpc_test.go +++ b/test/saga_grpc_test.go @@ -12,7 +12,8 @@ import ( "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" "github.com/dtm-labs/dtm/dtmgrpc" - "github.com/dtm-labs/dtm/examples" + "github.com/dtm-labs/dtm/dtmutil" + "github.com/dtm-labs/dtm/test/busi" "github.com/stretchr/testify/assert" ) @@ -26,7 +27,7 @@ func TestSagaGrpcNormal(t *testing.T) { func TestSagaGrpcRollback(t *testing.T) { saga := genSagaGrpc(dtmimp.GetFuncName(), false, true) - examples.MainSwitch.TransOutRevertResult.SetOnce(dtmcli.ResultOngoing) + busi.MainSwitch.TransOutRevertResult.SetOnce(dtmcli.ResultOngoing) saga.Submit() waitTransProcessed(saga.Gid) assert.Equal(t, StatusAborting, getTransStatus(saga.Gid)) @@ -56,7 +57,7 @@ func TestSagaGrpcCurrentOrder(t *testing.T) { func TestSagaGrpcCommittedOngoing(t *testing.T) { saga := genSagaGrpc(dtmimp.GetFuncName(), false, false) - examples.MainSwitch.TransOutResult.SetOnce(dtmcli.ResultOngoing) + busi.MainSwitch.TransOutResult.SetOnce(dtmcli.ResultOngoing) saga.Submit() waitTransProcessed(saga.Gid) assert.Equal(t, StatusSubmitted, getTransStatus(saga.Gid)) @@ -76,10 +77,10 @@ func TestSagaGrpcNormalWait(t *testing.T) { } func TestSagaGrpcEmptyUrl(t *testing.T) { - saga := dtmgrpc.NewSagaGrpc(examples.DtmGrpcServer, dtmimp.GetFuncName()) - req := examples.GenBusiReq(30, false, false) - saga.Add(examples.BusiGrpc+"/examples.Busi/TransOut", examples.BusiGrpc+"/examples.Busi/TransOutRevert", req) - saga.Add("", examples.BusiGrpc+"/examples.Busi/TransInRevert", req) + saga := dtmgrpc.NewSagaGrpc(dtmutil.DefaultGrpcServer, dtmimp.GetFuncName()) + req := busi.GenBusiReq(30, false, false) + saga.Add(busi.BusiGrpc+"/busi.Busi/TransOut", busi.BusiGrpc+"/busi.Busi/TransOutRevert", req) + saga.Add("", busi.BusiGrpc+"/busi.Busi/TransInRevert", req) saga.Submit() waitTransProcessed(saga.Gid) assert.Equal(t, []string{StatusPrepared, StatusSucceed, StatusPrepared, StatusSucceed}, getBranchesStatus(saga.Gid)) @@ -87,9 +88,9 @@ func TestSagaGrpcEmptyUrl(t *testing.T) { } func genSagaGrpc(gid string, outFailed bool, inFailed bool) *dtmgrpc.SagaGrpc { - saga := dtmgrpc.NewSagaGrpc(examples.DtmGrpcServer, gid) - req := examples.GenBusiReq(30, outFailed, inFailed) - saga.Add(examples.BusiGrpc+"/examples.Busi/TransOut", examples.BusiGrpc+"/examples.Busi/TransOutRevert", req) - saga.Add(examples.BusiGrpc+"/examples.Busi/TransIn", examples.BusiGrpc+"/examples.Busi/TransInRevert", req) + saga := dtmgrpc.NewSagaGrpc(dtmutil.DefaultGrpcServer, gid) + req := busi.GenBusiReq(30, outFailed, inFailed) + saga.Add(busi.BusiGrpc+"/busi.Busi/TransOut", busi.BusiGrpc+"/busi.Busi/TransOutRevert", req) + saga.Add(busi.BusiGrpc+"/busi.Busi/TransIn", busi.BusiGrpc+"/busi.Busi/TransInRevert", req) return saga } diff --git a/test/saga_options_test.go b/test/saga_options_test.go index c82bd56..bbd1689 100644 --- a/test/saga_options_test.go +++ b/test/saga_options_test.go @@ -11,14 +11,14 @@ import ( "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" - "github.com/dtm-labs/dtm/examples" + "github.com/dtm-labs/dtm/test/busi" "github.com/stretchr/testify/assert" ) func TestSagaOptionsRetryOngoing(t *testing.T) { saga := genSaga1(dtmimp.GetFuncName(), false, false) saga.RetryInterval = 150 // CronForwardDuration is larger than RetryInterval - examples.MainSwitch.TransOutResult.SetOnce(dtmcli.ResultOngoing) + busi.MainSwitch.TransOutResult.SetOnce(dtmcli.ResultOngoing) err := saga.Submit() assert.Nil(t, err) waitTransProcessed(saga.Gid) @@ -30,7 +30,7 @@ func TestSagaOptionsRetryOngoing(t *testing.T) { func TestSagaOptionsRetryError(t *testing.T) { saga := genSaga1(dtmimp.GetFuncName(), false, false) saga.RetryInterval = 150 // CronForwardDuration is less than 2*RetryInterval - examples.MainSwitch.TransOutResult.SetOnce("ERROR") + busi.MainSwitch.TransOutResult.SetOnce("ERROR") err := saga.Submit() assert.Nil(t, err) waitTransProcessed(saga.Gid) @@ -45,7 +45,7 @@ func TestSagaOptionsRetryError(t *testing.T) { func TestSagaOptionsTimeout(t *testing.T) { saga := genSaga(dtmimp.GetFuncName(), false, false) saga.TimeoutToFail = 1800 - examples.MainSwitch.TransOutResult.SetOnce(dtmcli.ResultOngoing) + busi.MainSwitch.TransOutResult.SetOnce(dtmcli.ResultOngoing) saga.Submit() waitTransProcessed(saga.Gid) assert.Equal(t, StatusSubmitted, getTransStatus(saga.Gid)) @@ -65,7 +65,7 @@ func TestSagaOptionsNormalWait(t *testing.T) { func TestSagaOptionsCommittedOngoingWait(t *testing.T) { saga := genSaga(dtmimp.GetFuncName(), false, false) - examples.MainSwitch.TransOutResult.SetOnce(dtmcli.ResultOngoing) + busi.MainSwitch.TransOutResult.SetOnce(dtmcli.ResultOngoing) saga.SetOptions(&dtmcli.TransOptions{WaitResult: true}) err := saga.Submit() assert.Error(t, err) diff --git a/test/saga_test.go b/test/saga_test.go index 5093ec5..57d3a85 100644 --- a/test/saga_test.go +++ b/test/saga_test.go @@ -11,7 +11,8 @@ import ( "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" - "github.com/dtm-labs/dtm/examples" + "github.com/dtm-labs/dtm/dtmutil" + "github.com/dtm-labs/dtm/test/busi" "github.com/stretchr/testify/assert" ) @@ -25,7 +26,7 @@ func TestSagaNormal(t *testing.T) { func TestSagaOngoingSucceed(t *testing.T) { saga := genSaga(dtmimp.GetFuncName(), false, false) - examples.MainSwitch.TransOutResult.SetOnce(dtmcli.ResultOngoing) + busi.MainSwitch.TransOutResult.SetOnce(dtmcli.ResultOngoing) saga.Submit() waitTransProcessed(saga.Gid) assert.Equal(t, []string{StatusPrepared, StatusPrepared, StatusPrepared, StatusPrepared}, getBranchesStatus(saga.Gid)) @@ -37,7 +38,7 @@ func TestSagaOngoingSucceed(t *testing.T) { func TestSagaFailed(t *testing.T) { saga := genSaga(dtmimp.GetFuncName(), false, true) - examples.MainSwitch.TransOutRevertResult.SetOnce("ERROR") + busi.MainSwitch.TransOutRevertResult.SetOnce("ERROR") err := saga.Submit() assert.Nil(t, err) waitTransProcessed(saga.Gid) @@ -59,9 +60,9 @@ func TestSagaAbnormal(t *testing.T) { } func TestSagaEmptyUrl(t *testing.T) { - saga := dtmcli.NewSaga(examples.DtmHttpServer, dtmimp.GetFuncName()) - req := examples.GenTransReq(30, false, false) - saga.Add(examples.Busi+"/TransOut", "", &req) + saga := dtmcli.NewSaga(dtmutil.DefaultHttpServer, dtmimp.GetFuncName()) + req := busi.GenTransReq(30, false, false) + saga.Add(busi.Busi+"/TransOut", "", &req) saga.Add("", "", &req) saga.Submit() waitTransProcessed(saga.Gid) @@ -70,16 +71,16 @@ func TestSagaEmptyUrl(t *testing.T) { } func genSaga(gid string, outFailed bool, inFailed bool) *dtmcli.Saga { - saga := dtmcli.NewSaga(examples.DtmHttpServer, gid) - req := examples.GenTransReq(30, outFailed, inFailed) - saga.Add(examples.Busi+"/TransOut", examples.Busi+"/TransOutRevert", &req) - saga.Add(examples.Busi+"/TransIn", examples.Busi+"/TransInRevert", &req) + saga := dtmcli.NewSaga(dtmutil.DefaultHttpServer, gid) + req := busi.GenTransReq(30, outFailed, inFailed) + saga.Add(busi.Busi+"/TransOut", busi.Busi+"/TransOutRevert", &req) + saga.Add(busi.Busi+"/TransIn", busi.Busi+"/TransInRevert", &req) return saga } func genSaga1(gid string, outFailed bool, inFailed bool) *dtmcli.Saga { - saga := dtmcli.NewSaga(examples.DtmHttpServer, gid) - req := examples.GenTransReq(30, outFailed, inFailed) - saga.Add(examples.Busi+"/TransOut", examples.Busi+"/TransOutRevert", &req) + saga := dtmcli.NewSaga(dtmutil.DefaultHttpServer, gid) + req := busi.GenTransReq(30, outFailed, inFailed) + saga.Add(busi.Busi+"/TransOut", busi.Busi+"/TransOutRevert", &req) return saga } diff --git a/test/store_test.go b/test/store_test.go index 08c9966..47cd425 100644 --- a/test/store_test.go +++ b/test/store_test.go @@ -70,21 +70,21 @@ func TestStoreLockTrans(t *testing.T) { gid := dtmimp.GetFuncName() g, s := initTransGlobal(gid) - g2 := s.LockOneGlobalTrans(2 * time.Duration(config.RetryInterval) * time.Second) + g2 := s.LockOneGlobalTrans(2 * time.Duration(conf.RetryInterval) * time.Second) assert.NotNil(t, g2) assert.Equal(t, gid, g2.Gid) - s.TouchCronTime(g, 3*config.RetryInterval) - g2 = s.LockOneGlobalTrans(2 * time.Duration(config.RetryInterval) * time.Second) + s.TouchCronTime(g, 3*conf.RetryInterval) + g2 = s.LockOneGlobalTrans(2 * time.Duration(conf.RetryInterval) * time.Second) assert.Nil(t, g2) - s.TouchCronTime(g, 1*config.RetryInterval) - g2 = s.LockOneGlobalTrans(2 * time.Duration(config.RetryInterval) * time.Second) + s.TouchCronTime(g, 1*conf.RetryInterval) + g2 = s.LockOneGlobalTrans(2 * time.Duration(conf.RetryInterval) * time.Second) assert.NotNil(t, g2) assert.Equal(t, gid, g2.Gid) s.ChangeGlobalStatus(g, "succeed", []string{}, true) - g2 = s.LockOneGlobalTrans(2 * time.Duration(config.RetryInterval) * time.Second) + g2 = s.LockOneGlobalTrans(2 * time.Duration(conf.RetryInterval) * time.Second) assert.Nil(t, g2) } @@ -93,7 +93,7 @@ func TestStoreWait(t *testing.T) { } func TestUpdateBranchSql(t *testing.T) { - if !config.Store.IsDB() { + if !conf.Store.IsDB() { r := registry.GetStore().UpdateBranchesSql(nil, nil) assert.Nil(t, r) } diff --git a/test/tcc_barrier_test.go b/test/tcc_barrier_test.go index 6194b64..87c3aea 100644 --- a/test/tcc_barrier_test.go +++ b/test/tcc_barrier_test.go @@ -12,19 +12,18 @@ import ( "fmt" "strings" "testing" - "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/examples" + "github.com/dtm-labs/dtm/test/busi" "github.com/gin-gonic/gin" "github.com/go-resty/resty/v2" "github.com/stretchr/testify/assert" ) func TestTccBarrierNormal(t *testing.T) { - req := examples.GenTransReq(30, false, false) + req := busi.GenTransReq(30, false, false) gid := dtmimp.GetFuncName() err := dtmcli.TccGlobalTransaction(DtmServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { _, err := tcc.CallBranch(req, Busi+"/TccBTransOutTry", Busi+"/TccBTransOutConfirm", Busi+"/TccBTransOutCancel") @@ -38,7 +37,7 @@ func TestTccBarrierNormal(t *testing.T) { } func TestTccBarrierRollback(t *testing.T) { - req := examples.GenTransReq(30, false, true) + req := busi.GenTransReq(30, false, true) gid := dtmimp.GetFuncName() err := dtmcli.TccGlobalTransaction(DtmServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { _, err := tcc.CallBranch(req, Busi+"/TccBTransOutTry", Busi+"/TccBTransOutConfirm", Busi+"/TccBTransOutCancel") @@ -51,30 +50,29 @@ func TestTccBarrierRollback(t *testing.T) { assert.Equal(t, []string{StatusSucceed, StatusPrepared, StatusSucceed, StatusPrepared}, getBranchesStatus(gid)) } -var disorderHandler func(c *gin.Context) (interface{}, error) = nil - func TestTccBarrierDisorder(t *testing.T) { - timeoutChan := make(chan string, 2) - finishedChan := make(chan string, 2) + ua1 := busi.GetUserAccountByUid(1) + ua2 := busi.GetUserAccountByUid(2) + cancelFinishedChan := make(chan string, 2) + cancelCanReturnChan := make(chan string, 2) gid := dtmimp.GetFuncName() + cronFinished := make(chan string, 2) err := dtmcli.TccGlobalTransaction(DtmServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { - body := &examples.TransReq{Amount: 30} + body := &busi.TransReq{Amount: 30} tryURL := Busi + "/TccBTransOutTry" confirmURL := Busi + "/TccBTransOutConfirm" cancelURL := Busi + "/TccBSleepCancel" // 请参见子事务屏障里的时序图,这里为了模拟该时序图,手动拆解了callbranch branchID := tcc.NewSubBranchID() - sleeped := false - disorderHandler = func(c *gin.Context) (interface{}, error) { - res, err := examples.TccBarrierTransOutCancel(c) - if !sleeped { - sleeped = true - logger.Debugf("sleep before cancel return") - <-timeoutChan - finishedChan <- "1" - } + busi.SetSleepCancelHandler(func(c *gin.Context) (interface{}, error) { + res, err := busi.TccBarrierTransOutCancel(c) + logger.Debugf("disorderHandler before cancel finish write") + cancelFinishedChan <- "1" + logger.Debugf("disorderHandler before cancel return read") + <-cancelCanReturnChan + logger.Debugf("disorderHandler after cancel return read") return res, err - } + }) // 注册子事务 resp, err := dtmimp.RestyClient.R(). SetBody(map[string]interface{}{ @@ -89,37 +87,44 @@ func TestTccBarrierDisorder(t *testing.T) { assert.Nil(t, err) assert.Contains(t, resp.String(), dtmcli.ResultSuccess) - go func() { - logger.Debugf("sleeping to wait for tcc try timeout") - <-timeoutChan - r, _ := dtmimp.RestyClient.R(). - SetBody(body). - SetQueryParams(map[string]string{ - "dtm": tcc.Dtm, - "gid": tcc.Gid, - "branch_id": branchID, - "trans_type": "tcc", - "op": dtmcli.BranchTry, - }). - Post(tryURL) - assert.True(t, strings.Contains(r.String(), dtmcli.ResultSuccess)) // 这个是悬挂操作,为了简单起见,依旧让他返回成功 - finishedChan <- "1" - }() - logger.Debugf("cron to timeout and then call cancel") - go cronTransOnceForwardNow(300) - time.Sleep(100 * time.Millisecond) logger.Debugf("cron to timeout and then call cancelled twice") - cronTransOnceForwardNow(300) - timeoutChan <- "wake" - timeoutChan <- "wake" - <-finishedChan - <-finishedChan - time.Sleep(100 * time.Millisecond) + cron := func() { + cronTransOnceForwardNow(300) + logger.Debugf("cronFinished write") + cronFinished <- "1" + logger.Debugf("cronFinished after write") + } + go cron() + <-cancelFinishedChan + go cron() + <-cancelFinishedChan + cancelCanReturnChan <- "1" + cancelCanReturnChan <- "1" + logger.Debugf("after cancelCanRetrun 2 write") + // after cancel then run try + r, _ := dtmimp.RestyClient.R(). + SetBody(body). + SetQueryParams(map[string]string{ + "dtm": tcc.Dtm, + "gid": tcc.Gid, + "branch_id": branchID, + "trans_type": "tcc", + "op": dtmcli.BranchTry, + }). + Post(tryURL) + assert.True(t, strings.Contains(r.String(), dtmcli.ResultSuccess)) // 这个是悬挂操作,为了简单起见,依旧让他返回成功 + logger.Debugf("cronFinished read") + <-cronFinished + <-cronFinished + logger.Debugf("cronFinished after read") + return nil, fmt.Errorf("a cancelled tcc") }) assert.Error(t, err, fmt.Errorf("a cancelled tcc")) assert.Equal(t, []string{StatusSucceed, StatusPrepared}, getBranchesStatus(gid)) assert.Equal(t, StatusFailed, getTransStatus(gid)) + assert.True(t, busi.IsEqual(ua1, busi.GetUserAccountByUid(1))) + assert.True(t, busi.IsEqual(ua2, busi.GetUserAccountByUid(2))) } func TestTccBarrierPanic(t *testing.T) { diff --git a/test/tcc_cover_test.go b/test/tcc_cover_test.go index d865395..9ca4285 100644 --- a/test/tcc_cover_test.go +++ b/test/tcc_cover_test.go @@ -5,7 +5,7 @@ import ( "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" - "github.com/dtm-labs/dtm/examples" + "github.com/dtm-labs/dtm/dtmutil" "github.com/go-resty/resty/v2" "github.com/stretchr/testify/assert" ) @@ -21,7 +21,7 @@ func TestTccCoverNotConnected(t *testing.T) { func TestTccCoverPanic(t *testing.T) { gid := dtmimp.GetFuncName() err := dtmimp.CatchP(func() { - _ = dtmcli.TccGlobalTransaction(examples.DtmHttpServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { + _ = dtmcli.TccGlobalTransaction(dtmutil.DefaultHttpServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { panic("user panic") }) assert.FailNow(t, "not executed") diff --git a/test/tcc_grpc_cover_test.go b/test/tcc_grpc_cover_test.go index c23c160..6056b9e 100644 --- a/test/tcc_grpc_cover_test.go +++ b/test/tcc_grpc_cover_test.go @@ -5,7 +5,8 @@ import ( "github.com/dtm-labs/dtm/dtmcli/dtmimp" "github.com/dtm-labs/dtm/dtmgrpc" - "github.com/dtm-labs/dtm/examples" + "github.com/dtm-labs/dtm/dtmutil" + "github.com/dtm-labs/dtm/test/busi" "github.com/stretchr/testify/assert" "google.golang.org/protobuf/types/known/emptypb" ) @@ -21,7 +22,7 @@ func TestTccGrpcCoverNotConnected(t *testing.T) { func TestTccGrpcCoverPanic(t *testing.T) { gid := dtmimp.GetFuncName() err := dtmimp.CatchP(func() { - _ = dtmgrpc.TccGlobalTransaction(examples.DtmGrpcServer, gid, func(tcc *dtmgrpc.TccGrpc) error { + _ = dtmgrpc.TccGlobalTransaction(dtmutil.DefaultGrpcServer, gid, func(tcc *dtmgrpc.TccGrpc) error { panic("user panic") }) assert.FailNow(t, "not executed") @@ -30,16 +31,16 @@ func TestTccGrpcCoverPanic(t *testing.T) { } func TestTccGrpcCoverCallBranch(t *testing.T) { - req := examples.GenBusiReq(30, false, false) + req := busi.GenBusiReq(30, false, false) gid := dtmimp.GetFuncName() - err := dtmgrpc.TccGlobalTransaction(examples.DtmGrpcServer, gid, func(tcc *dtmgrpc.TccGrpc) error { + err := dtmgrpc.TccGlobalTransaction(dtmutil.DefaultGrpcServer, gid, func(tcc *dtmgrpc.TccGrpc) error { r := &emptypb.Empty{} - err := tcc.CallBranch(req, "not_exists://abc", examples.BusiGrpc+"/examples.Busi/TransOutConfirm", examples.BusiGrpc+"/examples.Busi/TransOutRevert", r) + err := tcc.CallBranch(req, "not_exists://abc", busi.BusiGrpc+"/busi.Busi/TransOutConfirm", busi.BusiGrpc+"/busi.Busi/TransOutRevert", r) assert.Error(t, err) tcc.Dtm = "localhost:01" - err = tcc.CallBranch(req, examples.BusiGrpc+"/examples.Busi/TransOut", examples.BusiGrpc+"/examples.Busi/TransOutConfirm", examples.BusiGrpc+"/examples.Busi/TransOutRevert", r) + err = tcc.CallBranch(req, busi.BusiGrpc+"/busi.Busi/TransOut", busi.BusiGrpc+"/busi.Busi/TransOutConfirm", busi.BusiGrpc+"/busi.Busi/TransOutRevert", r) assert.Error(t, err) return err diff --git a/test/tcc_grpc_test.go b/test/tcc_grpc_test.go index c2c919d..a9fc40b 100644 --- a/test/tcc_grpc_test.go +++ b/test/tcc_grpc_test.go @@ -14,19 +14,20 @@ import ( "github.com/dtm-labs/dtm/dtmcli/dtmimp" "github.com/dtm-labs/dtm/dtmcli/logger" "github.com/dtm-labs/dtm/dtmgrpc" - "github.com/dtm-labs/dtm/examples" + "github.com/dtm-labs/dtm/dtmutil" + "github.com/dtm-labs/dtm/test/busi" "github.com/stretchr/testify/assert" "google.golang.org/protobuf/types/known/emptypb" ) func TestTccGrpcNormal(t *testing.T) { - req := examples.GenBusiReq(30, false, false) + req := busi.GenBusiReq(30, false, false) gid := dtmimp.GetFuncName() - err := dtmgrpc.TccGlobalTransaction(examples.DtmGrpcServer, gid, func(tcc *dtmgrpc.TccGrpc) error { + err := dtmgrpc.TccGlobalTransaction(dtmutil.DefaultGrpcServer, gid, func(tcc *dtmgrpc.TccGrpc) error { r := &emptypb.Empty{} - err := tcc.CallBranch(req, examples.BusiGrpc+"/examples.Busi/TransOut", examples.BusiGrpc+"/examples.Busi/TransOutConfirm", examples.BusiGrpc+"/examples.Busi/TransOutRevert", r) + err := tcc.CallBranch(req, busi.BusiGrpc+"/busi.Busi/TransOut", busi.BusiGrpc+"/busi.Busi/TransOutConfirm", busi.BusiGrpc+"/busi.Busi/TransOutRevert", r) assert.Nil(t, err) - return tcc.CallBranch(req, examples.BusiGrpc+"/examples.Busi/TransIn", examples.BusiGrpc+"/examples.Busi/TransInConfirm", examples.BusiGrpc+"/examples.Busi/TransInRevert", r) + return tcc.CallBranch(req, busi.BusiGrpc+"/busi.Busi/TransIn", busi.BusiGrpc+"/busi.Busi/TransInConfirm", busi.BusiGrpc+"/busi.Busi/TransInRevert", r) }) assert.Nil(t, err) waitTransProcessed(gid) @@ -37,13 +38,13 @@ func TestTccGrpcNormal(t *testing.T) { func TestTccGrpcRollback(t *testing.T) { gid := dtmimp.GetFuncName() - req := examples.GenBusiReq(30, false, true) - err := dtmgrpc.TccGlobalTransaction(examples.DtmGrpcServer, gid, func(tcc *dtmgrpc.TccGrpc) error { + req := busi.GenBusiReq(30, false, true) + err := dtmgrpc.TccGlobalTransaction(dtmutil.DefaultGrpcServer, gid, func(tcc *dtmgrpc.TccGrpc) error { r := &emptypb.Empty{} - err := tcc.CallBranch(req, examples.BusiGrpc+"/examples.Busi/TransOutTcc", examples.BusiGrpc+"/examples.Busi/TransOutConfirm", examples.BusiGrpc+"/examples.Busi/TransOutRevert", r) + err := tcc.CallBranch(req, busi.BusiGrpc+"/busi.Busi/TransOutTcc", busi.BusiGrpc+"/busi.Busi/TransOutConfirm", busi.BusiGrpc+"/busi.Busi/TransOutRevert", r) assert.Nil(t, err) - examples.MainSwitch.TransOutRevertResult.SetOnce(dtmcli.ResultOngoing) - return tcc.CallBranch(req, examples.BusiGrpc+"/examples.Busi/TransInTcc", examples.BusiGrpc+"/examples.Busi/TransInConfirm", examples.BusiGrpc+"/examples.Busi/TransInRevert", r) + busi.MainSwitch.TransOutRevertResult.SetOnce(dtmcli.ResultOngoing) + return tcc.CallBranch(req, busi.BusiGrpc+"/busi.Busi/TransInTcc", busi.BusiGrpc+"/busi.Busi/TransInConfirm", busi.BusiGrpc+"/busi.Busi/TransInRevert", r) }) assert.Error(t, err) waitTransProcessed(gid) @@ -54,13 +55,13 @@ func TestTccGrpcRollback(t *testing.T) { } func TestTccGrpcNested(t *testing.T) { - req := examples.GenBusiReq(30, false, false) + req := busi.GenBusiReq(30, false, false) gid := dtmimp.GetFuncName() - err := dtmgrpc.TccGlobalTransaction(examples.DtmGrpcServer, gid, func(tcc *dtmgrpc.TccGrpc) error { + err := dtmgrpc.TccGlobalTransaction(dtmutil.DefaultGrpcServer, gid, func(tcc *dtmgrpc.TccGrpc) error { r := &emptypb.Empty{} - err := tcc.CallBranch(req, examples.BusiGrpc+"/examples.Busi/TransOutTcc", examples.BusiGrpc+"/examples.Busi/TransOutConfirm", examples.BusiGrpc+"/examples.Busi/TransOutRevert", r) + err := tcc.CallBranch(req, busi.BusiGrpc+"/busi.Busi/TransOutTcc", busi.BusiGrpc+"/busi.Busi/TransOutConfirm", busi.BusiGrpc+"/busi.Busi/TransOutRevert", r) assert.Nil(t, err) - return tcc.CallBranch(req, examples.BusiGrpc+"/examples.Busi/TransInTccNested", examples.BusiGrpc+"/examples.Busi/TransInConfirm", examples.BusiGrpc+"/examples.Busi/TransInRevert", r) + return tcc.CallBranch(req, busi.BusiGrpc+"/busi.Busi/TransInTccNested", busi.BusiGrpc+"/busi.Busi/TransInConfirm", busi.BusiGrpc+"/busi.Busi/TransInRevert", r) }) assert.Nil(t, err) waitTransProcessed(gid) @@ -71,7 +72,7 @@ func TestTccGrpcNested(t *testing.T) { func TestTccGrpcType(t *testing.T) { _, err := dtmgrpc.TccFromGrpc(context.Background()) assert.Error(t, err) - logger.Debugf("expecting dtmgrpcserver error") + logger.Debugf("expecting dtmutil.DefaultGrpcServer error") err = dtmgrpc.TccGlobalTransaction("-", "", func(tcc *dtmgrpc.TccGrpc) error { return nil }) assert.Error(t, err) } diff --git a/test/tcc_test.go b/test/tcc_test.go index b2cf9c3..3766c59 100644 --- a/test/tcc_test.go +++ b/test/tcc_test.go @@ -11,15 +11,16 @@ import ( "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" - "github.com/dtm-labs/dtm/examples" + "github.com/dtm-labs/dtm/dtmutil" + "github.com/dtm-labs/dtm/test/busi" "github.com/go-resty/resty/v2" "github.com/stretchr/testify/assert" ) func TestTccNormal(t *testing.T) { - req := examples.GenTransReq(30, false, false) + req := busi.GenTransReq(30, false, false) gid := dtmimp.GetFuncName() - err := dtmcli.TccGlobalTransaction(examples.DtmHttpServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { + err := dtmcli.TccGlobalTransaction(dtmutil.DefaultHttpServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { _, err := tcc.CallBranch(req, Busi+"/TransOut", Busi+"/TransOutConfirm", Busi+"/TransOutRevert") assert.Nil(t, err) return tcc.CallBranch(req, Busi+"/TransIn", Busi+"/TransInConfirm", Busi+"/TransInRevert") @@ -32,11 +33,11 @@ func TestTccNormal(t *testing.T) { func TestTccRollback(t *testing.T) { gid := dtmimp.GetFuncName() - req := examples.GenTransReq(30, false, true) - err := dtmcli.TccGlobalTransaction(examples.DtmHttpServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { + req := busi.GenTransReq(30, false, true) + err := dtmcli.TccGlobalTransaction(dtmutil.DefaultHttpServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { _, rerr := tcc.CallBranch(req, Busi+"/TransOut", Busi+"/TransOutConfirm", Busi+"/TransOutRevert") assert.Nil(t, rerr) - examples.MainSwitch.TransOutRevertResult.SetOnce(dtmcli.ResultOngoing) + busi.MainSwitch.TransOutRevertResult.SetOnce(dtmcli.ResultOngoing) return tcc.CallBranch(req, Busi+"/TransIn", Busi+"/TransInConfirm", Busi+"/TransInRevert") }) assert.Error(t, err) @@ -48,11 +49,11 @@ func TestTccRollback(t *testing.T) { } func TestTccTimeout(t *testing.T) { - req := examples.GenTransReq(30, false, false) + req := busi.GenTransReq(30, false, false) gid := dtmimp.GetFuncName() timeoutChan := make(chan int, 1) - err := dtmcli.TccGlobalTransaction(examples.DtmHttpServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { + err := dtmcli.TccGlobalTransaction(dtmutil.DefaultHttpServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { _, err := tcc.CallBranch(req, Busi+"/TransOut", Busi+"/TransOutConfirm", Busi+"/TransOutRevert") assert.Nil(t, err) go func() { @@ -70,9 +71,9 @@ func TestTccTimeout(t *testing.T) { } func TestTccCompatible(t *testing.T) { - req := examples.GenTransReq(30, false, false) + req := busi.GenTransReq(30, false, false) gid := dtmimp.GetFuncName() - err := dtmcli.TccGlobalTransaction(examples.DtmHttpServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { + err := dtmcli.TccGlobalTransaction(dtmutil.DefaultHttpServer, gid, func(tcc *dtmcli.Tcc) (*resty.Response, error) { _, err := tcc.CallBranch(req, Busi+"/TransOut", Busi+"/TransOutConfirm", Busi+"/TransOutRevert") assert.Nil(t, err) return tcc.CallBranch(req, Busi+"/TransIn", Busi+"/TransInConfirm", Busi+"/TransInRevert") diff --git a/test/types.go b/test/types.go index 923cc35..8ed65c8 100644 --- a/test/types.go +++ b/test/types.go @@ -9,17 +9,19 @@ package test import ( "time" - "github.com/dtm-labs/dtm/common" "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" + "github.com/dtm-labs/dtm/dtmsvr/config" + "github.com/dtm-labs/dtm/dtmutil" + "github.com/dtm-labs/dtm/test/busi" ) -var config = &common.Config +var conf = &config.Config -func dbGet() *common.DB { - return common.DbGet(config.ExamplesDB) +func dbGet() *dtmutil.DB { + return dtmutil.DbGet(busi.BusiConf) } // waitTransProcessed only for test usage. wait for transaction processed once @@ -28,7 +30,7 @@ func waitTransProcessed(gid string) { select { case id := <-dtmsvr.TransProcessedTestChan: for id != gid { - logger.Errorf("-------id %s not match gid %s", id, gid) + logger.Warnf("------- expecting: %s but %s found", gid, id) id = <-dtmsvr.TransProcessedTestChan } logger.Debugf("finish for gid %s", gid) diff --git a/test/xa_cover_test.go b/test/xa_cover_test.go index 6c61700..fddada6 100644 --- a/test/xa_cover_test.go +++ b/test/xa_cover_test.go @@ -5,7 +5,7 @@ import ( "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" - "github.com/dtm-labs/dtm/examples" + "github.com/dtm-labs/dtm/test/busi" "github.com/go-resty/resty/v2" "github.com/stretchr/testify/assert" ) @@ -14,11 +14,11 @@ func TestXaCoverDBError(t *testing.T) { oldDriver := getXc().Conf.Driver gid := dtmimp.GetFuncName() err := getXc().XaGlobalTransaction(gid, func(xa *dtmcli.Xa) (*resty.Response, error) { - req := examples.GenTransReq(30, false, false) - _, err := xa.CallBranch(req, examples.Busi+"/TransOutXa") + req := busi.GenTransReq(30, false, false) + _, err := xa.CallBranch(req, busi.Busi+"/TransOutXa") assert.Nil(t, err) getXc().Conf.Driver = "no-driver" - _, err = xa.CallBranch(req, examples.Busi+"/TransInXa") + _, err = xa.CallBranch(req, busi.Busi+"/TransInXa") assert.Error(t, err) getXc().Conf.Driver = oldDriver // make abort succeed return nil, err @@ -45,8 +45,8 @@ func TestXaCoverDTMError(t *testing.T) { func TestXaCoverGidError(t *testing.T) { gid := "errgid-' '" err := getXc().XaGlobalTransaction(gid, func(xa *dtmcli.Xa) (*resty.Response, error) { - req := examples.GenTransReq(30, false, false) - _, err := xa.CallBranch(req, examples.Busi+"/TransOutXa") + req := busi.GenTransReq(30, false, false) + _, err := xa.CallBranch(req, busi.Busi+"/TransOutXa") assert.Error(t, err) return nil, err }) diff --git a/test/xa_grpc_test.go b/test/xa_grpc_test.go index 283df1b..586e3db 100644 --- a/test/xa_grpc_test.go +++ b/test/xa_grpc_test.go @@ -13,24 +13,24 @@ import ( "github.com/dtm-labs/dtm/dtmcli/dtmimp" "github.com/dtm-labs/dtm/dtmgrpc" - "github.com/dtm-labs/dtm/examples" + "github.com/dtm-labs/dtm/test/busi" "github.com/stretchr/testify/assert" "google.golang.org/protobuf/types/known/emptypb" ) func getXcg() *dtmgrpc.XaGrpcClient { - return examples.XaGrpcClient + return busi.XaGrpcClient } func TestXaGrpcNormal(t *testing.T) { gid := dtmimp.GetFuncName() err := getXcg().XaGlobalTransaction(gid, func(xa *dtmgrpc.XaGrpc) error { - req := examples.GenBusiReq(30, false, false) + req := busi.GenBusiReq(30, false, false) r := &emptypb.Empty{} - err := xa.CallBranch(req, examples.BusiGrpc+"/examples.Busi/TransOutXa", r) + err := xa.CallBranch(req, busi.BusiGrpc+"/busi.Busi/TransOutXa", r) if err != nil { return err } - return xa.CallBranch(req, examples.BusiGrpc+"/examples.Busi/TransInXa", r) + return xa.CallBranch(req, busi.BusiGrpc+"/busi.Busi/TransInXa", r) }) assert.Equal(t, nil, err) waitTransProcessed(gid) @@ -41,13 +41,13 @@ func TestXaGrpcNormal(t *testing.T) { func TestXaGrpcRollback(t *testing.T) { gid := dtmimp.GetFuncName() err := getXcg().XaGlobalTransaction(gid, func(xa *dtmgrpc.XaGrpc) error { - req := examples.GenBusiReq(30, false, true) + req := busi.GenBusiReq(30, false, true) r := &emptypb.Empty{} - err := xa.CallBranch(req, examples.BusiGrpc+"/examples.Busi/TransOutXa", r) + err := xa.CallBranch(req, busi.BusiGrpc+"/busi.Busi/TransOutXa", r) if err != nil { return err } - return xa.CallBranch(req, examples.BusiGrpc+"/examples.Busi/TransInXa", r) + return xa.CallBranch(req, busi.BusiGrpc+"/busi.Busi/TransInXa", r) }) assert.Error(t, err) waitTransProcessed(gid) @@ -59,17 +59,17 @@ func TestXaGrpcType(t *testing.T) { _, err := dtmgrpc.XaGrpcFromRequest(context.Background()) assert.Error(t, err) - err = examples.XaGrpcClient.XaLocalTransaction(context.Background(), nil, nil) + err = busi.XaGrpcClient.XaLocalTransaction(context.Background(), nil, nil) assert.Error(t, err) err = dtmimp.CatchP(func() { - examples.XaGrpcClient.XaGlobalTransaction("id1", func(xa *dtmgrpc.XaGrpc) error { panic(fmt.Errorf("hello")) }) + busi.XaGrpcClient.XaGlobalTransaction("id1", func(xa *dtmgrpc.XaGrpc) error { panic(fmt.Errorf("hello")) }) }) assert.Error(t, err) } func TestXaGrpcLocalError(t *testing.T) { - xc := examples.XaGrpcClient + xc := busi.XaGrpcClient err := xc.XaGlobalTransaction(dtmimp.GetFuncName(), func(xa *dtmgrpc.XaGrpc) error { return fmt.Errorf("an error") }) diff --git a/test/xa_test.go b/test/xa_test.go index 929d80d..0515c02 100644 --- a/test/xa_test.go +++ b/test/xa_test.go @@ -12,24 +12,24 @@ import ( "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" - "github.com/dtm-labs/dtm/examples" + "github.com/dtm-labs/dtm/test/busi" "github.com/go-resty/resty/v2" "github.com/stretchr/testify/assert" ) func getXc() *dtmcli.XaClient { - return examples.XaClient + return busi.XaClient } func TestXaNormal(t *testing.T) { gid := dtmimp.GetFuncName() err := getXc().XaGlobalTransaction(gid, func(xa *dtmcli.Xa) (*resty.Response, error) { - req := examples.GenTransReq(30, false, false) - resp, err := xa.CallBranch(req, examples.Busi+"/TransOutXa") + req := busi.GenTransReq(30, false, false) + resp, err := xa.CallBranch(req, busi.Busi+"/TransOutXa") if err != nil { return resp, err } - return xa.CallBranch(req, examples.Busi+"/TransInXa") + return xa.CallBranch(req, busi.Busi+"/TransInXa") }) assert.Equal(t, nil, err) waitTransProcessed(gid) @@ -40,10 +40,10 @@ func TestXaNormal(t *testing.T) { func TestXaDuplicate(t *testing.T) { gid := dtmimp.GetFuncName() err := getXc().XaGlobalTransaction(gid, func(xa *dtmcli.Xa) (*resty.Response, error) { - req := examples.GenTransReq(30, false, false) - _, err := xa.CallBranch(req, examples.Busi+"/TransOutXa") + req := busi.GenTransReq(30, false, false) + _, err := xa.CallBranch(req, busi.Busi+"/TransOutXa") assert.Nil(t, err) - sdb, err := dtmimp.StandaloneDB(config.ExamplesDB) + sdb, err := dtmimp.StandaloneDB(busi.BusiConf) assert.Nil(t, err) if dtmcli.GetCurrentDBType() == dtmcli.DBTypeMysql { _, err = dtmimp.DBExec(sdb, "xa recover") @@ -51,7 +51,7 @@ func TestXaDuplicate(t *testing.T) { } _, err = dtmimp.DBExec(sdb, dtmimp.GetDBSpecial().GetXaSQL("commit", gid+"-01")) // 先把某一个事务提交,模拟重复请求 assert.Nil(t, err) - return xa.CallBranch(req, examples.Busi+"/TransInXa") + return xa.CallBranch(req, busi.Busi+"/TransInXa") }) assert.Nil(t, err) waitTransProcessed(gid) @@ -62,12 +62,12 @@ func TestXaDuplicate(t *testing.T) { func TestXaRollback(t *testing.T) { gid := dtmimp.GetFuncName() err := getXc().XaGlobalTransaction(gid, func(xa *dtmcli.Xa) (*resty.Response, error) { - req := examples.GenTransReq(30, false, true) - resp, err := xa.CallBranch(req, examples.Busi+"/TransOutXa") + req := busi.GenTransReq(30, false, true) + resp, err := xa.CallBranch(req, busi.Busi+"/TransOutXa") if err != nil { return resp, err } - return xa.CallBranch(req, examples.Busi+"/TransInXa") + return xa.CallBranch(req, busi.Busi+"/TransInXa") }) assert.Error(t, err) waitTransProcessed(gid) @@ -92,7 +92,7 @@ func TestXaTimeout(t *testing.T) { cronTransOnceForwardNow(300) timeoutChan <- 0 }() - _ = <-timeoutChan + <-timeoutChan return nil, nil }) assert.Error(t, err) @@ -109,10 +109,10 @@ func TestXaNotTimeout(t *testing.T) { timeoutChan <- 0 }() _ = <-timeoutChan - req := examples.GenTransReq(30, false, false) - _, err := xa.CallBranch(req, examples.Busi+"/TransOutXa") + req := busi.GenTransReq(30, false, false) + _, err := xa.CallBranch(req, busi.Busi+"/TransOutXa") assert.Nil(t, err) - examples.MainSwitch.NextResult.SetOnce(dtmcli.ResultOngoing) // make commit temp error + busi.MainSwitch.NextResult.SetOnce(dtmcli.ResultOngoing) // make commit temp error return nil, nil }) assert.Nil(t, err) From 46b14d5432708e9d2d8766a538f8f5b6e47a6df6 Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Wed, 29 Dec 2021 16:25:42 +0800 Subject: [PATCH 02/22] cover more --- conf.sample.yml | 12 ++++++------ dtmsvr/config/config_test.go | 3 +++ dtmsvr/storage/sql/sql.go | 4 ++-- test/common_test.go | 3 ++- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/conf.sample.yml b/conf.sample.yml index e4f6348..8dee2ea 100644 --- a/conf.sample.yml +++ b/conf.sample.yml @@ -1,4 +1,4 @@ -Store: # specify which engine to store trans status +# Store: # specify which engine to store trans status # Driver: 'boltdb' # default store engine # Driver: 'redis' @@ -7,11 +7,11 @@ Store: # specify which engine to store trans status # Password: '' # Port: 6379 - Driver: 'mysql' - Host: 'localhost' - User: 'root' - Password: '' - Port: 3306 +# Driver: 'mysql' +# Host: 'localhost' +# User: 'root' +# Password: '' +# Port: 3306 # Driver: 'postgres' # Host: 'localhost' diff --git a/dtmsvr/config/config_test.go b/dtmsvr/config/config_test.go index db62add..8088bef 100644 --- a/dtmsvr/config/config_test.go +++ b/dtmsvr/config/config_test.go @@ -18,12 +18,15 @@ func TestLoadFromEnv(t *testing.T) { } func TestCheckConfig(t *testing.T) { + MustLoadConfig("../../conf.sample.yml") config := &Config + config.RetryInterval = 1 retryIntervalErr := checkConfig() retryIntervalExpect := errors.New("RetryInterval should not be less than 10") assert.Equal(t, retryIntervalErr, retryIntervalExpect) config.RetryInterval = 10 + config.TimeoutToFail = 5 timeoutToFailErr := checkConfig() timeoutToFailExpect := errors.New("TimeoutToFail should not be less than RetryInterval") assert.Equal(t, timeoutToFailErr, timeoutToFailExpect) diff --git a/dtmsvr/storage/sql/sql.go b/dtmsvr/storage/sql/sql.go index 45d03b3..7e4e74d 100644 --- a/dtmsvr/storage/sql/sql.go +++ b/dtmsvr/storage/sql/sql.go @@ -144,7 +144,7 @@ func (s *SqlStore) LockOneGlobalTrans(expireIn time.Duration) *storage.TransGlob return global } -func setDBConn(db *gorm.DB) { +func SetDBConn(db *gorm.DB) { sqldb, _ := db.DB() sqldb.SetMaxOpenConns(int(conf.Store.MaxOpenConns)) sqldb.SetMaxIdleConns(int(conf.Store.MaxIdleConns)) @@ -152,7 +152,7 @@ func setDBConn(db *gorm.DB) { } func dbGet() *dtmutil.DB { - return dtmutil.DbGet(conf.Store.GetDBConf(), setDBConn) + return dtmutil.DbGet(conf.Store.GetDBConf(), SetDBConn) } func wrapError(err error) error { diff --git a/test/common_test.go b/test/common_test.go index 3b14e8d..21337fb 100644 --- a/test/common_test.go +++ b/test/common_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/dtm-labs/dtm/dtmcli/dtmimp" + "github.com/dtm-labs/dtm/dtmsvr/storage/sql" "github.com/dtm-labs/dtm/dtmutil" "github.com/stretchr/testify/assert" ) @@ -16,7 +17,7 @@ func TestGeneralDB(t *testing.T) { } func testSql(t *testing.T) { - db := dtmutil.DbGet(conf.Store.GetDBConf()) + db := dtmutil.DbGet(conf.Store.GetDBConf(), sql.SetDBConn) err := func() (rerr error) { defer dtmimp.P2E(&rerr) db.Must().Exec("select a") From 2fe248faac4e2908f843080fc9f9d2b041bdedeb Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Wed, 29 Dec 2021 16:34:26 +0800 Subject: [PATCH 03/22] TestDBConn --- test/common_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/common_test.go b/test/common_test.go index 21337fb..683577a 100644 --- a/test/common_test.go +++ b/test/common_test.go @@ -17,7 +17,9 @@ func TestGeneralDB(t *testing.T) { } func testSql(t *testing.T) { - db := dtmutil.DbGet(conf.Store.GetDBConf(), sql.SetDBConn) + conf := conf.Store.GetDBConf() + conf.Host = "127.0.0.1" // use a new host to trigger SetDBConn called + db := dtmutil.DbGet(conf, sql.SetDBConn) err := func() (rerr error) { defer dtmimp.P2E(&rerr) db.Must().Exec("select a") From 4d2b17b62ba3b0ca82b7c7c0e62b77c33135270d Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Wed, 29 Dec 2021 16:48:51 +0800 Subject: [PATCH 04/22] update coverage --- test/common_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/common_test.go b/test/common_test.go index 683577a..b042fb5 100644 --- a/test/common_test.go +++ b/test/common_test.go @@ -3,7 +3,9 @@ package test import ( "testing" + "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" + "github.com/dtm-labs/dtm/dtmgrpc" "github.com/dtm-labs/dtm/dtmsvr/storage/sql" "github.com/dtm-labs/dtm/dtmutil" "github.com/stretchr/testify/assert" @@ -39,3 +41,8 @@ func testDbAlone(t *testing.T) { _, err = dtmimp.DBExec(db, "select 1") assert.NotEqual(t, nil, err) } + +func TestMustGenGid(t *testing.T) { + dtmgrpc.MustGenGid(dtmutil.DefaultGrpcServer) + dtmcli.MustGenGid(dtmutil.DefaultHttpServer) +} From 51b0748969628de459f74d2cae32c520b7bd1aae Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Wed, 29 Dec 2021 18:42:21 +0800 Subject: [PATCH 05/22] update readme --- README-cn.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README-cn.md b/README-cn.md index 122e7df..319790f 100644 --- a/README-cn.md +++ b/README-cn.md @@ -12,9 +12,9 @@ DTM是一款golang开发的分布式事务管理器,解决了跨数据库、 他优雅的解决了幂等、空补偿、悬挂等分布式事务难题,提供了简单易用、高性能、易水平扩展的解决方案。 -作者受邀参加中国数据库大会分享[多语言环境下分布式事务实践](http://dtcc.it168.com/yicheng.html#b9) +通俗一点说,DTM提供跨服务事务能力,一组服务要么全部成功,要么全部回滚,避免只更新了一部分数据产生的业务问题。 -## 谁在使用dtm +## 谁在使用DTM(仅列出部分) [Tencent 腾讯](https://dtm.pub/other/using.html#tencent) [Ivydad 常青藤爸爸](https://dtm.pub/other/using.html#ivydad) @@ -86,6 +86,8 @@ go run main.go ### 启动并运行一个saga示例 `go run qs/main.go` +这是一个类似跨行转账的示例,包括两个事务分支:资金转出(TransOut)、资金转入(TransIn)。DTM保证TransIn和TransOut要么全部成功,要么全部回滚,保证最终金额的正确性。 + ## 接入详解 ### 接入代码 From 63742982c089fcbdd960b8e218d69493b1777717 Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Wed, 29 Dec 2021 19:46:38 +0800 Subject: [PATCH 06/22] update workflow scripts --- helper/.goreleaser.yml | 2 +- helper/Dockerfile-release | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/helper/.goreleaser.yml b/helper/.goreleaser.yml index 39ca3ad..daee966 100644 --- a/helper/.goreleaser.yml +++ b/helper/.goreleaser.yml @@ -10,6 +10,6 @@ builds: - amd64 id: 'dtm' dir: . - main: ./app/main.go + main: main.go ldflags: - -s -w -X main.Version={{.Version}} -X main.Commit={{.Commit}} -X main.Date={{.Date}} diff --git a/helper/Dockerfile-release b/helper/Dockerfile-release index b922185..3ef3ff7 100644 --- a/helper/Dockerfile-release +++ b/helper/Dockerfile-release @@ -6,10 +6,10 @@ WORKDIR /app/dtm # RUN go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,direct EXPOSE 8080 COPY . . -RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags="-s -w" app/main.go +RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags="-s -w" FROM --platform=$TARGETPLATFORM alpine:3.14 -COPY --from=builder /app/dtm/main /app/dtm/ +COPY --from=builder /app/dtm/dtm /app/dtm/ ENV IS_DOCKER=1 WORKDIR /app/dtm -CMD ["/app/dtm/main", "dtmsvr"] +CMD ["/app/dtm/dtm", "dtmsvr"] From 3005be72792fd9385a61374c18477c525476eab9 Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Wed, 29 Dec 2021 19:48:18 +0800 Subject: [PATCH 07/22] remove args --- helper/Dockerfile-release | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helper/Dockerfile-release b/helper/Dockerfile-release index 3ef3ff7..acf6846 100644 --- a/helper/Dockerfile-release +++ b/helper/Dockerfile-release @@ -12,4 +12,4 @@ FROM --platform=$TARGETPLATFORM alpine:3.14 COPY --from=builder /app/dtm/dtm /app/dtm/ ENV IS_DOCKER=1 WORKDIR /app/dtm -CMD ["/app/dtm/dtm", "dtmsvr"] +CMD ["/app/dtm/dtm"] From 83c483a9607eeea7cc47062cf07de1b1f5bb0e2a Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Wed, 29 Dec 2021 22:26:39 +0800 Subject: [PATCH 08/22] try to publish to homebrew --- helper/.goreleaser.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/helper/.goreleaser.yml b/helper/.goreleaser.yml index daee966..4b70ccc 100644 --- a/helper/.goreleaser.yml +++ b/helper/.goreleaser.yml @@ -13,3 +13,13 @@ builds: main: main.go ldflags: - -s -w -X main.Version={{.Version}} -X main.Commit={{.Commit}} -X main.Date={{.Date}} +brews: + - homepage: 'https://d.dtm.pub' + description: 'A cross-language distributed transaction manager.' + folder: Formula + commit_author: + name: yedf2 + email: 120050102@qq.com + tap: + owner: yedf2 + name: dtm From 93abba9cdcfc7dd09f5f79df68a61504944d3e49 Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Wed, 29 Dec 2021 22:35:52 +0800 Subject: [PATCH 09/22] fix tap name --- helper/.goreleaser.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/helper/.goreleaser.yml b/helper/.goreleaser.yml index 4b70ccc..218bced 100644 --- a/helper/.goreleaser.yml +++ b/helper/.goreleaser.yml @@ -18,8 +18,8 @@ brews: description: 'A cross-language distributed transaction manager.' folder: Formula commit_author: - name: yedf2 + name: dtm-labs email: 120050102@qq.com tap: - owner: yedf2 + owner: dtm-labs name: dtm From e932ddf194a1bceb29260c139ba0618c2bedc6b8 Mon Sep 17 00:00:00 2001 From: dtm-labs <120050102@qq.com> Date: Wed, 29 Dec 2021 14:42:09 +0000 Subject: [PATCH 10/22] Brew formula update for dtm version v1.8.1 --- Formula/dtm.rb | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 Formula/dtm.rb diff --git a/Formula/dtm.rb b/Formula/dtm.rb new file mode 100644 index 0000000..19341e9 --- /dev/null +++ b/Formula/dtm.rb @@ -0,0 +1,31 @@ +# typed: false +# frozen_string_literal: true + +# This file was generated by GoReleaser. DO NOT EDIT. +class Dtm < Formula + desc "A cross-language distributed transaction manager." + homepage "https://d.dtm.pub" + version "1.8.1" + + on_macos do + if Hardware::CPU.intel? + url "https://github.com/dtm-labs/dtm/releases/download/v1.8.1/dtm_1.8.1_darwin_amd64.tar.gz" + sha256 "8277820eac478f48fd6770f41eb2ec674dac1eddc66e4ebbd9c73eb41ae39548" + + def install + bin.install "dtm" + end + end + end + + on_linux do + if Hardware::CPU.intel? + url "https://github.com/dtm-labs/dtm/releases/download/v1.8.1/dtm_1.8.1_linux_amd64.tar.gz" + sha256 "ce83774f50b9f121c5f54baf657555053f817af9efccb50d80a9854b7579807a" + + def install + bin.install "dtm" + end + end + end +end From 00af043e6f4ec0cf1711659ee9413e12ae056db3 Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Thu, 30 Dec 2021 10:20:47 +0800 Subject: [PATCH 11/22] update readme --- README-cn.md | 24 +++++++++------------ README.md | 61 ++++++++++++++++++++-------------------------------- 2 files changed, 33 insertions(+), 52 deletions(-) diff --git a/README-cn.md b/README-cn.md index 319790f..cc2c53f 100644 --- a/README-cn.md +++ b/README-cn.md @@ -23,8 +23,6 @@ DTM是一款golang开发的分布式事务管理器,解决了跨数据库、 [极欧科技](https://dtm.pub/other/using.html) -[金数智联](https://dtm.pub/other/using.html) - ## 亮点 * 极易接入 @@ -34,15 +32,13 @@ DTM是一款golang开发的分布式事务管理器,解决了跨数据库、 * 跨语言 - 可适合多语言栈的公司使用。方便go、python、php、nodejs、ruby、c# 各类语言使用。 * 易部署、易扩展 - - 仅依赖mysql,部署简单,易集群化,易水平扩展 + - 支持零配置,或依赖mysql|redis,部署简单,易集群化,易水平扩展 * 多种分布式事务协议支持 - - TCC、SAGA、XA、事务消息 + - TCC、SAGA、XA、二阶段消息 ## 与其他框架对比 -目前开源的分布式事务框架,Java的框架较多,有大厂开源的SEATA、ServiceComb-Pack,shardingsphere,以及个人开源的himly,tcc-transaction,ByteTCC等等,其中以Seata的应用最为广泛。 - -非Java语言类的,暂未看到除dtm之外的成熟框架,因此这里仅将DTM和Java中最成熟的Seata对比: +非Java语言类的,暂未看到除dtm之外的成熟框架,因此这里将DTM和Java中最成熟的Seata对比: | 特性| DTM | SEATA |备注| |:-----:|:----:|:----:|:----:| @@ -69,9 +65,8 @@ DTM是一款golang开发的分布式事务管理器,解决了跨数据库、 ## 微服务框架支持 - [go-zero](https://github.com/zeromicro/go-zero):一开源就非常火爆的微服务框架,首家接入dtm的微服务框架。感谢go-zero作者[kevwan](https://github.com/kevwan)的大力支持 - [polaris](https://github.com/polarismesh/polaris): 腾讯开源的注册发现组件,以及在其上构建的微服务框架。感谢腾讯同学[ychensha](https://github.com/ychensha)的PR -- 其他:看用户需求量,择机接入 +- 其他:看用户需求量,择机接入,参见[微服务支持](https://dtm.pub/protocol/intro.html) -具体微服务接入使用,参见[微服务支持](https://dtm.pub/protocol/intro.html) ## 快速开始 如果您不是Go语言,可以跳转[各语言客户端及示例](https://dtm.pub/summary/code.html#go),里面有相关的快速开始示例 @@ -84,9 +79,9 @@ go run main.go ``` ### 启动并运行一个saga示例 -`go run qs/main.go` +下面运行一个类似跨行转账的示例,包括两个事务分支:资金转出(TransOut)、资金转入(TransIn)。DTM保证TransIn和TransOut要么全部成功,要么全部回滚,保证最终金额的正确性。 -这是一个类似跨行转账的示例,包括两个事务分支:资金转出(TransOut)、资金转入(TransIn)。DTM保证TransIn和TransOut要么全部成功,要么全部回滚,保证最终金额的正确性。 +`go run qs/main.go` ## 接入详解 @@ -117,9 +112,10 @@ go run main.go ### 更多示例 参考[dtm-labs/dtm-examples](https://github.com/dtm-labs/dtm-examples) -## 公众号 -您可以关注公众号:分布式事务,及时跟踪dtm的最新内容 -## 交流群 +## 联系我们 +### 公众号 +dtm官方公众号:分布式事务,大量干货分享,以及dtm的最新消息 +### 交流群 请加 yedf2008 好友或者扫码加好友,验证回复 dtm 按照指引进群 ![yedf2008](http://service.ivydad.com/cover/dubbingb6b5e2c0-2d2a-cd59-f7c5-c6b90aceb6f1.jpeg) diff --git a/README.md b/README.md index 27be69d..cc2c53f 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ DTM是一款golang开发的分布式事务管理器,解决了跨数据库、 他优雅的解决了幂等、空补偿、悬挂等分布式事务难题,提供了简单易用、高性能、易水平扩展的解决方案。 -作者受邀参加中国数据库大会分享[多语言环境下分布式事务实践](http://dtcc.it168.com/yicheng.html#b9) +通俗一点说,DTM提供跨服务事务能力,一组服务要么全部成功,要么全部回滚,避免只更新了一部分数据产生的业务问题。 -## 谁在使用dtm +## 谁在使用DTM(仅列出部分) [Tencent 腾讯](https://dtm.pub/other/using.html#tencent) [Ivydad 常青藤爸爸](https://dtm.pub/other/using.html#ivydad) @@ -23,8 +23,6 @@ DTM是一款golang开发的分布式事务管理器,解决了跨数据库、 [极欧科技](https://dtm.pub/other/using.html) -[金数智联](https://dtm.pub/other/using.html) - ## 亮点 * 极易接入 @@ -34,15 +32,13 @@ DTM是一款golang开发的分布式事务管理器,解决了跨数据库、 * 跨语言 - 可适合多语言栈的公司使用。方便go、python、php、nodejs、ruby、c# 各类语言使用。 * 易部署、易扩展 - - 仅依赖mysql,部署简单,易集群化,易水平扩展 + - 支持零配置,或依赖mysql|redis,部署简单,易集群化,易水平扩展 * 多种分布式事务协议支持 - - TCC、SAGA、XA、事务消息 + - TCC、SAGA、XA、二阶段消息 ## 与其他框架对比 -目前开源的分布式事务框架,Java的框架较多,有大厂开源的SEATA、ServiceComb-Pack,shardingsphere,以及个人开源的himly,tcc-transaction,ByteTCC等等,其中以Seata的应用最为广泛。 - -非Java语言类的,暂未看到除dtm之外的成熟框架,因此这里仅将DTM和Java中最成熟的Seata对比: +非Java语言类的,暂未看到除dtm之外的成熟框架,因此这里将DTM和Java中最成熟的Seata对比: | 特性| DTM | SEATA |备注| |:-----:|:----:|:----:|:----:| @@ -69,31 +65,27 @@ DTM是一款golang开发的分布式事务管理器,解决了跨数据库、 ## 微服务框架支持 - [go-zero](https://github.com/zeromicro/go-zero):一开源就非常火爆的微服务框架,首家接入dtm的微服务框架。感谢go-zero作者[kevwan](https://github.com/kevwan)的大力支持 - [polaris](https://github.com/polarismesh/polaris): 腾讯开源的注册发现组件,以及在其上构建的微服务框架。感谢腾讯同学[ychensha](https://github.com/ychensha)的PR -- 其他:看用户需求量,择机接入 +- 其他:看用户需求量,择机接入,参见[微服务支持](https://dtm.pub/protocol/intro.html) -具体微服务接入使用,参见[微服务支持](https://dtm.pub/protocol/intro.html) ## 快速开始 -### 获取代码 - -`git clone https://github.com/dtm-labs/dtm && cd dtm` +如果您不是Go语言,可以跳转[各语言客户端及示例](https://dtm.pub/summary/code.html#go),里面有相关的快速开始示例 -### dtm依赖于mysql +### 运行dtm -安装[docker 20.04+](https://docs.docker.com/get-docker/)之后 - -`docker-compose -f helper/compose.mysql.yml up` +``` bash +git clone https://github.com/dtm-labs/dtm && cd dtm +go run main.go +``` -> 您也可以配置使用现有的mysql,需要高级权限,允许dtm创建数据库 -> -> `cp conf.sample.yml conf.yml # 修改conf.yml` +### 启动并运行一个saga示例 +下面运行一个类似跨行转账的示例,包括两个事务分支:资金转出(TransOut)、资金转入(TransIn)。DTM保证TransIn和TransOut要么全部成功,要么全部回滚,保证最终金额的正确性。 -### 启动并运行saga示例 -`go run app/main.go qs` +`go run qs/main.go` -## 开始使用 +## 接入详解 -### 使用 +### 接入代码 ``` GO // 具体业务微服务地址 const qsBusi = "http://localhost:8081/api/busi_saga" @@ -117,23 +109,16 @@ DTM是一款golang开发的分布式事务管理器,解决了跨数据库、 -### 完整示例 -参考[examples/quick_start.go](./examples/quick_start.go) +### 更多示例 +参考[dtm-labs/dtm-examples](https://github.com/dtm-labs/dtm-examples) -## 公众号 -您可以关注公众号:分布式事务,及时跟踪dtm的最新内容 -## 交流群 +## 联系我们 +### 公众号 +dtm官方公众号:分布式事务,大量干货分享,以及dtm的最新消息 +### 交流群 请加 yedf2008 好友或者扫码加好友,验证回复 dtm 按照指引进群 ![yedf2008](http://service.ivydad.com/cover/dubbingb6b5e2c0-2d2a-cd59-f7c5-c6b90aceb6f1.jpeg) 欢迎使用[dtm](https://github.com/dtm-labs/dtm),或者通过dtm学习实践分布式事务相关知识,欢迎star支持我们 -## 谁在使用 -
- 腾讯 - 常青藤爸爸 - 镜小二 - 极欧科技 - 金数智联 -
From 0878e8f11400d0d1663b850e07b33256954dec8c Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Thu, 30 Dec 2021 11:57:48 +0800 Subject: [PATCH 12/22] update readme --- README-cn.md | 25 ++++++++++++++++++++----- README.md | 25 ++++++++++++++++++++----- go.mod | 4 +--- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/README-cn.md b/README-cn.md index cc2c53f..66cd490 100644 --- a/README-cn.md +++ b/README-cn.md @@ -26,15 +26,15 @@ DTM是一款golang开发的分布式事务管理器,解决了跨数据库、 ## 亮点 * 极易接入 - - 支持HTTP,提供非常简单的接口,极大降低上手分布式事务的难度,新手也能快速接入 -* 使用简单 - - 开发者不再担心悬挂、空补偿、幂等各类问题,框架层代为处理 + - 零配置启动服务,提供非常简单的HTTP接口,极大降低上手分布式事务的难度,新手也能快速接入 * 跨语言 - 可适合多语言栈的公司使用。方便go、python、php、nodejs、ruby、c# 各类语言使用。 +* 使用简单 + - 开发者不再担心悬挂、空补偿、幂等各类问题,首创子事务屏障技术代为处理 * 易部署、易扩展 - - 支持零配置,或依赖mysql|redis,部署简单,易集群化,易水平扩展 + - 依赖mysql|redis,部署简单,易集群化,易水平扩展 * 多种分布式事务协议支持 - - TCC、SAGA、XA、二阶段消息 + - TCC、SAGA、XA、二阶段消息,一站式解决所有分布式事务问题 ## 与其他框架对比 @@ -109,6 +109,21 @@ go run main.go +### 失败情况 +在实际的业务中,子事务可能出现失败,例如转入的子账号被冻结导致转账失败。我们对业务代码进行修改,让TransIn的正向操作失败,然后看看结果 + +``` go + app.POST(qsBusiAPI+"/TransIn", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + return M{"dtm_result": "FAILURE"}, nil + })) +``` + +再运行这个例子,整个事务最终失败,时序图如下: + +![saga_rollback](https://pic3.zhimg.com/80/v2-8d8f1476be8a1e2e09ce97a89b4116c2_1440w.jpg) + +在转入操作失败的情况下,TransIn和TransOut的补偿操作被执行,保证了最终的余额和转账前是一样的。 + ### 更多示例 参考[dtm-labs/dtm-examples](https://github.com/dtm-labs/dtm-examples) diff --git a/README.md b/README.md index cc2c53f..66cd490 100644 --- a/README.md +++ b/README.md @@ -26,15 +26,15 @@ DTM是一款golang开发的分布式事务管理器,解决了跨数据库、 ## 亮点 * 极易接入 - - 支持HTTP,提供非常简单的接口,极大降低上手分布式事务的难度,新手也能快速接入 -* 使用简单 - - 开发者不再担心悬挂、空补偿、幂等各类问题,框架层代为处理 + - 零配置启动服务,提供非常简单的HTTP接口,极大降低上手分布式事务的难度,新手也能快速接入 * 跨语言 - 可适合多语言栈的公司使用。方便go、python、php、nodejs、ruby、c# 各类语言使用。 +* 使用简单 + - 开发者不再担心悬挂、空补偿、幂等各类问题,首创子事务屏障技术代为处理 * 易部署、易扩展 - - 支持零配置,或依赖mysql|redis,部署简单,易集群化,易水平扩展 + - 依赖mysql|redis,部署简单,易集群化,易水平扩展 * 多种分布式事务协议支持 - - TCC、SAGA、XA、二阶段消息 + - TCC、SAGA、XA、二阶段消息,一站式解决所有分布式事务问题 ## 与其他框架对比 @@ -109,6 +109,21 @@ go run main.go +### 失败情况 +在实际的业务中,子事务可能出现失败,例如转入的子账号被冻结导致转账失败。我们对业务代码进行修改,让TransIn的正向操作失败,然后看看结果 + +``` go + app.POST(qsBusiAPI+"/TransIn", common.WrapHandler(func(c *gin.Context) (interface{}, error) { + return M{"dtm_result": "FAILURE"}, nil + })) +``` + +再运行这个例子,整个事务最终失败,时序图如下: + +![saga_rollback](https://pic3.zhimg.com/80/v2-8d8f1476be8a1e2e09ce97a89b4116c2_1440w.jpg) + +在转入操作失败的情况下,TransIn和TransOut的补偿操作被执行,保证了最终的余额和转账前是一样的。 + ### 更多示例 参考[dtm-labs/dtm-examples](https://github.com/dtm-labs/dtm-examples) diff --git a/go.mod b/go.mod index 9c897a0..0d19a2f 100644 --- a/go.mod +++ b/go.mod @@ -8,11 +8,10 @@ require ( github.com/dtm-labs/dtmdriver-polaris v0.0.2 github.com/dtm-labs/dtmdriver-protocol1 v0.0.1 github.com/gin-gonic/gin v1.6.3 - github.com/go-playground/assert/v2 v2.0.1 + github.com/go-redis/redis/v8 v8.11.4 github.com/go-resty/resty/v2 v2.7.0 github.com/go-sql-driver/mysql v1.6.0 - github.com/google/uuid v1.3.0 github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 github.com/lib/pq v1.10.3 github.com/lithammer/shortuuid v2.0.3+incompatible @@ -32,7 +31,6 @@ require ( gorm.io/driver/mysql v1.0.3 gorm.io/driver/postgres v1.2.1 gorm.io/gorm v1.22.2 - honnef.co/go/tools v0.0.1-2020.1.3 // gotest.tools v2.2.0+incompatible ) From 852731ae3aa4bee386412cdde1305793888e66f4 Mon Sep 17 00:00:00 2001 From: yedf2 <43027375+yedf2@users.noreply.github.com> Date: Thu, 30 Dec 2021 12:13:46 +0800 Subject: [PATCH 13/22] adjust image size --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 66cd490..7d93642 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ go run main.go 上述saga分布式事务的时序图如下: - + ### 失败情况 在实际的业务中,子事务可能出现失败,例如转入的子账号被冻结导致转账失败。我们对业务代码进行修改,让TransIn的正向操作失败,然后看看结果 @@ -120,7 +120,7 @@ go run main.go 再运行这个例子,整个事务最终失败,时序图如下: -![saga_rollback](https://pic3.zhimg.com/80/v2-8d8f1476be8a1e2e09ce97a89b4116c2_1440w.jpg) + 在转入操作失败的情况下,TransIn和TransOut的补偿操作被执行,保证了最终的余额和转账前是一样的。 From a441b6ebc2d800eeb0fa3b0bee481e018e29d43e Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Thu, 30 Dec 2021 14:50:04 +0800 Subject: [PATCH 14/22] try to add brew test --- Formula/dtm.rb | 31 ------------------------------- helper/.goreleaser.yml | 10 ---------- main.go | 4 ++++ qs/main.go | 7 +++---- test/busi/quick_start.go | 2 ++ 5 files changed, 9 insertions(+), 45 deletions(-) delete mode 100644 Formula/dtm.rb diff --git a/Formula/dtm.rb b/Formula/dtm.rb deleted file mode 100644 index 19341e9..0000000 --- a/Formula/dtm.rb +++ /dev/null @@ -1,31 +0,0 @@ -# typed: false -# frozen_string_literal: true - -# This file was generated by GoReleaser. DO NOT EDIT. -class Dtm < Formula - desc "A cross-language distributed transaction manager." - homepage "https://d.dtm.pub" - version "1.8.1" - - on_macos do - if Hardware::CPU.intel? - url "https://github.com/dtm-labs/dtm/releases/download/v1.8.1/dtm_1.8.1_darwin_amd64.tar.gz" - sha256 "8277820eac478f48fd6770f41eb2ec674dac1eddc66e4ebbd9c73eb41ae39548" - - def install - bin.install "dtm" - end - end - end - - on_linux do - if Hardware::CPU.intel? - url "https://github.com/dtm-labs/dtm/releases/download/v1.8.1/dtm_1.8.1_linux_amd64.tar.gz" - sha256 "ce83774f50b9f121c5f54baf657555053f817af9efccb50d80a9854b7579807a" - - def install - bin.install "dtm" - end - end - end -end diff --git a/helper/.goreleaser.yml b/helper/.goreleaser.yml index 218bced..daee966 100644 --- a/helper/.goreleaser.yml +++ b/helper/.goreleaser.yml @@ -13,13 +13,3 @@ builds: main: main.go ldflags: - -s -w -X main.Version={{.Version}} -X main.Commit={{.Commit}} -X main.Date={{.Date}} -brews: - - homepage: 'https://d.dtm.pub' - description: 'A cross-language distributed transaction manager.' - folder: Formula - commit_author: - name: dtm-labs - email: 120050102@qq.com - tap: - owner: dtm-labs - name: dtm diff --git a/main.go b/main.go index 4308f4a..ab781c2 100644 --- a/main.go +++ b/main.go @@ -49,6 +49,7 @@ func usage() { var isVersion = flag.Bool("v", false, "Show the version of dtm.") var isDebug = flag.Bool("d", false, "Set log level to debug.") var isHelp = flag.Bool("h", false, "Show the help information about etcd.") +var isReset = flag.Bool("r", false, "Reset dtm server data.") var confFile = flag.String("c", "", "Path to the server configuration file.") func main() { @@ -64,6 +65,9 @@ func main() { if *isDebug { config.Config.LogLevel = "debug" } + if *isReset { + dtmsvr.PopulateDB(false) + } maxprocs.Set(maxprocs.Logger(logger.Infof)) registry.WaitStoreUp() dtmsvr.StartSvr() // 启动dtmsvr的api服务 diff --git a/qs/main.go b/qs/main.go index f31d83a..4cf0586 100644 --- a/qs/main.go +++ b/qs/main.go @@ -7,13 +7,12 @@ package main import ( - "time" - + "github.com/dtm-labs/dtm/dtmcli/logger" "github.com/dtm-labs/dtm/test/busi" ) func main() { busi.QsStartSvr() - busi.QsFireRequest() - time.Sleep(1 * time.Second) + gid := busi.QsFireRequest() + logger.Infof("transaction: %s succeed", gid) } diff --git a/test/busi/quick_start.go b/test/busi/quick_start.go index 3fd9616..8e12cb9 100644 --- a/test/busi/quick_start.go +++ b/test/busi/quick_start.go @@ -40,6 +40,8 @@ func QsFireRequest() string { Add(qsBusi+"/TransOut", qsBusi+"/TransOutCompensate", req). // 添加一个TransIn的子事务,正向操作为url: qsBusi+"/TransOut", 逆向操作为url: qsBusi+"/TransInCompensate" Add(qsBusi+"/TransIn", qsBusi+"/TransInCompensate", req) + // 等待事务全部完成后再返回,可选 + saga.WaitResult = true // 提交saga事务,dtm会完成所有的子事务/回滚所有的子事务 err := saga.Submit() logger.FatalIfError(err) From 6f8af2b7e1ace840edc55a35d423491ece8019be Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Thu, 30 Dec 2021 16:12:09 +0800 Subject: [PATCH 15/22] update version --- .gitignore | 3 ++- helper/.goreleaser.yml | 2 +- main.go | 9 ++------- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index e89d163..34e44f0 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,5 @@ coverage.* profile.* test.sh dtm -dtm.* \ No newline at end of file +dtm-* +dtm.* diff --git a/helper/.goreleaser.yml b/helper/.goreleaser.yml index daee966..5c5a639 100644 --- a/helper/.goreleaser.yml +++ b/helper/.goreleaser.yml @@ -12,4 +12,4 @@ builds: dir: . main: main.go ldflags: - - -s -w -X main.Version={{.Version}} -X main.Commit={{.Commit}} -X main.Date={{.Date}} + - -s -w -X main.Version={{.Version}} diff --git a/main.go b/main.go index ab781c2..013441d 100644 --- a/main.go +++ b/main.go @@ -25,18 +25,13 @@ import ( _ "github.com/dtm-labs/dtmdriver-protocol1" ) -var Version, Commit, Date string +var Version string func version() { if Version == "" { Version = "0.0.0-dev" - Commit = "NA" - Date = "NA" } - if len(Commit) > 8 { - Commit = Commit[:8] - } - fmt.Printf("version: %s commit: %s built at: %s\n", Version, Commit, Date) + fmt.Printf("dtm version: %s\n", Version) } func usage() { From 57f42800a5122fb0676df3ac0913c5da6ba5e0b5 Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Thu, 30 Dec 2021 16:30:10 +0800 Subject: [PATCH 16/22] update readme --- README-cn.md | 2 -- README.md | 6 ++---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/README-cn.md b/README-cn.md index 66cd490..a339308 100644 --- a/README-cn.md +++ b/README-cn.md @@ -12,8 +12,6 @@ DTM是一款golang开发的分布式事务管理器,解决了跨数据库、 他优雅的解决了幂等、空补偿、悬挂等分布式事务难题,提供了简单易用、高性能、易水平扩展的解决方案。 -通俗一点说,DTM提供跨服务事务能力,一组服务要么全部成功,要么全部回滚,避免只更新了一部分数据产生的业务问题。 - ## 谁在使用DTM(仅列出部分) [Tencent 腾讯](https://dtm.pub/other/using.html#tencent) diff --git a/README.md b/README.md index 7d93642..a339308 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,6 @@ DTM是一款golang开发的分布式事务管理器,解决了跨数据库、 他优雅的解决了幂等、空补偿、悬挂等分布式事务难题,提供了简单易用、高性能、易水平扩展的解决方案。 -通俗一点说,DTM提供跨服务事务能力,一组服务要么全部成功,要么全部回滚,避免只更新了一部分数据产生的业务问题。 - ## 谁在使用DTM(仅列出部分) [Tencent 腾讯](https://dtm.pub/other/using.html#tencent) @@ -107,7 +105,7 @@ go run main.go 上述saga分布式事务的时序图如下: - + ### 失败情况 在实际的业务中,子事务可能出现失败,例如转入的子账号被冻结导致转账失败。我们对业务代码进行修改,让TransIn的正向操作失败,然后看看结果 @@ -120,7 +118,7 @@ go run main.go 再运行这个例子,整个事务最终失败,时序图如下: - +![saga_rollback](https://pic3.zhimg.com/80/v2-8d8f1476be8a1e2e09ce97a89b4116c2_1440w.jpg) 在转入操作失败的情况下,TransIn和TransOut的补偿操作被执行,保证了最终的余额和转账前是一样的。 From af56f3db1efa670f717358524caeb088e1c1ab7d Mon Sep 17 00:00:00 2001 From: jxlwqq Date: Fri, 31 Dec 2021 11:25:36 +0800 Subject: [PATCH 17/22] use ENTRYPOINT instead of CMD --- helper/Dockerfile-release | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helper/Dockerfile-release b/helper/Dockerfile-release index acf6846..0dd5bf1 100644 --- a/helper/Dockerfile-release +++ b/helper/Dockerfile-release @@ -12,4 +12,4 @@ FROM --platform=$TARGETPLATFORM alpine:3.14 COPY --from=builder /app/dtm/dtm /app/dtm/ ENV IS_DOCKER=1 WORKDIR /app/dtm -CMD ["/app/dtm/dtm"] +ENTRYPOINT ["/app/dtm/dtm"] From 09ae1cdaa25a9fa1d19f31d72671cc851f64293b Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Sat, 1 Jan 2022 11:28:42 +0800 Subject: [PATCH 18/22] support headers --- bench/svr/http.go | 8 +- conf.sample.yml | 11 +- dtmcli/barrier.go | 2 +- dtmcli/dtmimp/trans_base.go | 23 ++-- dtmcli/dtmimp/vars.go | 8 +- dtmcli/tcc.go | 6 + dtmcli/types.go | 23 ++++ dtmcli/types_test.go | 1 + dtmcli/xa.go | 12 +- dtmgrpc/dtmgimp/grpc_clients.go | 7 +- dtmgrpc/dtmgimp/utils.go | 45 +++++-- dtmgrpc/dtmgpb/dtmgimp.pb.go | 197 ++++++++++++++++++------------- dtmgrpc/dtmgpb/dtmgimp.proto | 2 + dtmgrpc/tcc.go | 23 ++-- dtmgrpc/type.go | 17 +-- dtmgrpc/type_test.go | 5 - dtmgrpc/xa.go | 10 +- dtmsvr/api_grpc.go | 6 +- dtmsvr/config/config.go | 24 ++-- dtmsvr/config/config_test.go | 43 ++++--- dtmsvr/config/config_utils.go | 22 ++-- dtmsvr/storage/trans.go | 12 +- dtmsvr/trans_class.go | 31 ++++- dtmsvr/trans_process.go | 7 ++ dtmsvr/trans_status.go | 6 + go.mod | 1 - go.sum | 6 + helper/sync-dtmcli.sh | 2 - sqls/dtmsvr.storage.mysql.sql | 4 +- sqls/dtmsvr.storage.postgres.sql | 4 +- test/busi/base_grpc.go | 17 +++ test/busi/base_http.go | 14 +++ test/busi/busi.pb.go | 56 +++++---- test/busi/busi.proto | 2 + test/busi/busi_grpc.pb.go | 72 +++++++++++ test/busi/utils.go | 28 ++++- test/dtmsvr_test.go | 3 +- test/main_test.go | 4 + test/msg_grpc_test.go | 3 +- test/msg_options_test.go | 9 +- test/msg_test.go | 5 +- test/saga_concurrent_test.go | 6 +- test/saga_cover_test.go | 11 ++ test/saga_grpc_test.go | 74 +++++++++++- test/saga_options_test.go | 85 +++++++++++-- test/saga_test.go | 8 +- test/tcc_cover_test.go | 1 + test/tcc_grpc_cover_test.go | 3 + test/tcc_grpc_test.go | 22 +++- test/tcc_test.go | 19 ++- test/types.go | 18 +-- test/xa_cover_test.go | 3 +- test/xa_grpc_test.go | 8 +- test/xa_test.go | 3 +- 54 files changed, 779 insertions(+), 263 deletions(-) create mode 100644 test/saga_cover_test.go diff --git a/bench/svr/http.go b/bench/svr/http.go index d1c8978..92fd44d 100644 --- a/bench/svr/http.go +++ b/bench/svr/http.go @@ -33,14 +33,14 @@ const total = 200000 var benchPort = dtmimp.If(os.Getenv("BENCH_PORT") == "", "8083", os.Getenv("BENCH_PORT")).(string) var benchBusi = fmt.Sprintf("http://localhost:%s%s", benchPort, benchAPI) -func sdbGet() *sql.DB { +func pdbGet() *sql.DB { db, err := dtmimp.PooledDB(busi.BusiConf) logger.FatalIfError(err) return db } func txGet() *sql.Tx { - db := sdbGet() + db := pdbGet() tx, err := db.Begin() logger.FatalIfError(err) return tx @@ -49,7 +49,7 @@ func txGet() *sql.Tx { func reloadData() { time.Sleep(dtmsvr.UpdateBranchAsyncInterval * 2) began := time.Now() - db := sdbGet() + db := pdbGet() tables := []string{"dtm_busi.user_account", "dtm_busi.user_account_log", "dtm.trans_global", "dtm.trans_branch_op", "dtm_barrier.barrier"} for _, t := range tables { _, err := dtmimp.DBExec(db, fmt.Sprintf("truncate %s", t)) @@ -70,7 +70,7 @@ var mode string = "" var sqls int = 1 func PrepareBenchDB() { - db := sdbGet() + db := pdbGet() _, err := dtmimp.DBExec(db, "drop table if exists dtm_busi.user_account_log") logger.FatalIfError(err) _, err = dtmimp.DBExec(db, `create table if not exists dtm_busi.user_account_log ( diff --git a/conf.sample.yml b/conf.sample.yml index 8dee2ea..807d582 100644 --- a/conf.sample.yml +++ b/conf.sample.yml @@ -1,3 +1,10 @@ +##################################################################### +### dtm can be run without any config. +### all config in this file is optional. the default value is as specified in each line +### all configs can be specified from env. for example: +### Store.MaxOpenConns can also specified from env: STORE_MAX_OPEN_CONNS +##################################################################### + # Store: # specify which engine to store trans status # Driver: 'boltdb' # default store engine @@ -19,10 +26,12 @@ # Password: 'mysecretpassword' # Port: '5432' -### following connection config is for only Driver postgres/mysql +### following config is for only Driver postgres/mysql # MaxOpenConns: 500 # MaxIdleConns: 500 # ConnMaxLifeTime 5 # default value is 5 (minutes) +# TransGlobalTable: 'dtm.trans_global' +# TransBranchOp: 'dtm.trans_branch_op' ### flollowing config is only for some Driver # DataExpire: 604800 # Trans data will expire in 7 days. only for redis/boltdb. diff --git a/dtmcli/barrier.go b/dtmcli/barrier.go index ff14336..62f59b2 100644 --- a/dtmcli/barrier.go +++ b/dtmcli/barrier.go @@ -54,7 +54,7 @@ func insertBarrier(tx DB, transType string, gid string, branchID string, op stri if op == "" { return 0, nil } - sql := dtmimp.GetDBSpecial().GetInsertIgnoreTemplate("dtm_barrier.barrier(trans_type, gid, branch_id, op, barrier_id, reason) values(?,?,?,?,?,?)", "uniq_barrier") + sql := dtmimp.GetDBSpecial().GetInsertIgnoreTemplate(dtmimp.BarrierTableName+"(trans_type, gid, branch_id, op, barrier_id, reason) values(?,?,?,?,?,?)", "uniq_barrier") return dtmimp.DBExec(tx, sql, transType, gid, branchID, op, barrierID, reason) } diff --git a/dtmcli/dtmimp/trans_base.go b/dtmcli/dtmimp/trans_base.go index b050064..9c89a9f 100644 --- a/dtmcli/dtmimp/trans_base.go +++ b/dtmcli/dtmimp/trans_base.go @@ -40,9 +40,11 @@ func (g *BranchIDGen) CurrentSubBranchID() string { // TransOptions transaction options type TransOptions struct { - WaitResult bool `json:"wait_result,omitempty" gorm:"-"` - TimeoutToFail int64 `json:"timeout_to_fail,omitempty" gorm:"-"` // for trans type: xa, tcc - RetryInterval int64 `json:"retry_interval,omitempty" gorm:"-"` // for trans type: msg saga xa tcc + WaitResult bool `json:"wait_result,omitempty" gorm:"-"` + TimeoutToFail int64 `json:"timeout_to_fail,omitempty" gorm:"-"` // for trans type: xa, tcc + RetryInterval int64 `json:"retry_interval,omitempty" gorm:"-"` // for trans type: msg saga xa tcc + PassthroughHeaders []string `json:"passthrough_headers,omitempty" gorm:"-"` + BranchHeaders map[string]string `json:"branch_headers,omitempty" gorm:"-"` } // TransBase base for all trans @@ -62,18 +64,14 @@ type TransBase struct { QueryPrepared string `json:"query_prepared,omitempty"` // used in MSG } -// SetOptions set options -func (tb *TransBase) SetOptions(options *TransOptions) { - tb.TransOptions = *options -} - // NewTransBase new a TransBase func NewTransBase(gid string, transType string, dtm string, branchID string) *TransBase { return &TransBase{ - Gid: gid, - TransType: transType, - BranchIDGen: BranchIDGen{BranchID: branchID}, - Dtm: dtm, + Gid: gid, + TransType: transType, + BranchIDGen: BranchIDGen{BranchID: branchID}, + Dtm: dtm, + TransOptions: TransOptions{PassthroughHeaders: PassthroughHeaders}, } } @@ -118,6 +116,7 @@ func TransRequestBranch(t *TransBase, body interface{}, branchID string, op stri "trans_type": t.TransType, "op": op, }). + SetHeaders(t.BranchHeaders). Post(url) return resp, CheckResponse(resp, err) } diff --git a/dtmcli/dtmimp/vars.go b/dtmcli/dtmimp/vars.go index eea02ad..fc51d70 100644 --- a/dtmcli/dtmimp/vars.go +++ b/dtmcli/dtmimp/vars.go @@ -31,13 +31,19 @@ var MapFailure = map[string]interface{}{"dtm_result": ResultFailure} // RestyClient the resty object var RestyClient = resty.New() +// PassthroughHeaders will be passed to every sub-trans call +var PassthroughHeaders = []string{} + +// BarrierTableName the table name of barrier table +var BarrierTableName = "dtm_barrier.barrier" + func init() { // RestyClient.SetTimeout(3 * time.Second) // RestyClient.SetRetryCount(2) // RestyClient.SetRetryWaitTime(1 * time.Second) RestyClient.OnBeforeRequest(func(c *resty.Client, r *resty.Request) error { r.URL = MayReplaceLocalhost(r.URL) - logger.Debugf("requesting: %s %s %v %v", r.Method, r.URL, r.Body, r.QueryParam) + logger.Debugf("requesting: %s %s %s", r.Method, r.URL, MustMarshalString(r.Body)) return nil }) RestyClient.OnAfterResponse(func(c *resty.Client, resp *resty.Response) error { diff --git a/dtmcli/tcc.go b/dtmcli/tcc.go index 73d1172..d61a7fe 100644 --- a/dtmcli/tcc.go +++ b/dtmcli/tcc.go @@ -27,7 +27,13 @@ type TccGlobalFunc func(tcc *Tcc) (*resty.Response, error) // gid global transaction ID // tccFunc tcc事务函数,里面会定义全局事务的分支 func TccGlobalTransaction(dtm string, gid string, tccFunc TccGlobalFunc) (rerr error) { + return TccGlobalTransaction2(dtm, gid, func(t *Tcc) {}, tccFunc) +} + +// TccGlobalTransaction2 new version of TccGlobalTransaction, add custom param +func TccGlobalTransaction2(dtm string, gid string, custom func(*Tcc), tccFunc TccGlobalFunc) (rerr error) { tcc := &Tcc{TransBase: *dtmimp.NewTransBase(gid, "tcc", dtm, "")} + custom(tcc) rerr = dtmimp.TransCallDtm(&tcc.TransBase, tcc, "prepare") if rerr != nil { return rerr diff --git a/dtmcli/types.go b/dtmcli/types.go index e0e54e2..482651a 100644 --- a/dtmcli/types.go +++ b/dtmcli/types.go @@ -10,6 +10,7 @@ import ( "fmt" "github.com/dtm-labs/dtm/dtmcli/dtmimp" + "github.com/go-resty/resty/v2" ) // MustGenGid generate a new gid @@ -49,3 +50,25 @@ func SetXaSqlTimeoutMs(ms int) { func GetXaSqlTimeoutMs() int { return dtmimp.XaSqlTimeoutMs } + +func SetBarrierTableName(tablename string) { + dtmimp.BarrierTableName = tablename +} + +// OnBeforeRequest add before request middleware +func OnBeforeRequest(middleware func(c *resty.Client, r *resty.Request) error) { + dtmimp.RestyClient.OnBeforeRequest(middleware) +} + +// OnAfterResponse add after request middleware +func OnAfterResponse(middleware func(c *resty.Client, resp *resty.Response) error) { + dtmimp.RestyClient.OnAfterResponse(middleware) +} + +// SetPassthroughHeaders experimental. +// apply to http header and grpc metadata +// dtm server will save these headers in trans creating request. +// and then passthrough them to sub-trans +func SetPassthroughHeaders(headers []string) { + dtmimp.PassthroughHeaders = headers +} diff --git a/dtmcli/types_test.go b/dtmcli/types_test.go index b37ba9a..269c54b 100644 --- a/dtmcli/types_test.go +++ b/dtmcli/types_test.go @@ -28,4 +28,5 @@ func TestTypes(t *testing.T) { func TestXaSqlTimeout(t *testing.T) { old := GetXaSqlTimeoutMs() SetXaSqlTimeoutMs(old) + SetBarrierTableName(dtmimp.BarrierTableName) // just cover this func } diff --git a/dtmcli/xa.go b/dtmcli/xa.go index d28bed7..c74b4d1 100644 --- a/dtmcli/xa.go +++ b/dtmcli/xa.go @@ -83,11 +83,17 @@ func (xc *XaClient) XaLocalTransaction(qs url.Values, xaFunc XaLocalFunc) error // XaGlobalTransaction start a xa global transaction func (xc *XaClient) XaGlobalTransaction(gid string, xaFunc XaGlobalFunc) (rerr error) { - xa := Xa{TransBase: *dtmimp.NewTransBase(gid, "xa", xc.XaClientBase.Server, "")} + return xc.XaGlobalTransaction2(gid, func(x *Xa) {}, xaFunc) +} + +// XaGlobalTransaction start a xa global transaction +func (xc *XaClient) XaGlobalTransaction2(gid string, custom func(*Xa), xaFunc XaGlobalFunc) (rerr error) { + xa := &Xa{TransBase: *dtmimp.NewTransBase(gid, "xa", xc.XaClientBase.Server, "")} + custom(xa) return xc.HandleGlobalTrans(&xa.TransBase, func(action string) error { - return dtmimp.TransCallDtm(&xa.TransBase, &xa, action) + return dtmimp.TransCallDtm(&xa.TransBase, xa, action) }, func() error { - _, rerr := xaFunc(&xa) + _, rerr := xaFunc(xa) return rerr }) } diff --git a/dtmgrpc/dtmgimp/grpc_clients.go b/dtmgrpc/dtmgimp/grpc_clients.go index d2c63a0..dc21e81 100644 --- a/dtmgrpc/dtmgimp/grpc_clients.go +++ b/dtmgrpc/dtmgimp/grpc_clients.go @@ -13,6 +13,7 @@ import ( "github.com/dtm-labs/dtm/dtmcli/dtmimp" "github.com/dtm-labs/dtm/dtmcli/logger" "github.com/dtm-labs/dtm/dtmgrpc/dtmgpb" + grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" grpc "google.golang.org/grpc" ) @@ -35,6 +36,8 @@ func (cb rawCodec) Name() string { return "dtm_raw" } var normalClients, rawClients sync.Map +var ClientInterceptors = []grpc.UnaryClientInterceptor{} + // MustGetDtmClient 1 func MustGetDtmClient(grpcServer string) dtmgpb.DtmClient { return dtmgpb.NewDtmClient(MustGetGrpcConn(grpcServer, false)) @@ -59,7 +62,9 @@ func GetGrpcConn(grpcServer string, isRaw bool) (conn *grpc.ClientConn, rerr err opts = grpc.WithDefaultCallOptions(grpc.ForceCodec(rawCodec{})) } logger.Debugf("grpc client connecting %s", grpcServer) - conn, rerr := grpc.Dial(grpcServer, grpc.WithInsecure(), grpc.WithUnaryInterceptor(GrpcClientLog), opts) + interceptors := append(ClientInterceptors, GrpcClientLog) + inOpt := grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(interceptors...)) + conn, rerr := grpc.Dial(grpcServer, inOpt, grpc.WithInsecure(), opts) if rerr == nil { clients.Store(grpcServer, conn) v = conn diff --git a/dtmgrpc/dtmgimp/utils.go b/dtmgrpc/dtmgimp/utils.go index bb49f39..fb3eadf 100644 --- a/dtmgrpc/dtmgimp/utils.go +++ b/dtmgrpc/dtmgimp/utils.go @@ -31,9 +31,11 @@ func DtmGrpcCall(s *dtmimp.TransBase, operation string) error { Gid: s.Gid, TransType: s.TransType, TransOptions: &dtmgpb.DtmTransOptions{ - WaitResult: s.WaitResult, - TimeoutToFail: s.TimeoutToFail, - RetryInterval: s.RetryInterval, + WaitResult: s.WaitResult, + TimeoutToFail: s.TimeoutToFail, + RetryInterval: s.RetryInterval, + PassthroughHeaders: s.PassthroughHeaders, + BranchHeaders: s.BranchHeaders, }, QueryPrepared: s.QueryPrepared, CustomedData: s.CustomData, @@ -42,20 +44,29 @@ func DtmGrpcCall(s *dtmimp.TransBase, operation string) error { }, &reply) } -const mdpre string = "dtm-" +const dtmpre string = "dtm-" // TransInfo2Ctx add trans info to grpc context func TransInfo2Ctx(gid, transType, branchID, op, dtm string) context.Context { md := metadata.Pairs( - mdpre+"gid", gid, - mdpre+"trans_type", transType, - mdpre+"branch_id", branchID, - mdpre+"op", op, - mdpre+"dtm", dtm, + dtmpre+"gid", gid, + dtmpre+"trans_type", transType, + dtmpre+"branch_id", branchID, + dtmpre+"op", op, + dtmpre+"dtm", dtm, ) return metadata.NewOutgoingContext(context.Background(), md) } +// Map2Kvs map to metadata kv +func Map2Kvs(m map[string]string) []string { + kvs := []string{} + for k, v := range m { + kvs = append(kvs, k, v) + } + return kvs +} + // LogDtmCtx logout dtm info in context metadata func LogDtmCtx(ctx context.Context) { tb := TransBaseFromGrpc(ctx) @@ -64,8 +75,12 @@ func LogDtmCtx(ctx context.Context) { } } +func dtmGet(md metadata.MD, key string) string { + return mdGet(md, dtmpre+key) +} + func mdGet(md metadata.MD, key string) string { - v := md.Get(mdpre + key) + v := md.Get(key) if len(v) == 0 { return "" } @@ -75,7 +90,13 @@ func mdGet(md metadata.MD, key string) string { // TransBaseFromGrpc get trans base info from a context metadata func TransBaseFromGrpc(ctx context.Context) *dtmimp.TransBase { md, _ := metadata.FromIncomingContext(ctx) - tb := dtmimp.NewTransBase(mdGet(md, "gid"), mdGet(md, "trans_type"), mdGet(md, "dtm"), mdGet(md, "branch_id")) - tb.Op = mdGet(md, "op") + tb := dtmimp.NewTransBase(dtmGet(md, "gid"), dtmGet(md, "trans_type"), dtmGet(md, "dtm"), dtmGet(md, "branch_id")) + tb.Op = dtmGet(md, "op") return tb } + +// GetMetaFromContext get header from context +func GetMetaFromContext(ctx context.Context, name string) string { + md, _ := metadata.FromIncomingContext(ctx) + return mdGet(md, name) +} diff --git a/dtmgrpc/dtmgpb/dtmgimp.pb.go b/dtmgrpc/dtmgpb/dtmgimp.pb.go index 89a2526..9247260 100644 --- a/dtmgrpc/dtmgpb/dtmgimp.pb.go +++ b/dtmgrpc/dtmgpb/dtmgimp.pb.go @@ -26,9 +26,11 @@ type DtmTransOptions struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - WaitResult bool `protobuf:"varint,1,opt,name=WaitResult,proto3" json:"WaitResult,omitempty"` - TimeoutToFail int64 `protobuf:"varint,2,opt,name=TimeoutToFail,proto3" json:"TimeoutToFail,omitempty"` - RetryInterval int64 `protobuf:"varint,3,opt,name=RetryInterval,proto3" json:"RetryInterval,omitempty"` + WaitResult bool `protobuf:"varint,1,opt,name=WaitResult,proto3" json:"WaitResult,omitempty"` + TimeoutToFail int64 `protobuf:"varint,2,opt,name=TimeoutToFail,proto3" json:"TimeoutToFail,omitempty"` + RetryInterval int64 `protobuf:"varint,3,opt,name=RetryInterval,proto3" json:"RetryInterval,omitempty"` + 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"` } func (x *DtmTransOptions) Reset() { @@ -84,6 +86,20 @@ func (x *DtmTransOptions) GetRetryInterval() int64 { return 0 } +func (x *DtmTransOptions) GetPassthroughHeaders() []string { + if x != nil { + return x.PassthroughHeaders + } + return nil +} + +func (x *DtmTransOptions) GetBranchHeaders() map[string]string { + if x != nil { + return x.BranchHeaders + } + return nil +} + // DtmRequest request sent to dtm server type DtmRequest struct { state protoimpl.MessageState @@ -321,69 +337,82 @@ 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, 0x7d, 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, 0x6f, - 0x75, 0x74, 0x54, 0x6f, 0x46, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, - 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x54, 0x6f, 0x46, 0x61, 0x69, 0x6c, 0x12, 0x24, 0x0a, - 0x0d, 0x52, 0x65, 0x74, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x52, 0x65, 0x74, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x76, 0x61, 0x6c, 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, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc2, 0x02, 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, + 0x6f, 0x75, 0x74, 0x54, 0x6f, 0x46, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0d, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x54, 0x6f, 0x46, 0x61, 0x69, 0x6c, 0x12, 0x24, + 0x0a, 0x0d, 0x52, 0x65, 0x74, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x52, 0x65, 0x74, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x12, 0x2e, 0x0a, 0x12, 0x50, 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, 0x6f, + 0x75, 0x67, 0x68, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x12, 0x50, 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x73, 0x12, 0x51, 0x0a, 0x0d, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x64, 0x74, + 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 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, 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, + 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, 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, 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 ( @@ -398,33 +427,35 @@ func file_dtmgrpc_dtmgpb_dtmgimp_proto_rawDescGZIP() []byte { return file_dtmgrpc_dtmgpb_dtmgimp_proto_rawDescData } -var file_dtmgrpc_dtmgpb_dtmgimp_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_dtmgrpc_dtmgpb_dtmgimp_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_dtmgrpc_dtmgpb_dtmgimp_proto_goTypes = []interface{}{ (*DtmTransOptions)(nil), // 0: dtmgimp.DtmTransOptions (*DtmRequest)(nil), // 1: dtmgimp.DtmRequest (*DtmGidReply)(nil), // 2: dtmgimp.DtmGidReply (*DtmBranchRequest)(nil), // 3: dtmgimp.DtmBranchRequest - nil, // 4: dtmgimp.DtmBranchRequest.DataEntry - (*emptypb.Empty)(nil), // 5: google.protobuf.Empty + nil, // 4: dtmgimp.DtmTransOptions.BranchHeadersEntry + nil, // 5: dtmgimp.DtmBranchRequest.DataEntry + (*emptypb.Empty)(nil), // 6: google.protobuf.Empty } var file_dtmgrpc_dtmgpb_dtmgimp_proto_depIdxs = []int32{ - 0, // 0: dtmgimp.DtmRequest.TransOptions:type_name -> dtmgimp.DtmTransOptions - 4, // 1: dtmgimp.DtmBranchRequest.Data:type_name -> dtmgimp.DtmBranchRequest.DataEntry - 5, // 2: dtmgimp.Dtm.NewGid:input_type -> google.protobuf.Empty - 1, // 3: dtmgimp.Dtm.Submit:input_type -> dtmgimp.DtmRequest - 1, // 4: dtmgimp.Dtm.Prepare:input_type -> dtmgimp.DtmRequest - 1, // 5: dtmgimp.Dtm.Abort:input_type -> dtmgimp.DtmRequest - 3, // 6: dtmgimp.Dtm.RegisterBranch:input_type -> dtmgimp.DtmBranchRequest - 2, // 7: dtmgimp.Dtm.NewGid:output_type -> dtmgimp.DtmGidReply - 5, // 8: dtmgimp.Dtm.Submit:output_type -> google.protobuf.Empty - 5, // 9: dtmgimp.Dtm.Prepare:output_type -> google.protobuf.Empty - 5, // 10: dtmgimp.Dtm.Abort:output_type -> google.protobuf.Empty - 5, // 11: dtmgimp.Dtm.RegisterBranch:output_type -> google.protobuf.Empty - 7, // [7:12] is the sub-list for method output_type - 2, // [2:7] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name + 4, // 0: dtmgimp.DtmTransOptions.BranchHeaders:type_name -> dtmgimp.DtmTransOptions.BranchHeadersEntry + 0, // 1: dtmgimp.DtmRequest.TransOptions:type_name -> dtmgimp.DtmTransOptions + 5, // 2: dtmgimp.DtmBranchRequest.Data:type_name -> dtmgimp.DtmBranchRequest.DataEntry + 6, // 3: dtmgimp.Dtm.NewGid:input_type -> google.protobuf.Empty + 1, // 4: dtmgimp.Dtm.Submit:input_type -> dtmgimp.DtmRequest + 1, // 5: dtmgimp.Dtm.Prepare:input_type -> dtmgimp.DtmRequest + 1, // 6: dtmgimp.Dtm.Abort:input_type -> dtmgimp.DtmRequest + 3, // 7: dtmgimp.Dtm.RegisterBranch:input_type -> dtmgimp.DtmBranchRequest + 2, // 8: dtmgimp.Dtm.NewGid:output_type -> dtmgimp.DtmGidReply + 6, // 9: dtmgimp.Dtm.Submit:output_type -> google.protobuf.Empty + 6, // 10: dtmgimp.Dtm.Prepare:output_type -> google.protobuf.Empty + 6, // 11: dtmgimp.Dtm.Abort:output_type -> google.protobuf.Empty + 6, // 12: dtmgimp.Dtm.RegisterBranch:output_type -> google.protobuf.Empty + 8, // [8:13] is the sub-list for method output_type + 3, // [3:8] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name } func init() { file_dtmgrpc_dtmgpb_dtmgimp_proto_init() } @@ -488,7 +519,7 @@ func file_dtmgrpc_dtmgpb_dtmgimp_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_dtmgrpc_dtmgpb_dtmgimp_proto_rawDesc, NumEnums: 0, - NumMessages: 5, + NumMessages: 6, NumExtensions: 0, NumServices: 1, }, diff --git a/dtmgrpc/dtmgpb/dtmgimp.proto b/dtmgrpc/dtmgpb/dtmgimp.proto index 84e3105..f97b277 100644 --- a/dtmgrpc/dtmgpb/dtmgimp.proto +++ b/dtmgrpc/dtmgpb/dtmgimp.proto @@ -18,6 +18,8 @@ message DtmTransOptions { bool WaitResult = 1; int64 TimeoutToFail = 2; int64 RetryInterval = 3; + repeated string PassthroughHeaders = 4; + map BranchHeaders = 5; } // DtmRequest request sent to dtm server diff --git a/dtmgrpc/tcc.go b/dtmgrpc/tcc.go index d4c0592..3f39676 100644 --- a/dtmgrpc/tcc.go +++ b/dtmgrpc/tcc.go @@ -14,6 +14,7 @@ import ( "github.com/dtm-labs/dtm/dtmgrpc/dtmgimp" "github.com/dtm-labs/dtm/dtmgrpc/dtmgpb" "github.com/dtm-labs/dtmdriver" + "google.golang.org/grpc/metadata" "google.golang.org/protobuf/proto" ) @@ -30,13 +31,14 @@ type TccGlobalFunc func(tcc *TccGrpc) error // gid 全局事务id // tccFunc tcc事务函数,里面会定义全局事务的分支 func TccGlobalTransaction(dtm string, gid string, tccFunc TccGlobalFunc) (rerr error) { + return TccGlobalTransaction2(dtm, gid, func(tg *TccGrpc) {}, tccFunc) +} + +// TccGlobalTransaction2 new version of TccGlobalTransaction +func TccGlobalTransaction2(dtm string, gid string, custom func(*TccGrpc), tccFunc TccGlobalFunc) (rerr error) { tcc := &TccGrpc{TransBase: *dtmimp.NewTransBase(gid, "tcc", dtm, "")} - dc := dtmgimp.MustGetDtmClient(tcc.Dtm) - dr := &dtmgpb.DtmRequest{ - Gid: tcc.Gid, - TransType: tcc.TransType, - } - _, rerr = dc.Prepare(context.Background(), dr) + custom(tcc) + rerr = dtmgimp.DtmGrpcCall(&tcc.TransBase, "Prepare") if rerr != nil { return rerr } @@ -44,10 +46,10 @@ func TccGlobalTransaction(dtm string, gid string, tccFunc TccGlobalFunc) (rerr e defer func() { x := recover() if x == nil && rerr == nil { - _, rerr = dc.Submit(context.Background(), dr) + rerr = dtmgimp.DtmGrpcCall(&tcc.TransBase, "Submit") return } - _, err := dc.Abort(context.Background(), dr) + err := dtmgimp.DtmGrpcCall(&tcc.TransBase, "Abort") if rerr == nil { rerr = err } @@ -87,6 +89,7 @@ func (t *TccGrpc) CallBranch(busiMsg proto.Message, tryURL string, confirmURL st if err != nil { return err } - return dtmgimp.MustGetGrpcConn(server, false).Invoke( - dtmgimp.TransInfo2Ctx(t.Gid, t.TransType, branchID, "try", t.Dtm), method, busiMsg, reply) + ctx := dtmgimp.TransInfo2Ctx(t.Gid, t.TransType, branchID, "try", t.Dtm) + ctx = metadata.AppendToOutgoingContext(ctx, dtmgimp.Map2Kvs(t.BranchHeaders)...) + return dtmgimp.MustGetGrpcConn(server, false).Invoke(ctx, method, busiMsg, reply) } diff --git a/dtmgrpc/type.go b/dtmgrpc/type.go index c2b7fa7..d166b5c 100644 --- a/dtmgrpc/type.go +++ b/dtmgrpc/type.go @@ -9,10 +9,10 @@ package dtmgrpc import ( context "context" - "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" "github.com/dtm-labs/dtm/dtmgrpc/dtmgimp" "github.com/dtm-labs/dtmdriver" + grpc "google.golang.org/grpc" emptypb "google.golang.org/protobuf/types/known/emptypb" ) @@ -24,16 +24,11 @@ func MustGenGid(grpcServer string) string { return r.Gid } -// SetCurrentDBType set the current db type -func SetCurrentDBType(dbType string) { - dtmcli.SetCurrentDBType(dbType) -} - -// GetCurrentDBType set the current db type -func GetCurrentDBType() string { - return dtmcli.GetCurrentDBType() -} - +// UseDriver use the specified driver to handle grpc urls func UseDriver(driverName string) error { return dtmdriver.Use(driverName) } + +func AddUnaryInterceptor(interceptor grpc.UnaryClientInterceptor) { + dtmgimp.ClientInterceptors = append(dtmgimp.ClientInterceptors, interceptor) +} diff --git a/dtmgrpc/type_test.go b/dtmgrpc/type_test.go index 7c44e4a..c54583e 100644 --- a/dtmgrpc/type_test.go +++ b/dtmgrpc/type_test.go @@ -10,7 +10,6 @@ import ( "context" "testing" - "github.com/dtm-labs/dtm/dtmcli" "github.com/stretchr/testify/assert" ) @@ -21,10 +20,6 @@ func TestType(t *testing.T) { _, err = TccFromGrpc(context.Background()) assert.Error(t, err) - old := GetCurrentDBType() - SetCurrentDBType(dtmcli.DBTypeMysql) - SetCurrentDBType(old) - err = UseDriver("default") assert.Nil(t, err) } diff --git a/dtmgrpc/xa.go b/dtmgrpc/xa.go index 95a97a1..3cfd8bf 100644 --- a/dtmgrpc/xa.go +++ b/dtmgrpc/xa.go @@ -92,7 +92,13 @@ func (xc *XaGrpcClient) XaLocalTransaction(ctx context.Context, msg proto.Messag // XaGlobalTransaction start a xa global transaction func (xc *XaGrpcClient) XaGlobalTransaction(gid string, xaFunc XaGrpcGlobalFunc) error { - xa := XaGrpc{TransBase: *dtmimp.NewTransBase(gid, "xa", xc.Server, "")} + return xc.XaGlobalTransaction2(gid, func(xg *XaGrpc) {}, xaFunc) +} + +// XaGlobalTransaction2 new version of XaGlobalTransaction. support custom +func (xc *XaGrpcClient) XaGlobalTransaction2(gid string, custom func(*XaGrpc), xaFunc XaGrpcGlobalFunc) error { + xa := &XaGrpc{TransBase: *dtmimp.NewTransBase(gid, "xa", xc.Server, "")} + custom(xa) dc := dtmgimp.MustGetDtmClient(xa.Dtm) req := &dtmgpb.DtmRequest{ Gid: gid, @@ -107,7 +113,7 @@ func (xc *XaGrpcClient) XaGlobalTransaction(gid string, xaFunc XaGrpcGlobalFunc) _, err := f(context.Background(), req) return err }, func() error { - return xaFunc(&xa) + return xaFunc(xa) }) } diff --git a/dtmsvr/api_grpc.go b/dtmsvr/api_grpc.go index 461b251..8cd48d3 100644 --- a/dtmsvr/api_grpc.go +++ b/dtmsvr/api_grpc.go @@ -25,17 +25,17 @@ func (s *dtmServer) NewGid(ctx context.Context, in *emptypb.Empty) (*pb.DtmGidRe } func (s *dtmServer) Submit(ctx context.Context, in *pb.DtmRequest) (*emptypb.Empty, error) { - r, err := svcSubmit(TransFromDtmRequest(in)) + r, err := svcSubmit(TransFromDtmRequest(ctx, in)) return &emptypb.Empty{}, dtmgimp.Result2Error(r, err) } func (s *dtmServer) Prepare(ctx context.Context, in *pb.DtmRequest) (*emptypb.Empty, error) { - r, err := svcPrepare(TransFromDtmRequest(in)) + r, err := svcPrepare(TransFromDtmRequest(ctx, in)) return &emptypb.Empty{}, dtmgimp.Result2Error(r, err) } func (s *dtmServer) Abort(ctx context.Context, in *pb.DtmRequest) (*emptypb.Empty, error) { - r, err := svcAbort(TransFromDtmRequest(in)) + r, err := svcAbort(TransFromDtmRequest(ctx, in)) return &emptypb.Empty{}, dtmgimp.Result2Error(r, err) } diff --git a/dtmsvr/config/config.go b/dtmsvr/config/config.go index 9acc8f5..5aad90f 100644 --- a/dtmsvr/config/config.go +++ b/dtmsvr/config/config.go @@ -24,16 +24,18 @@ type MicroService struct { } type Store struct { - Driver string `yaml:"Driver" default:"boltdb"` - Host string `yaml:"Host"` - Port int64 `yaml:"Port"` - User string `yaml:"User"` - Password string `yaml:"Password"` - MaxOpenConns int64 `yaml:"MaxOpenConns" default:"500"` - MaxIdleConns int64 `yaml:"MaxIdleConns" default:"500"` - ConnMaxLifeTime int64 `yaml:"ConnMaxLifeTime" default:"5"` - DataExpire int64 `yaml:"DataExpire" default:"604800"` // Trans data will expire in 7 days. only for redis/boltdb. - RedisPrefix string `yaml:"RedisPrefix" default:"{a}"` // Redis storage prefix. store data to only one slot in cluster + Driver string `yaml:"Driver" default:"boltdb"` + Host string `yaml:"Host"` + Port int64 `yaml:"Port"` + User string `yaml:"User"` + Password string `yaml:"Password"` + MaxOpenConns int64 `yaml:"MaxOpenConns" default:"500"` + MaxIdleConns int64 `yaml:"MaxIdleConns" default:"500"` + ConnMaxLifeTime int64 `yaml:"ConnMaxLifeTime" default:"5"` + DataExpire int64 `yaml:"DataExpire" default:"604800"` // Trans data will expire in 7 days. only for redis/boltdb. + RedisPrefix string `yaml:"RedisPrefix" default:"{a}"` // Redis storage prefix. store data to only one slot in cluster + TransGlobalTable string `yaml:"TransGlobalTable" default:"dtm.trans_global"` + TransBranchOpTable string `yaml:"BranchTransOpTable" default:"dtm.trans_branch_op"` } func (s *Store) IsDB() bool { @@ -77,7 +79,7 @@ func MustLoadConfig(confFile string) { scont, err := json.MarshalIndent(&Config, "", " ") logger.FatalIfError(err) logger.Infof("config file: %s loaded config is: \n%s", confFile, scont) - err = checkConfig() + err = checkConfig(&Config) logger.FatalfIf(err != nil, `config error: '%v'. please visit http://d.dtm.pub to see the config document.`, err) } diff --git a/dtmsvr/config/config_test.go b/dtmsvr/config/config_test.go index 8088bef..f7ac1e8 100644 --- a/dtmsvr/config/config_test.go +++ b/dtmsvr/config/config_test.go @@ -17,38 +17,47 @@ func TestLoadFromEnv(t *testing.T) { assert.Equal(t, "d1", ms.Driver) } -func TestCheckConfig(t *testing.T) { +func TestLoadConfig(t *testing.T) { MustLoadConfig("../../conf.sample.yml") - config := &Config - config.RetryInterval = 1 - retryIntervalErr := checkConfig() +} +func TestCheckConfig(t *testing.T) { + conf := Config + conf.RetryInterval = 1 + retryIntervalErr := checkConfig(&conf) retryIntervalExpect := errors.New("RetryInterval should not be less than 10") assert.Equal(t, retryIntervalErr, retryIntervalExpect) - config.RetryInterval = 10 - config.TimeoutToFail = 5 - timeoutToFailErr := checkConfig() + conf.RetryInterval = 10 + conf.TimeoutToFail = 5 + timeoutToFailErr := checkConfig(&conf) timeoutToFailExpect := errors.New("TimeoutToFail should not be less than RetryInterval") assert.Equal(t, timeoutToFailErr, timeoutToFailExpect) - config.TimeoutToFail = 20 - driverErr := checkConfig() + conf.TimeoutToFail = 20 + driverErr := checkConfig(&conf) assert.Equal(t, driverErr, nil) - config.Store = Store{Driver: Mysql} - hostErr := checkConfig() + conf.Store = Store{Driver: Mysql} + hostErr := checkConfig(&conf) hostExpect := errors.New("Db host not valid ") assert.Equal(t, hostErr, hostExpect) - config.Store = Store{Driver: Mysql, Host: "127.0.0.1"} - portErr := checkConfig() + conf.Store = Store{Driver: Mysql, Host: "127.0.0.1"} + portErr := checkConfig(&conf) portExpect := errors.New("Db port not valid ") assert.Equal(t, portErr, portExpect) - config.Store = Store{Driver: Mysql, Host: "127.0.0.1", Port: 8686} - userErr := checkConfig() + conf.Store = Store{Driver: Mysql, Host: "127.0.0.1", Port: 8686} + userErr := checkConfig(&conf) userExpect := errors.New("Db user not valid ") assert.Equal(t, userErr, userExpect) + + conf.Store = Store{Driver: Redis, Host: "", Port: 8686} + assert.Equal(t, errors.New("Redis host not valid"), checkConfig(&conf)) + + conf.Store = Store{Driver: Redis, Host: "127.0.0.1", Port: 0} + assert.Equal(t, errors.New("Redis port not valid"), checkConfig(&conf)) + } func TestConfig(t *testing.T) { @@ -61,7 +70,7 @@ func TestConfig(t *testing.T) { func testConfigStringField(fd *string, val string, t *testing.T) { old := *fd *fd = val - str := checkConfig() + str := checkConfig(&Config) assert.NotEqual(t, "", str) *fd = old } @@ -69,7 +78,7 @@ func testConfigStringField(fd *string, val string, t *testing.T) { func testConfigIntField(fd *int64, val int64, t *testing.T) { old := *fd *fd = val - str := checkConfig() + str := checkConfig(&Config) assert.NotEqual(t, "", str) *fd = old } diff --git a/dtmsvr/config/config_utils.go b/dtmsvr/config/config_utils.go index 1dc991f..e5b1785 100644 --- a/dtmsvr/config/config_utils.go +++ b/dtmsvr/config/config_utils.go @@ -55,32 +55,32 @@ func toUnderscoreUpper(key string) string { return strings.ToUpper(s2) } -func checkConfig() error { - if Config.RetryInterval < 10 { +func checkConfig(conf *configType) error { + if conf.RetryInterval < 10 { return errors.New("RetryInterval should not be less than 10") } - if Config.TimeoutToFail < Config.RetryInterval { + if conf.TimeoutToFail < conf.RetryInterval { return errors.New("TimeoutToFail should not be less than RetryInterval") } - switch Config.Store.Driver { + switch conf.Store.Driver { case BoltDb: return nil case Mysql: - if Config.Store.Host == "" { + if conf.Store.Host == "" { return errors.New("Db host not valid ") } - if Config.Store.Port == 0 { + if conf.Store.Port == 0 { return errors.New("Db port not valid ") } - if Config.Store.User == "" { + if conf.Store.User == "" { return errors.New("Db user not valid ") } case Redis: - if Config.Store.Host == "" { - return errors.New("Redis host not valid ") + if conf.Store.Host == "" { + return errors.New("Redis host not valid") } - if Config.Store.Port == 0 { - return errors.New("Redis port not valid ") + if conf.Store.Port == 0 { + return errors.New("Redis port not valid") } } return nil diff --git a/dtmsvr/storage/trans.go b/dtmsvr/storage/trans.go index e1f3fa3..80663c9 100644 --- a/dtmsvr/storage/trans.go +++ b/dtmsvr/storage/trans.go @@ -5,9 +5,14 @@ import ( "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" + "github.com/dtm-labs/dtm/dtmsvr/config" "github.com/dtm-labs/dtm/dtmutil" ) +type TransGlobalExt struct { + Headers map[string]string `json:"headers,omitempty" gorm:"-"` +} + type TransGlobalStore struct { dtmutil.ModelBase Gid string `json:"gid,omitempty"` @@ -18,7 +23,6 @@ type TransGlobalStore struct { Status string `json:"status,omitempty"` QueryPrepared string `json:"query_prepared,omitempty"` Protocol string `json:"protocol,omitempty"` - CommitTime *time.Time `json:"commit_time,omitempty"` FinishTime *time.Time `json:"finish_time,omitempty"` RollbackTime *time.Time `json:"rollback_time,omitempty"` Options string `json:"options,omitempty"` @@ -26,12 +30,14 @@ type TransGlobalStore struct { NextCronInterval int64 `json:"next_cron_interval,omitempty"` NextCronTime *time.Time `json:"next_cron_time,omitempty"` Owner string `json:"owner,omitempty"` + Ext TransGlobalExt `json:"-" gorm:"-"` + ExtData string `json:"ext_data,omitempty"` // storage of ext. a db field to store many values. like Options dtmcli.TransOptions } // TableName TableName func (g *TransGlobalStore) TableName() string { - return "dtm.trans_global" + return config.Config.Store.TransGlobalTable } func (g *TransGlobalStore) String() string { @@ -53,7 +59,7 @@ type TransBranchStore struct { // TableName TableName func (b *TransBranchStore) TableName() string { - return "dtm.trans_branch_op" + return config.Config.Store.TransBranchOpTable } func (b *TransBranchStore) String() string { diff --git a/dtmsvr/trans_class.go b/dtmsvr/trans_class.go index 977f44b..50f9b01 100644 --- a/dtmsvr/trans_class.go +++ b/dtmsvr/trans_class.go @@ -7,11 +7,13 @@ package dtmsvr import ( + "context" "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/dtmgrpc/dtmgimp" "github.com/dtm-labs/dtm/dtmgrpc/dtmgpb" "github.com/dtm-labs/dtm/dtmsvr/storage" "github.com/gin-gonic/gin" @@ -69,11 +71,21 @@ func TransFromContext(c *gin.Context) *TransGlobal { } } m.Protocol = "http" + + m.Ext.Headers = map[string]string{} + if len(m.PassthroughHeaders) > 0 { + for _, h := range m.PassthroughHeaders { + v := c.GetHeader(h) + if v != "" { + m.Ext.Headers[h] = v + } + } + } return &m } // TransFromDtmRequest TransFromContext -func TransFromDtmRequest(c *dtmgpb.DtmRequest) *TransGlobal { +func TransFromDtmRequest(ctx context.Context, c *dtmgpb.DtmRequest) *TransGlobal { o := &dtmgpb.DtmTransOptions{} if c.TransOptions != nil { o = c.TransOptions @@ -85,13 +97,24 @@ func TransFromDtmRequest(c *dtmgpb.DtmRequest) *TransGlobal { Protocol: "grpc", BinPayloads: c.BinPayloads, TransOptions: dtmcli.TransOptions{ - WaitResult: o.WaitResult, - TimeoutToFail: o.TimeoutToFail, - RetryInterval: o.RetryInterval, + WaitResult: o.WaitResult, + TimeoutToFail: o.TimeoutToFail, + RetryInterval: o.RetryInterval, + PassthroughHeaders: o.PassthroughHeaders, + BranchHeaders: o.BranchHeaders, }, }} if c.Steps != "" { dtmimp.MustUnmarshalString(c.Steps, &r.Steps) } + if len(o.PassthroughHeaders) > 0 { + r.Ext.Headers = map[string]string{} + for _, h := range o.PassthroughHeaders { + v := dtmgimp.GetMetaFromContext(ctx, h) + if v != "" { + r.Ext.Headers[h] = v + } + } + } return &r } diff --git a/dtmsvr/trans_process.go b/dtmsvr/trans_process.go index cac4c96..db6243c 100644 --- a/dtmsvr/trans_process.go +++ b/dtmsvr/trans_process.go @@ -26,6 +26,9 @@ func (t *TransGlobal) process(branches []TransBranch) map[string]interface{} { if t.Options != "" { dtmimp.MustUnmarshalString(t.Options, &t.TransOptions) } + if t.ExtData != "" { + dtmimp.MustUnmarshalString(t.ExtData, &t.Ext) + } if !t.WaitResult { go t.processInner(branches) @@ -63,6 +66,10 @@ func (t *TransGlobal) processInner(branches []TransBranch) (rerr error) { func (t *TransGlobal) saveNew() ([]TransBranch, error) { t.NextCronInterval = t.getNextCronInterval(cronReset) t.NextCronTime = dtmutil.GetNextTime(t.NextCronInterval) + t.ExtData = dtmimp.MustMarshalString(t.Ext) + if t.ExtData == "{}" { + t.ExtData = "" + } t.Options = dtmimp.MustMarshalString(t.TransOptions) if t.Options == "{}" { t.Options = "" diff --git a/dtmsvr/trans_status.go b/dtmsvr/trans_status.go index 6f1dea0..c04110a 100644 --- a/dtmsvr/trans_status.go +++ b/dtmsvr/trans_status.go @@ -17,6 +17,7 @@ import ( "github.com/dtm-labs/dtm/dtmgrpc/dtmgimp" "github.com/dtm-labs/dtmdriver" "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" ) @@ -83,6 +84,9 @@ func (t *TransGlobal) getURLResult(url string, branchID, op string, branchPayloa } conn := dtmgimp.MustGetGrpcConn(server, true) ctx := dtmgimp.TransInfo2Ctx(t.Gid, t.TransType, branchID, op, "") + kvs := dtmgimp.Map2Kvs(t.Ext.Headers) + kvs = append(kvs, dtmgimp.Map2Kvs(t.BranchHeaders)...) + ctx = metadata.AppendToOutgoingContext(ctx, kvs...) err = conn.Invoke(ctx, method, branchPayload, &[]byte{}) if err == nil { return dtmcli.ResultSuccess, nil @@ -106,6 +110,8 @@ func (t *TransGlobal) getURLResult(url string, branchID, op string, branchPayloa "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), url) if err != nil { return "", err diff --git a/go.mod b/go.mod index 0d19a2f..306fad3 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,6 @@ require ( github.com/dtm-labs/dtmdriver-polaris v0.0.2 github.com/dtm-labs/dtmdriver-protocol1 v0.0.1 github.com/gin-gonic/gin v1.6.3 - github.com/go-redis/redis/v8 v8.11.4 github.com/go-resty/resty/v2 v2.7.0 github.com/go-sql-driver/mysql v1.6.0 diff --git a/go.sum b/go.sum index 09eb829..d37ef25 100644 --- a/go.sum +++ b/go.sum @@ -509,6 +509,12 @@ github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/X github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= +github.com/ychensha/dtmdriver-polaris v0.0.1/go.mod h1:0BdQvxXlGOlF6YVlsDoVvu8jyxdTlJZ9Kyh5t9lRA94= +github.com/yedf/dtm v1.7.2 h1:qGjio5O+Zm5CmMfga9Eb0rsUu9nkNHxGuJwc7PEkMfc= +github.com/yedf/dtm v1.7.2/go.mod h1:R1Q55spqLh7yHMVJhGI8RpS1iG7OvRX99pWZRlsAtME= +github.com/yedf/dtmdriver v0.0.0-20211203060147-29426c663b6e/go.mod h1:aeo6ZWiVI0x8P8O18r6uB1cG2uw9BCQyYZaH15MlRDI= +github.com/yedf/dtmdriver-gozero v0.0.0-20211204083751-a14485949435/go.mod h1:RYtA6oZny6LzlIRb1tPGt5bHfgqws/JaU6ogFly8ByQ= +github.com/yedf/dtmdriver-protocol1 v0.0.0-20211205112411-d7a7052dc90e/go.mod h1:kB3NPnDKSGioVjgdfj6qgbqYJinOml45GnlHqR46Ycc= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= diff --git a/helper/sync-dtmcli.sh b/helper/sync-dtmcli.sh index 3ac42b0..dd70a5a 100755 --- a/helper/sync-dtmcli.sh +++ b/helper/sync-dtmcli.sh @@ -30,8 +30,6 @@ go build || exit 1 git add . git commit -m"update from dtm to version $ver" git push -git tag $ver -git push --tags cd ../dtmgrpc diff --git a/sqls/dtmsvr.storage.mysql.sql b/sqls/dtmsvr.storage.mysql.sql index 59d61dd..09c82f5 100644 --- a/sqls/dtmsvr.storage.mysql.sql +++ b/sqls/dtmsvr.storage.mysql.sql @@ -12,14 +12,14 @@ CREATE TABLE if not EXISTS dtm.trans_global ( `protocol` varchar(45) not null comment '通信协议 http | grpc', `create_time` datetime DEFAULT NULL, `update_time` datetime DEFAULT NULL, - `commit_time` datetime DEFAULT NULL, `finish_time` datetime DEFAULT NULL, `rollback_time` datetime DEFAULT NULL, - `options` varchar(256) DEFAULT '', + `options` varchar(1024) DEFAULT '', `custom_data` varchar(256) DEFAULT '', `next_cron_interval` int(11) default null comment '下次定时处理的间隔', `next_cron_time` datetime default null comment '下次定时处理的时间', `owner` varchar(128) not null default '' comment '正在处理全局事务的锁定者', + `ext_data` TEXT comment 'global扩展字段的数据', 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 bccb8be..f19d25e 100644 --- a/sqls/dtmsvr.storage.postgres.sql +++ b/sqls/dtmsvr.storage.postgres.sql @@ -13,14 +13,14 @@ CREATE TABLE if not EXISTS dtm.trans_global ( protocol varchar(45) not null, create_time timestamp(0) with time zone DEFAULT NULL, update_time timestamp(0) with time zone DEFAULT NULL, - commit_time timestamp(0) with time zone DEFAULT NULL, finish_time timestamp(0) with time zone DEFAULT NULL, rollback_time timestamp(0) with time zone DEFAULT NULL, - options varchar(256) DEFAULT '', + options varchar(1024) DEFAULT '', custom_data varchar(256) DEFAULT '', next_cron_interval int default null, next_cron_time timestamp(0) with time zone default null, owner varchar(128) not null default '', + ext_data text, PRIMARY KEY (id), CONSTRAINT gid UNIQUE (gid) ); diff --git a/test/busi/base_grpc.go b/test/busi/base_grpc.go index dcfca4e..6fd3790 100644 --- a/test/busi/base_grpc.go +++ b/test/busi/base_grpc.go @@ -9,6 +9,7 @@ package busi import ( "context" "database/sql" + "errors" "fmt" "net" @@ -123,3 +124,19 @@ func (s *busiServer) TransInTccNested(ctx context.Context, in *BusiReq) (*emptyp func (s *busiServer) XaNotify(ctx context.Context, in *emptypb.Empty) (*emptypb.Empty, error) { return XaGrpcClient.HandleCallback(ctx) } + +func (s *busiServer) TransOutHeaderYes(ctx context.Context, in *BusiReq) (*emptypb.Empty, error) { + meta := dtmgimp.GetMetaFromContext(ctx, "test_header") + if meta == "" { + return &emptypb.Empty{}, errors.New("no header found in HeaderYes") + } + return &emptypb.Empty{}, handleGrpcBusiness(in, MainSwitch.TransOutResult.Fetch(), in.TransOutResult, dtmimp.GetFuncName()) +} + +func (s *busiServer) TransOutHeaderNo(ctx context.Context, in *BusiReq) (*emptypb.Empty, error) { + meta := dtmgimp.GetMetaFromContext(ctx, "test_header") + if meta != "" { + return &emptypb.Empty{}, errors.New("header found in HeaderNo") + } + return &emptypb.Empty{}, nil +} diff --git a/test/busi/base_http.go b/test/busi/base_http.go index 4518d0e..fe47dd7 100644 --- a/test/busi/base_http.go +++ b/test/busi/base_http.go @@ -154,4 +154,18 @@ func BaseAddRoute(app *gin.Engine) { app.POST(BusiAPI+"/TccBSleepCancel", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { return sleepCancelHandler(c) })) + app.POST(BusiAPI+"/TransOutHeaderYes", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { + h := c.GetHeader("test_header") + if h == "" { + return nil, errors.New("no test_header found in TransOutHeaderYes") + } + return handleGeneralBusiness(c, MainSwitch.TransOutResult.Fetch(), reqFrom(c).TransOutResult, "TransOut") + })) + app.POST(BusiAPI+"/TransOutHeaderNo", dtmutil.WrapHandler(func(c *gin.Context) (interface{}, error) { + h := c.GetHeader("test_header") + if h != "" { + return nil, errors.New("test_header found in TransOutHeaderNo") + } + return dtmcli.MapSuccess, nil + })) } diff --git a/test/busi/busi.pb.go b/test/busi/busi.pb.go index fa73c00..cfa8766 100644 --- a/test/busi/busi.pb.go +++ b/test/busi/busi.pb.go @@ -148,7 +148,7 @@ var file_test_busi_busi_proto_rawDesc = []byte{ 0x6e, 0x73, 0x49, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x25, 0x0a, 0x09, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x32, 0xd3, 0x07, 0x0a, 0x04, 0x42, 0x75, 0x73, 0x69, 0x12, 0x2d, 0x0a, 0x09, 0x43, 0x61, + 0x65, 0x32, 0xce, 0x08, 0x0a, 0x04, 0x42, 0x75, 0x73, 0x69, 0x12, 0x2d, 0x0a, 0x09, 0x43, 0x61, 0x6e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x12, 0x0d, 0x2e, 0x62, 0x75, 0x73, 0x69, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x62, 0x75, 0x73, 0x69, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x32, 0x0a, 0x07, 0x54, 0x72, 0x61, @@ -209,8 +209,16 @@ var file_test_busi_busi_proto_rawDesc = []byte{ 0x4f, 0x75, 0x74, 0x52, 0x65, 0x76, 0x65, 0x72, 0x74, 0x42, 0x53, 0x61, 0x67, 0x61, 0x12, 0x0d, 0x2e, 0x62, 0x75, 0x73, 0x69, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x62, 0x75, 0x73, - 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x11, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x4f, 0x75, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x59, 0x65, 0x73, 0x12, 0x0d, 0x2e, 0x62, + 0x75, 0x73, 0x69, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x3b, 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x75, + 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4e, 0x6f, 0x12, 0x0d, 0x2e, 0x62, 0x75, 0x73, 0x69, + 0x2e, 0x42, 0x75, 0x73, 0x69, 0x52, 0x65, 0x71, 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, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x62, 0x75, 0x73, 0x69, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -249,25 +257,29 @@ var file_test_busi_busi_proto_depIdxs = []int32{ 0, // 14: busi.Busi.TransOutBSaga:input_type -> busi.BusiReq 0, // 15: busi.Busi.TransInRevertBSaga:input_type -> busi.BusiReq 0, // 16: busi.Busi.TransOutRevertBSaga:input_type -> busi.BusiReq - 1, // 17: busi.Busi.CanSubmit:output_type -> busi.BusiReply - 2, // 18: busi.Busi.TransIn:output_type -> google.protobuf.Empty - 2, // 19: busi.Busi.TransOut:output_type -> google.protobuf.Empty - 2, // 20: busi.Busi.TransInRevert:output_type -> google.protobuf.Empty - 2, // 21: busi.Busi.TransOutRevert:output_type -> google.protobuf.Empty - 2, // 22: busi.Busi.TransInConfirm:output_type -> google.protobuf.Empty - 2, // 23: busi.Busi.TransOutConfirm:output_type -> google.protobuf.Empty - 2, // 24: busi.Busi.XaNotify:output_type -> google.protobuf.Empty - 2, // 25: busi.Busi.TransInXa:output_type -> google.protobuf.Empty - 2, // 26: busi.Busi.TransOutXa:output_type -> google.protobuf.Empty - 2, // 27: busi.Busi.TransInTcc:output_type -> google.protobuf.Empty - 2, // 28: busi.Busi.TransOutTcc:output_type -> google.protobuf.Empty - 2, // 29: busi.Busi.TransInTccNested:output_type -> google.protobuf.Empty - 2, // 30: busi.Busi.TransInBSaga:output_type -> google.protobuf.Empty - 2, // 31: busi.Busi.TransOutBSaga:output_type -> google.protobuf.Empty - 2, // 32: busi.Busi.TransInRevertBSaga:output_type -> google.protobuf.Empty - 2, // 33: busi.Busi.TransOutRevertBSaga:output_type -> google.protobuf.Empty - 17, // [17:34] is the sub-list for method output_type - 0, // [0:17] is the sub-list for method input_type + 0, // 17: busi.Busi.TransOutHeaderYes:input_type -> busi.BusiReq + 0, // 18: busi.Busi.TransOutHeaderNo:input_type -> busi.BusiReq + 1, // 19: busi.Busi.CanSubmit:output_type -> busi.BusiReply + 2, // 20: busi.Busi.TransIn:output_type -> google.protobuf.Empty + 2, // 21: busi.Busi.TransOut:output_type -> google.protobuf.Empty + 2, // 22: busi.Busi.TransInRevert:output_type -> google.protobuf.Empty + 2, // 23: busi.Busi.TransOutRevert:output_type -> google.protobuf.Empty + 2, // 24: busi.Busi.TransInConfirm:output_type -> google.protobuf.Empty + 2, // 25: busi.Busi.TransOutConfirm:output_type -> google.protobuf.Empty + 2, // 26: busi.Busi.XaNotify:output_type -> google.protobuf.Empty + 2, // 27: busi.Busi.TransInXa:output_type -> google.protobuf.Empty + 2, // 28: busi.Busi.TransOutXa:output_type -> google.protobuf.Empty + 2, // 29: busi.Busi.TransInTcc:output_type -> google.protobuf.Empty + 2, // 30: busi.Busi.TransOutTcc:output_type -> google.protobuf.Empty + 2, // 31: busi.Busi.TransInTccNested:output_type -> google.protobuf.Empty + 2, // 32: busi.Busi.TransInBSaga:output_type -> google.protobuf.Empty + 2, // 33: busi.Busi.TransOutBSaga:output_type -> google.protobuf.Empty + 2, // 34: busi.Busi.TransInRevertBSaga:output_type -> google.protobuf.Empty + 2, // 35: busi.Busi.TransOutRevertBSaga:output_type -> google.protobuf.Empty + 2, // 36: busi.Busi.TransOutHeaderYes:output_type -> google.protobuf.Empty + 2, // 37: busi.Busi.TransOutHeaderNo:output_type -> google.protobuf.Empty + 19, // [19:38] is the sub-list for method output_type + 0, // [0:19] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name diff --git a/test/busi/busi.proto b/test/busi/busi.proto index 0e421b0..9d43abd 100644 --- a/test/busi/busi.proto +++ b/test/busi/busi.proto @@ -36,5 +36,7 @@ service Busi { rpc TransOutBSaga(BusiReq) returns (google.protobuf.Empty) {} rpc TransInRevertBSaga(BusiReq) returns (google.protobuf.Empty) {} rpc TransOutRevertBSaga(BusiReq) returns (google.protobuf.Empty) {} + rpc TransOutHeaderYes(BusiReq) returns (google.protobuf.Empty) {} + rpc TransOutHeaderNo(BusiReq) returns (google.protobuf.Empty) {} } diff --git a/test/busi/busi_grpc.pb.go b/test/busi/busi_grpc.pb.go index bc612b1..095b295 100644 --- a/test/busi/busi_grpc.pb.go +++ b/test/busi/busi_grpc.pb.go @@ -36,6 +36,8 @@ type BusiClient interface { TransOutBSaga(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) TransInRevertBSaga(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) TransOutRevertBSaga(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) + TransOutHeaderYes(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) + TransOutHeaderNo(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) } type busiClient struct { @@ -199,6 +201,24 @@ func (c *busiClient) TransOutRevertBSaga(ctx context.Context, in *BusiReq, opts return out, nil } +func (c *busiClient) TransOutHeaderYes(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/busi.Busi/TransOutHeaderYes", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *busiClient) TransOutHeaderNo(ctx context.Context, in *BusiReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/busi.Busi/TransOutHeaderNo", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // BusiServer is the server API for Busi service. // All implementations must embed UnimplementedBusiServer // for forward compatibility @@ -220,6 +240,8 @@ type BusiServer interface { TransOutBSaga(context.Context, *BusiReq) (*emptypb.Empty, error) TransInRevertBSaga(context.Context, *BusiReq) (*emptypb.Empty, error) TransOutRevertBSaga(context.Context, *BusiReq) (*emptypb.Empty, error) + TransOutHeaderYes(context.Context, *BusiReq) (*emptypb.Empty, error) + TransOutHeaderNo(context.Context, *BusiReq) (*emptypb.Empty, error) mustEmbedUnimplementedBusiServer() } @@ -278,6 +300,12 @@ func (UnimplementedBusiServer) TransInRevertBSaga(context.Context, *BusiReq) (*e func (UnimplementedBusiServer) TransOutRevertBSaga(context.Context, *BusiReq) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method TransOutRevertBSaga not implemented") } +func (UnimplementedBusiServer) TransOutHeaderYes(context.Context, *BusiReq) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method TransOutHeaderYes not implemented") +} +func (UnimplementedBusiServer) TransOutHeaderNo(context.Context, *BusiReq) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method TransOutHeaderNo not implemented") +} func (UnimplementedBusiServer) mustEmbedUnimplementedBusiServer() {} // UnsafeBusiServer may be embedded to opt out of forward compatibility for this service. @@ -597,6 +625,42 @@ func _Busi_TransOutRevertBSaga_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _Busi_TransOutHeaderYes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BusiReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BusiServer).TransOutHeaderYes(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/busi.Busi/TransOutHeaderYes", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BusiServer).TransOutHeaderYes(ctx, req.(*BusiReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Busi_TransOutHeaderNo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BusiReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BusiServer).TransOutHeaderNo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/busi.Busi/TransOutHeaderNo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BusiServer).TransOutHeaderNo(ctx, req.(*BusiReq)) + } + return interceptor(ctx, in, info, handler) +} + // Busi_ServiceDesc is the grpc.ServiceDesc for Busi service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -672,6 +736,14 @@ var Busi_ServiceDesc = grpc.ServiceDesc{ MethodName: "TransOutRevertBSaga", Handler: _Busi_TransOutRevertBSaga_Handler, }, + { + MethodName: "TransOutHeaderYes", + Handler: _Busi_TransOutHeaderYes_Handler, + }, + { + MethodName: "TransOutHeaderNo", + Handler: _Busi_TransOutHeaderNo_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "test/busi/busi.proto", diff --git a/test/busi/utils.go b/test/busi/utils.go index 2b13712..5df72d1 100644 --- a/test/busi/utils.go +++ b/test/busi/utils.go @@ -4,27 +4,32 @@ import ( "context" "database/sql" "fmt" + "strings" "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/dtmgrpc" + "github.com/dtm-labs/dtm/dtmgrpc/dtmgpb" "github.com/dtm-labs/dtm/dtmutil" "github.com/gin-gonic/gin" + "github.com/go-resty/resty/v2" + grpc "google.golang.org/grpc" + "google.golang.org/grpc/metadata" ) func dbGet() *dtmutil.DB { return dtmutil.DbGet(BusiConf) } -func sdbGet() *sql.DB { +func pdbGet() *sql.DB { db, err := dtmimp.PooledDB(BusiConf) logger.FatalIfError(err) return db } func txGet() *sql.Tx { - db := sdbGet() + db := pdbGet() tx, err := db.Begin() logger.FatalIfError(err) return tx @@ -59,3 +64,22 @@ func MustBarrierFromGrpc(ctx context.Context) *dtmcli.BranchBarrier { logger.FatalIfError(err) return ti } + +// SetGrpcHeaderForHeadersYes interceptor to set head for HeadersYes +func SetGrpcHeaderForHeadersYes(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { + if r, ok := req.(*dtmgpb.DtmRequest); ok && strings.HasSuffix(r.Gid, "HeadersYes") { + logger.Debugf("writing test_header:test to ctx") + md := metadata.New(map[string]string{"test_header": "test"}) + ctx = metadata.NewOutgoingContext(ctx, md) + } + return invoker(ctx, method, req, reply, cc, opts...) +} + +// SetHttpHeaderForHeadersYes interceptor to set head for HeadersYes +func SetHttpHeaderForHeadersYes(c *resty.Client, r *resty.Request) error { + if b, ok := r.Body.(*dtmcli.Saga); ok && strings.HasSuffix(b.Gid, "HeadersYes") { + logger.Debugf("set test_header for url: %s", r.URL) + r.SetHeader("test_header", "yes") + } + return nil +} diff --git a/test/dtmsvr_test.go b/test/dtmsvr_test.go index 7af9144..28da6e2 100644 --- a/test/dtmsvr_test.go +++ b/test/dtmsvr_test.go @@ -10,7 +10,6 @@ import ( "testing" "time" - "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" "github.com/dtm-labs/dtm/dtmsvr" "github.com/dtm-labs/dtm/dtmutil" @@ -45,7 +44,7 @@ func TestUpdateBranchAsync(t *testing.T) { } conf.UpdateBranchSync = 0 saga := genSaga1(dtmimp.GetFuncName(), false, false) - saga.SetOptions(&dtmcli.TransOptions{WaitResult: true}) + saga.WaitResult = true err := saga.Submit() assert.Nil(t, err) waitTransProcessed(saga.Gid) diff --git a/test/main_test.go b/test/main_test.go index e7d7ca9..31bf4be 100644 --- a/test/main_test.go +++ b/test/main_test.go @@ -13,6 +13,7 @@ import ( "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/logger" + "github.com/dtm-labs/dtm/dtmgrpc" "github.com/dtm-labs/dtm/dtmsvr" "github.com/dtm-labs/dtm/dtmsvr/config" "github.com/dtm-labs/dtm/test/busi" @@ -33,6 +34,9 @@ func TestMain(m *testing.M) { dtmsvr.CronForwardDuration = 180 * time.Second conf.UpdateBranchSync = 1 + dtmgrpc.AddUnaryInterceptor(busi.SetGrpcHeaderForHeadersYes) + dtmcli.OnBeforeRequest(busi.SetHttpHeaderForHeadersYes) + tenv := os.Getenv("TEST_STORE") if tenv == "boltdb" { conf.Store.Driver = "boltdb" diff --git a/test/msg_grpc_test.go b/test/msg_grpc_test.go index 44af2ab..e228fbb 100644 --- a/test/msg_grpc_test.go +++ b/test/msg_grpc_test.go @@ -38,7 +38,8 @@ func TestMsgGrpcTimeoutSuccess(t *testing.T) { cronTransOnceForwardNow(180) assert.Equal(t, StatusSubmitted, getTransStatus(msg.Gid)) assert.Equal(t, []string{StatusPrepared, StatusPrepared}, getBranchesStatus(msg.Gid)) - cronTransOnce() + g := cronTransOnce() + assert.Equal(t, msg.Gid, g) assert.Equal(t, StatusSucceed, getTransStatus(msg.Gid)) assert.Equal(t, []string{StatusSucceed, StatusSucceed}, getBranchesStatus(msg.Gid)) } diff --git a/test/msg_options_test.go b/test/msg_options_test.go index f69b8c9..97cfbe3 100644 --- a/test/msg_options_test.go +++ b/test/msg_options_test.go @@ -18,7 +18,8 @@ import ( func TestMsgOptionsTimeout(t *testing.T) { msg := genMsg(dtmimp.GetFuncName()) msg.Prepare("") - cronTransOnce() + g := cronTransOnce() + assert.Equal(t, msg.Gid, g) assert.Equal(t, StatusPrepared, getTransStatus(msg.Gid)) cronTransOnceForwardNow(60) assert.Equal(t, StatusSucceed, getTransStatus(msg.Gid)) @@ -28,7 +29,8 @@ func TestMsgOptionsTimeoutCustom(t *testing.T) { msg := genMsg(dtmimp.GetFuncName()) msg.TimeoutToFail = 120 msg.Prepare("") - cronTransOnce() + g := cronTransOnce() + assert.Equal(t, msg.Gid, g) assert.Equal(t, StatusPrepared, getTransStatus(msg.Gid)) cronTransOnceForwardNow(60) assert.Equal(t, StatusPrepared, getTransStatus(msg.Gid)) @@ -40,7 +42,8 @@ func TestMsgOptionsTimeoutFailed(t *testing.T) { msg := genMsg(dtmimp.GetFuncName()) msg.TimeoutToFail = 120 msg.Prepare("") - cronTransOnce() + g := cronTransOnce() + assert.Equal(t, msg.Gid, g) assert.Equal(t, StatusPrepared, getTransStatus(msg.Gid)) cronTransOnceForwardNow(60) assert.Equal(t, StatusPrepared, getTransStatus(msg.Gid)) diff --git a/test/msg_test.go b/test/msg_test.go index fa29923..e9c1475 100644 --- a/test/msg_test.go +++ b/test/msg_test.go @@ -35,7 +35,8 @@ func TestMsgTimeoutSuccess(t *testing.T) { busi.MainSwitch.TransInResult.SetOnce(dtmcli.ResultOngoing) cronTransOnceForwardNow(180) assert.Equal(t, StatusSubmitted, getTransStatus(msg.Gid)) - cronTransOnce() + g := cronTransOnce() + assert.Equal(t, msg.Gid, g) assert.Equal(t, []string{StatusSucceed, StatusSucceed}, getBranchesStatus(msg.Gid)) assert.Equal(t, StatusSucceed, getTransStatus(msg.Gid)) } @@ -60,7 +61,7 @@ func TestMsgAbnormal(t *testing.T) { assert.Nil(t, err) err = msg.Submit() assert.Nil(t, err) - + waitTransProcessed(msg.Gid) err = msg.Prepare("") assert.Error(t, err) } diff --git a/test/saga_concurrent_test.go b/test/saga_concurrent_test.go index 7ae5635..e8c32c0 100644 --- a/test/saga_concurrent_test.go +++ b/test/saga_concurrent_test.go @@ -34,7 +34,8 @@ func TestSagaConRollbackNormal(t *testing.T) { assert.Nil(t, err) waitTransProcessed(sagaCon.Gid) assert.Equal(t, StatusAborting, getTransStatus(sagaCon.Gid)) - cronTransOnce() + g := cronTransOnce() + assert.Equal(t, sagaCon.Gid, g) assert.Equal(t, StatusFailed, getTransStatus(sagaCon.Gid)) // TODO should fix this // assert.Equal(t, []string{StatusSucceed, StatusFailed, StatusSucceed, StatusSucceed}, getBranchesStatus(sagaCon.Gid)) @@ -58,7 +59,8 @@ func TestSagaConCommittedOngoing(t *testing.T) { assert.Equal(t, []string{StatusPrepared, StatusPrepared, StatusPrepared, StatusSucceed}, getBranchesStatus(sagaCon.Gid)) assert.Equal(t, StatusSubmitted, getTransStatus(sagaCon.Gid)) - cronTransOnce() + g := cronTransOnce() + assert.Equal(t, sagaCon.Gid, g) assert.Equal(t, []string{StatusPrepared, StatusSucceed, StatusPrepared, StatusSucceed}, getBranchesStatus(sagaCon.Gid)) assert.Equal(t, StatusSucceed, getTransStatus(sagaCon.Gid)) } diff --git a/test/saga_cover_test.go b/test/saga_cover_test.go new file mode 100644 index 0000000..500f424 --- /dev/null +++ b/test/saga_cover_test.go @@ -0,0 +1,11 @@ +package test + +import ( + "testing" + + "github.com/dtm-labs/dtm/dtmcli" +) + +func TestSagaCover(t *testing.T) { + dtmcli.SetPassthroughHeaders([]string{}) +} diff --git a/test/saga_grpc_test.go b/test/saga_grpc_test.go index 831c649..74fd827 100644 --- a/test/saga_grpc_test.go +++ b/test/saga_grpc_test.go @@ -31,7 +31,8 @@ func TestSagaGrpcRollback(t *testing.T) { saga.Submit() waitTransProcessed(saga.Gid) assert.Equal(t, StatusAborting, getTransStatus(saga.Gid)) - cronTransOnce() + g := cronTransOnce() + assert.Equal(t, saga.Gid, g) assert.Equal(t, StatusFailed, getTransStatus(saga.Gid)) assert.Equal(t, []string{StatusSucceed, StatusSucceed, StatusSucceed, StatusFailed}, getBranchesStatus(saga.Gid)) } @@ -62,14 +63,15 @@ func TestSagaGrpcCommittedOngoing(t *testing.T) { waitTransProcessed(saga.Gid) assert.Equal(t, StatusSubmitted, getTransStatus(saga.Gid)) assert.Equal(t, []string{StatusPrepared, StatusPrepared, StatusPrepared, StatusPrepared}, getBranchesStatus(saga.Gid)) - cronTransOnce() + g := cronTransOnce() + assert.Equal(t, saga.Gid, g) assert.Equal(t, StatusSucceed, getTransStatus(saga.Gid)) assert.Equal(t, []string{StatusPrepared, StatusSucceed, StatusPrepared, StatusSucceed}, getBranchesStatus(saga.Gid)) } func TestSagaGrpcNormalWait(t *testing.T) { saga := genSagaGrpc(dtmimp.GetFuncName(), false, false) - saga.SetOptions(&dtmcli.TransOptions{WaitResult: true}) + saga.WaitResult = true saga.Submit() assert.Equal(t, []string{StatusPrepared, StatusSucceed, StatusPrepared, StatusSucceed}, getBranchesStatus(saga.Gid)) assert.Equal(t, StatusSucceed, getTransStatus(saga.Gid)) @@ -94,3 +96,69 @@ func genSagaGrpc(gid string, outFailed bool, inFailed bool) *dtmgrpc.SagaGrpc { saga.Add(busi.BusiGrpc+"/busi.Busi/TransIn", busi.BusiGrpc+"/busi.Busi/TransInRevert", req) return saga } + +func TestSagaGrpcPassthroughHeadersYes(t *testing.T) { + gidYes := dtmimp.GetFuncName() + sagaYes := dtmgrpc.NewSagaGrpc(dtmutil.DefaultGrpcServer, gidYes) + sagaYes.WaitResult = true + sagaYes.PassthroughHeaders = []string{"test_header"} + sagaYes.Add(busi.BusiGrpc+"/busi.Busi/TransOutHeaderYes", "", nil) + err := sagaYes.Submit() + assert.Nil(t, err) + waitTransProcessed(gidYes) +} + +func TestSagaGrpcCronPassthroughHeadersYes(t *testing.T) { + gidYes := dtmimp.GetFuncName() + sagaYes := dtmgrpc.NewSagaGrpc(dtmutil.DefaultGrpcServer, gidYes) + sagaYes.PassthroughHeaders = []string{"test_header"} + sagaYes.Add(busi.BusiGrpc+"/busi.Busi/TransOutHeaderYes", "", nil) + busi.MainSwitch.TransOutResult.SetOnce("ONGOING") + err := sagaYes.Submit() + assert.Nil(t, err) + waitTransProcessed(gidYes) + assert.Equal(t, StatusSubmitted, getTransStatus(gidYes)) + g := cronTransOnce() + assert.Equal(t, gidYes, g) + assert.Equal(t, StatusSucceed, getTransStatus(gidYes)) +} + +func TestSagaGrpcPassthroughHeadersNo(t *testing.T) { + gidNo := dtmimp.GetFuncName() + sagaNo := dtmgrpc.NewSagaGrpc(dtmutil.DefaultGrpcServer, gidNo) + sagaNo.WaitResult = true + sagaNo.Add(busi.BusiGrpc+"/busi.Busi/TransOutHeaderNo", "", nil) + err := sagaNo.Submit() + assert.Nil(t, err) + waitTransProcessed(gidNo) +} + +func TestSagaGrpcHeaders(t *testing.T) { + gidYes := dtmimp.GetFuncName() + sagaYes := dtmgrpc.NewSagaGrpc(dtmutil.DefaultGrpcServer, gidYes). + Add(busi.BusiGrpc+"/busi.Busi/TransOutHeaderYes", "", nil) + sagaYes.BranchHeaders = map[string]string{ + "test_header": "test", + } + sagaYes.WaitResult = true + err := sagaYes.Submit() + assert.Nil(t, err) + waitTransProcessed(gidYes) +} + +func TestSagaGrpcCronHeaders(t *testing.T) { + gidYes := dtmimp.GetFuncName() + sagaYes := dtmgrpc.NewSagaGrpc(dtmutil.DefaultGrpcServer, gidYes) + sagaYes.BranchHeaders = map[string]string{ + "test_header": "test", + } + sagaYes.Add(busi.BusiGrpc+"/busi.Busi/TransOutHeaderYes", "", nil) + busi.MainSwitch.TransOutResult.SetOnce("ONGOING") + err := sagaYes.Submit() + assert.Nil(t, err) + waitTransProcessed(gidYes) + assert.Equal(t, StatusSubmitted, getTransStatus(gidYes)) + g := cronTransOnce() + assert.Equal(t, gidYes, g) + assert.Equal(t, StatusSucceed, getTransStatus(gidYes)) +} diff --git a/test/saga_options_test.go b/test/saga_options_test.go index bbd1689..73ecc24 100644 --- a/test/saga_options_test.go +++ b/test/saga_options_test.go @@ -11,6 +11,7 @@ import ( "github.com/dtm-labs/dtm/dtmcli" "github.com/dtm-labs/dtm/dtmcli/dtmimp" + "github.com/dtm-labs/dtm/dtmutil" "github.com/dtm-labs/dtm/test/busi" "github.com/stretchr/testify/assert" ) @@ -22,7 +23,8 @@ func TestSagaOptionsRetryOngoing(t *testing.T) { err := saga.Submit() assert.Nil(t, err) waitTransProcessed(saga.Gid) - cronTransOnce() + g := cronTransOnce() + assert.Equal(t, saga.Gid, g) assert.Equal(t, StatusSucceed, getTransStatus(saga.Gid)) assert.Equal(t, []string{StatusPrepared, StatusSucceed}, getBranchesStatus(saga.Gid)) } @@ -34,10 +36,12 @@ func TestSagaOptionsRetryError(t *testing.T) { err := saga.Submit() assert.Nil(t, err) waitTransProcessed(saga.Gid) - cronTransOnce() assert.Equal(t, StatusSubmitted, getTransStatus(saga.Gid)) assert.Equal(t, []string{StatusPrepared, StatusPrepared}, getBranchesStatus(saga.Gid)) - cronTransOnceForwardCron(360) + g := cronTransOnce() + assert.Equal(t, "", g) + g = cronTransOnceForwardCron(360) + assert.Equal(t, saga.Gid, g) assert.Equal(t, StatusSucceed, getTransStatus(saga.Gid)) assert.Equal(t, []string{StatusPrepared, StatusSucceed}, getBranchesStatus(saga.Gid)) } @@ -55,7 +59,7 @@ func TestSagaOptionsTimeout(t *testing.T) { func TestSagaOptionsNormalWait(t *testing.T) { saga := genSaga(dtmimp.GetFuncName(), false, false) - saga.SetOptions(&dtmcli.TransOptions{WaitResult: true}) + saga.WaitResult = true err := saga.Submit() assert.Nil(t, err) assert.Equal(t, []string{StatusPrepared, StatusSucceed, StatusPrepared, StatusSucceed}, getBranchesStatus(saga.Gid)) @@ -66,23 +70,90 @@ func TestSagaOptionsNormalWait(t *testing.T) { func TestSagaOptionsCommittedOngoingWait(t *testing.T) { saga := genSaga(dtmimp.GetFuncName(), false, false) busi.MainSwitch.TransOutResult.SetOnce(dtmcli.ResultOngoing) - saga.SetOptions(&dtmcli.TransOptions{WaitResult: true}) + saga.WaitResult = true err := saga.Submit() assert.Error(t, err) assert.Equal(t, []string{StatusPrepared, StatusPrepared, StatusPrepared, StatusPrepared}, getBranchesStatus(saga.Gid)) assert.Equal(t, StatusSubmitted, getTransStatus(saga.Gid)) waitTransProcessed(saga.Gid) - cronTransOnce() + g := cronTransOnce() + assert.Equal(t, saga.Gid, g) assert.Equal(t, []string{StatusPrepared, StatusSucceed, StatusPrepared, StatusSucceed}, getBranchesStatus(saga.Gid)) assert.Equal(t, StatusSucceed, getTransStatus(saga.Gid)) } func TestSagaOptionsRollbackWait(t *testing.T) { saga := genSaga(dtmimp.GetFuncName(), false, true) - saga.SetOptions(&dtmcli.TransOptions{WaitResult: true}) + saga.WaitResult = true err := saga.Submit() assert.Error(t, err) waitTransProcessed(saga.Gid) assert.Equal(t, StatusFailed, getTransStatus(saga.Gid)) assert.Equal(t, []string{StatusSucceed, StatusSucceed, StatusSucceed, StatusFailed}, getBranchesStatus(saga.Gid)) } + +func TestSagaPassthroughHeadersYes(t *testing.T) { + gidYes := dtmimp.GetFuncName() + sagaYes := dtmcli.NewSaga(dtmutil.DefaultHttpServer, gidYes) + sagaYes.WaitResult = true + sagaYes.PassthroughHeaders = []string{"test_header"} + sagaYes.Add(busi.Busi+"/TransOutHeaderYes", "", nil) + err := sagaYes.Submit() + assert.Nil(t, err) + waitTransProcessed(gidYes) +} + +func TestSagaCronPassthroughHeadersYes(t *testing.T) { + gidYes := dtmimp.GetFuncName() + sagaYes := dtmcli.NewSaga(dtmutil.DefaultHttpServer, gidYes) + sagaYes.PassthroughHeaders = []string{"test_header"} + sagaYes.Add(busi.Busi+"/TransOutHeaderYes", "", nil) + busi.MainSwitch.TransOutResult.SetOnce("ONGOING") + err := sagaYes.Submit() + assert.Nil(t, err) + waitTransProcessed(gidYes) + assert.Equal(t, StatusSubmitted, getTransStatus(gidYes)) + g := cronTransOnce() + assert.Equal(t, gidYes, g) + assert.Equal(t, StatusSucceed, getTransStatus(gidYes)) +} + +func TestSagaPassthroughHeadersNo(t *testing.T) { + gidNo := dtmimp.GetFuncName() + sagaNo := dtmcli.NewSaga(dtmutil.DefaultHttpServer, gidNo) + sagaNo.WaitResult = true + sagaNo.Add(busi.Busi+"/TransOutHeaderNo", "", nil) + err := sagaNo.Submit() + assert.Nil(t, err) + waitTransProcessed(gidNo) +} + +func TestSagaHeaders(t *testing.T) { + gidYes := dtmimp.GetFuncName() + sagaYes := dtmcli.NewSaga(dtmutil.DefaultHttpServer, gidYes) + sagaYes.BranchHeaders = map[string]string{ + "test_header": "test", + } + sagaYes.WaitResult = true + sagaYes.Add(busi.Busi+"/TransOutHeaderYes", "", nil) + err := sagaYes.Submit() + assert.Nil(t, err) + waitTransProcessed(gidYes) +} + +func TestSagaHeadersYes1(t *testing.T) { + gidYes := dtmimp.GetFuncName() + sagaYes := dtmcli.NewSaga(dtmutil.DefaultHttpServer, gidYes) + sagaYes.BranchHeaders = map[string]string{ + "test_header": "test", + } + sagaYes.Add(busi.Busi+"/TransOutHeaderYes", "", nil) + busi.MainSwitch.TransOutResult.SetOnce("ONGOING") + err := sagaYes.Submit() + assert.Nil(t, err) + waitTransProcessed(gidYes) + assert.Equal(t, StatusSubmitted, getTransStatus(gidYes)) + g := cronTransOnce() + assert.Equal(t, gidYes, g) + assert.Equal(t, StatusSucceed, getTransStatus(gidYes)) +} diff --git a/test/saga_test.go b/test/saga_test.go index 57d3a85..0fa3a97 100644 --- a/test/saga_test.go +++ b/test/saga_test.go @@ -31,7 +31,8 @@ func TestSagaOngoingSucceed(t *testing.T) { waitTransProcessed(saga.Gid) assert.Equal(t, []string{StatusPrepared, StatusPrepared, StatusPrepared, StatusPrepared}, getBranchesStatus(saga.Gid)) assert.Equal(t, StatusSubmitted, getTransStatus(saga.Gid)) - cronTransOnce() + g := cronTransOnce() + assert.Equal(t, saga.Gid, g) assert.Equal(t, []string{StatusPrepared, StatusSucceed, StatusPrepared, StatusSucceed}, getBranchesStatus(saga.Gid)) assert.Equal(t, StatusSucceed, getTransStatus(saga.Gid)) } @@ -43,15 +44,18 @@ func TestSagaFailed(t *testing.T) { assert.Nil(t, err) waitTransProcessed(saga.Gid) assert.Equal(t, StatusAborting, getTransStatus(saga.Gid)) - cronTransOnce() + g := cronTransOnce() + assert.Equal(t, saga.Gid, g) assert.Equal(t, StatusFailed, getTransStatus(saga.Gid)) assert.Equal(t, []string{StatusSucceed, StatusSucceed, StatusSucceed, StatusFailed}, getBranchesStatus(saga.Gid)) } func TestSagaAbnormal(t *testing.T) { saga := genSaga(dtmimp.GetFuncName(), false, false) + busi.MainSwitch.TransOutResult.SetOnce("ONGOING") err := saga.Submit() assert.Nil(t, err) + waitTransProcessed(saga.Gid) err = saga.Submit() // submit twice, ignored assert.Nil(t, err) waitTransProcessed(saga.Gid) diff --git a/test/tcc_cover_test.go b/test/tcc_cover_test.go index 9ca4285..3683f23 100644 --- a/test/tcc_cover_test.go +++ b/test/tcc_cover_test.go @@ -27,4 +27,5 @@ func TestTccCoverPanic(t *testing.T) { assert.FailNow(t, "not executed") }) assert.Contains(t, err.Error(), "user panic") + waitTransProcessed(gid) } diff --git a/test/tcc_grpc_cover_test.go b/test/tcc_grpc_cover_test.go index 6056b9e..192d491 100644 --- a/test/tcc_grpc_cover_test.go +++ b/test/tcc_grpc_cover_test.go @@ -28,6 +28,7 @@ func TestTccGrpcCoverPanic(t *testing.T) { assert.FailNow(t, "not executed") }) assert.Contains(t, err.Error(), "user panic") + waitTransProcessed(gid) } func TestTccGrpcCoverCallBranch(t *testing.T) { @@ -46,4 +47,6 @@ func TestTccGrpcCoverCallBranch(t *testing.T) { return err }) assert.Error(t, err) + g := cronTransOnceForwardNow(300) + assert.Equal(t, gid, g) } diff --git a/test/tcc_grpc_test.go b/test/tcc_grpc_test.go index a9fc40b..b3a8169 100644 --- a/test/tcc_grpc_test.go +++ b/test/tcc_grpc_test.go @@ -49,7 +49,8 @@ func TestTccGrpcRollback(t *testing.T) { assert.Error(t, err) waitTransProcessed(gid) assert.Equal(t, StatusAborting, getTransStatus(gid)) - cronTransOnce() + g2 := cronTransOnce() + assert.Equal(t, gid, g2) assert.Equal(t, StatusFailed, getTransStatus(gid)) assert.Equal(t, []string{StatusSucceed, StatusPrepared, StatusSucceed, StatusPrepared}, getBranchesStatus(gid)) } @@ -76,3 +77,22 @@ func TestTccGrpcType(t *testing.T) { err = dtmgrpc.TccGlobalTransaction("-", "", func(tcc *dtmgrpc.TccGrpc) error { return nil }) assert.Error(t, err) } + +func TestTccGrpcHeaders(t *testing.T) { + gid := dtmimp.GetFuncName() + err := dtmgrpc.TccGlobalTransaction2(dtmutil.DefaultGrpcServer, gid, func(tg *dtmgrpc.TccGrpc) { + tg.BranchHeaders = map[string]string{ + "test_header": "test", + } + tg.WaitResult = true + }, func(tcc *dtmgrpc.TccGrpc) error { + data := &busi.BusiReq{Amount: 30} + r := &emptypb.Empty{} + return tcc.CallBranch(data, busi.BusiGrpc+"/busi.Busi/TransOutHeaderYes", "", "", r) + }) + assert.Nil(t, err) + waitTransProcessed(gid) + assert.Equal(t, StatusSucceed, getTransStatus(gid)) + assert.Equal(t, []string{StatusPrepared, StatusSucceed}, getBranchesStatus(gid)) + +} diff --git a/test/tcc_test.go b/test/tcc_test.go index 3766c59..4324769 100644 --- a/test/tcc_test.go +++ b/test/tcc_test.go @@ -43,7 +43,8 @@ func TestTccRollback(t *testing.T) { assert.Error(t, err) waitTransProcessed(gid) assert.Equal(t, StatusAborting, getTransStatus(gid)) - cronTransOnce() + g := cronTransOnce() + assert.Equal(t, gid, g) assert.Equal(t, StatusFailed, getTransStatus(gid)) assert.Equal(t, []string{StatusSucceed, StatusPrepared, StatusSucceed, StatusPrepared}, getBranchesStatus(gid)) } @@ -84,3 +85,19 @@ func TestTccCompatible(t *testing.T) { assert.Equal(t, []string{StatusPrepared, StatusSucceed, StatusPrepared, StatusSucceed}, getBranchesStatus(gid)) } + +func TestTccHeaders(t *testing.T) { + req := busi.GenTransReq(30, false, false) + gid := dtmimp.GetFuncName() + err := dtmcli.TccGlobalTransaction2(dtmutil.DefaultHttpServer, gid, func(t *dtmcli.Tcc) { + t.BranchHeaders = map[string]string{ + "test_header": "test", + } + }, func(tcc *dtmcli.Tcc) (*resty.Response, error) { + return tcc.CallBranch(req, Busi+"/TransOutHeaderYes", "", "") + }) + assert.Nil(t, err) + waitTransProcessed(gid) + assert.Equal(t, StatusSucceed, getTransStatus(gid)) + assert.Equal(t, []string{StatusPrepared, StatusSucceed}, getBranchesStatus(gid)) +} diff --git a/test/types.go b/test/types.go index 8ed65c8..4fcbe34 100644 --- a/test/types.go +++ b/test/types.go @@ -29,21 +29,19 @@ func waitTransProcessed(gid string) { logger.Debugf("waiting for gid %s", gid) select { case id := <-dtmsvr.TransProcessedTestChan: - for id != gid { - logger.Warnf("------- expecting: %s but %s found", gid, id) - 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 * 3)): logger.FatalfIf(true, "Wait Trans timeout") } } -func cronTransOnce() { +func cronTransOnce() string { gid := dtmsvr.CronTransOnce() if dtmsvr.TransProcessedTestChan != nil && gid != "" { waitTransProcessed(gid) } + return gid } var e2p = dtmimp.E2P @@ -54,18 +52,20 @@ type TransGlobal = dtmsvr.TransGlobal // TransBranch alias type TransBranch = dtmsvr.TransBranch -func cronTransOnceForwardNow(seconds int) { +func cronTransOnceForwardNow(seconds int) string { old := dtmsvr.NowForwardDuration dtmsvr.NowForwardDuration = time.Duration(seconds) * time.Second - cronTransOnce() + gid := cronTransOnce() dtmsvr.NowForwardDuration = old + return gid } -func cronTransOnceForwardCron(seconds int) { +func cronTransOnceForwardCron(seconds int) string { old := dtmsvr.CronForwardDuration dtmsvr.CronForwardDuration = time.Duration(seconds) * time.Second - cronTransOnce() + gid := cronTransOnce() dtmsvr.CronForwardDuration = old + return gid } const ( diff --git a/test/xa_cover_test.go b/test/xa_cover_test.go index fddada6..0103539 100644 --- a/test/xa_cover_test.go +++ b/test/xa_cover_test.go @@ -43,7 +43,7 @@ func TestXaCoverDTMError(t *testing.T) { } func TestXaCoverGidError(t *testing.T) { - gid := "errgid-' '" + gid := dtmimp.GetFuncName() + "-' '" err := getXc().XaGlobalTransaction(gid, func(xa *dtmcli.Xa) (*resty.Response, error) { req := busi.GenTransReq(30, false, false) _, err := xa.CallBranch(req, busi.Busi+"/TransOutXa") @@ -51,4 +51,5 @@ func TestXaCoverGidError(t *testing.T) { return nil, err }) assert.Error(t, err) + waitTransProcessed(gid) } diff --git a/test/xa_grpc_test.go b/test/xa_grpc_test.go index 586e3db..890d129 100644 --- a/test/xa_grpc_test.go +++ b/test/xa_grpc_test.go @@ -56,6 +56,7 @@ func TestXaGrpcRollback(t *testing.T) { } func TestXaGrpcType(t *testing.T) { + gid := dtmimp.GetFuncName() _, err := dtmgrpc.XaGrpcFromRequest(context.Background()) assert.Error(t, err) @@ -63,15 +64,18 @@ func TestXaGrpcType(t *testing.T) { assert.Error(t, err) err = dtmimp.CatchP(func() { - busi.XaGrpcClient.XaGlobalTransaction("id1", func(xa *dtmgrpc.XaGrpc) error { panic(fmt.Errorf("hello")) }) + busi.XaGrpcClient.XaGlobalTransaction(gid, func(xa *dtmgrpc.XaGrpc) error { panic(fmt.Errorf("hello")) }) }) assert.Error(t, err) + waitTransProcessed(gid) } func TestXaGrpcLocalError(t *testing.T) { + gid := dtmimp.GetFuncName() xc := busi.XaGrpcClient - err := xc.XaGlobalTransaction(dtmimp.GetFuncName(), func(xa *dtmgrpc.XaGrpc) error { + err := xc.XaGlobalTransaction(gid, func(xa *dtmgrpc.XaGrpc) error { return fmt.Errorf("an error") }) assert.Error(t, err, fmt.Errorf("an error")) + waitTransProcessed(gid) } diff --git a/test/xa_test.go b/test/xa_test.go index 0515c02..fcb460c 100644 --- a/test/xa_test.go +++ b/test/xa_test.go @@ -118,7 +118,8 @@ func TestXaNotTimeout(t *testing.T) { assert.Nil(t, err) waitTransProcessed(gid) assert.Equal(t, StatusSubmitted, getTransStatus(gid)) - cronTransOnce() + g := cronTransOnce() + assert.Equal(t, gid, g) assert.Equal(t, StatusSucceed, getTransStatus(gid)) assert.Equal(t, []string{StatusPrepared, StatusSucceed}, getBranchesStatus(gid)) } From aae384e597f98e5c21b151ccee9fb4f1431f8fc9 Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Sat, 1 Jan 2022 11:37:48 +0800 Subject: [PATCH 19/22] cover OnAfterResponse --- test/main_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/main_test.go b/test/main_test.go index 31bf4be..2fa6a1c 100644 --- a/test/main_test.go +++ b/test/main_test.go @@ -17,6 +17,7 @@ import ( "github.com/dtm-labs/dtm/dtmsvr" "github.com/dtm-labs/dtm/dtmsvr/config" "github.com/dtm-labs/dtm/test/busi" + "github.com/go-resty/resty/v2" ) func exitIf(code int) { @@ -36,6 +37,7 @@ func TestMain(m *testing.M) { dtmgrpc.AddUnaryInterceptor(busi.SetGrpcHeaderForHeadersYes) dtmcli.OnBeforeRequest(busi.SetHttpHeaderForHeadersYes) + dtmcli.OnAfterResponse(func(c *resty.Client, resp *resty.Response) error { return nil }) tenv := os.Getenv("TEST_STORE") if tenv == "boltdb" { From 4224cbff71b1ef9283e711cc4bd9992e1baea30c Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Sat, 1 Jan 2022 12:06:50 +0800 Subject: [PATCH 20/22] update xa base comment --- dtmcli/dtmimp/trans_xa_base.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dtmcli/dtmimp/trans_xa_base.go b/dtmcli/dtmimp/trans_xa_base.go index 95a8811..cc7e604 100644 --- a/dtmcli/dtmimp/trans_xa_base.go +++ b/dtmcli/dtmimp/trans_xa_base.go @@ -11,7 +11,7 @@ import ( "strings" ) -// XaClientBase XaClient/XaGrpcClient base +// XaClientBase XaClient/XaGrpcClient base. shared by http and grpc type XaClientBase struct { Server string Conf DBConf From 19e24816aae0168ee4047d45799d4354cd67658b Mon Sep 17 00:00:00 2001 From: yedf2 <120050102@qq.com> Date: Sat, 1 Jan 2022 19:17:41 +0800 Subject: [PATCH 21/22] add github author --- README-cn.md | 3 +++ README.md | 2 ++ 2 files changed, 5 insertions(+) diff --git a/README-cn.md b/README-cn.md index a339308..a5acf06 100644 --- a/README-cn.md +++ b/README-cn.md @@ -133,5 +133,8 @@ dtm官方公众号:分布式事务,大量干货分享,以及dtm的最新 ![yedf2008](http://service.ivydad.com/cover/dubbingb6b5e2c0-2d2a-cd59-f7c5-c6b90aceb6f1.jpeg) +### github +作者github: [https://github.com/yedf2](https://github.com/yedf2) + 欢迎使用[dtm](https://github.com/dtm-labs/dtm),或者通过dtm学习实践分布式事务相关知识,欢迎star支持我们 diff --git a/README.md b/README.md index a339308..fc83704 100644 --- a/README.md +++ b/README.md @@ -133,5 +133,7 @@ dtm官方公众号:分布式事务,大量干货分享,以及dtm的最新 ![yedf2008](http://service.ivydad.com/cover/dubbingb6b5e2c0-2d2a-cd59-f7c5-c6b90aceb6f1.jpeg) +作者github: [https://github.com/yedf2](https://github.com/yedf2) + 欢迎使用[dtm](https://github.com/dtm-labs/dtm),或者通过dtm学习实践分布式事务相关知识,欢迎star支持我们 From e42b67fd8e880f49e513ea2e33163f3cb0fcd858 Mon Sep 17 00:00:00 2001 From: fsdfsffdsf Date: Sun, 2 Jan 2022 15:08:44 +0800 Subject: [PATCH 22/22] feature:support tencent distributed database tdsql --- dtmsvr/svr.go | 1 + dtmsvr/trans_status.go | 2 +- dtmsvr/trans_type_saga.go | 12 ++++++--- dtmsvr/utils.go | 1 + sqls/dtmsvr.storage.tdsql.sql | 46 +++++++++++++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 sqls/dtmsvr.storage.tdsql.sql diff --git a/dtmsvr/svr.go b/dtmsvr/svr.go index be40e1c..f891a6f 100644 --- a/dtmsvr/svr.go +++ b/dtmsvr/svr.go @@ -70,6 +70,7 @@ func updateBranchAsync() { case updateBranch := <-updateBranchAsyncChan: updates = append(updates, TransBranch{ ModelBase: dtmutil.ModelBase{ID: updateBranch.id}, + Gid: updateBranch.gid, Status: updateBranch.status, FinishTime: updateBranch.finishTime, }) diff --git a/dtmsvr/trans_status.go b/dtmsvr/trans_status.go index c04110a..ec78533 100644 --- a/dtmsvr/trans_status.go +++ b/dtmsvr/trans_status.go @@ -53,7 +53,7 @@ func (t *TransGlobal) changeBranchStatus(b *TransBranch, status string, branchPo logger.Infof("LockGlobalSaveBranches ok: gid: %s old status: %s branches: %s", b.Gid, dtmcli.StatusPrepared, b.String()) } else { // 为了性能优化,把branch的status更新异步化 - updateBranchAsyncChan <- branchStatus{id: b.ID, status: status, finishTime: &now} + updateBranchAsyncChan <- branchStatus{id: b.ID, gid: t.Gid, status: status, finishTime: &now} } } diff --git a/dtmsvr/trans_type_saga.go b/dtmsvr/trans_type_saga.go index b74dce4..a02e8bc 100644 --- a/dtmsvr/trans_type_saga.go +++ b/dtmsvr/trans_type_saga.go @@ -20,7 +20,8 @@ type transSagaProcessor struct { } func init() { - registorProcessorCreator("saga", func(trans *TransGlobal) transProcessor { return &transSagaProcessor{TransGlobal: trans} }) + registorProcessorCreator("saga", func(trans *TransGlobal) transProcessor { + return &transSagaProcessor{TransGlobal: trans} }) } func (t *transSagaProcessor) GenBranches() []TransBranch { @@ -114,7 +115,8 @@ func (t *transSagaProcessor) ProcessOnce(branches []TransBranch) error { toRun := []int{} for current := 0; current < n; current++ { br := &branchResults[current] - if br.op == dtmcli.BranchAction && !br.started && isPreconditionsSucceed(current) && br.status == dtmcli.StatusPrepared { + if br.op == dtmcli.BranchAction && !br.started && isPreconditionsSucceed(current) && + br.status == dtmcli.StatusPrepared { toRun = append(toRun, current) } } @@ -132,11 +134,13 @@ func (t *transSagaProcessor) ProcessOnce(branches []TransBranch) error { } pickAndRunCompensates := func(toRunActions []int) { for _, b := range toRunActions { - // these branches may have run. so flag them to status succeed, then run the corresponding compensate + // these branches may have run. so flag them to status succeed, then run the corresponding + // compensate branchResults[b].status = dtmcli.StatusSucceed } for i, b := range branchResults { - if b.op == dtmcli.BranchCompensate && b.status != dtmcli.StatusSucceed && branchResults[i+1].status != dtmcli.StatusPrepared { + if b.op == dtmcli.BranchCompensate && b.status != dtmcli.StatusSucceed && + branchResults[i+1].status != dtmcli.StatusPrepared { rsCToStart++ go asyncExecBranch(i) } diff --git a/dtmsvr/utils.go b/dtmsvr/utils.go index 37d938c..c52dce0 100644 --- a/dtmsvr/utils.go +++ b/dtmsvr/utils.go @@ -19,6 +19,7 @@ import ( type branchStatus struct { id uint64 + gid string status string finishTime *time.Time } diff --git a/sqls/dtmsvr.storage.tdsql.sql b/sqls/dtmsvr.storage.tdsql.sql new file mode 100644 index 0000000..09cf816 --- /dev/null +++ b/sqls/dtmsvr.storage.tdsql.sql @@ -0,0 +1,46 @@ +CREATE DATABASE IF NOT EXISTS dtm +/*!40100 DEFAULT CHARACTER SET utf8mb4 */ +; +drop table IF EXISTS dtm.trans_global; +CREATE TABLE if not EXISTS dtm.trans_global ( + `id` bigint(22) NOT NULL AUTO_INCREMENT, + `gid` varchar(128) NOT NULL COMMENT '事务全局id', + `trans_type` varchar(45) not null COMMENT '事务类型: saga | xa | tcc | msg', + -- `data` TEXT COMMENT '事务携带的数据', -- 影响性能,不必要存储 + `status` varchar(12) NOT NULL COMMENT '全局事务的状态 prepared | submitted | aborting | finished | rollbacked', + `query_prepared` varchar(128) NOT NULL COMMENT 'prepared状态事务的查询api', + `protocol` varchar(45) not null comment '通信协议 http | grpc', + `create_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, + `commit_time` datetime DEFAULT NULL, + `finish_time` datetime DEFAULT NULL, + `rollback_time` datetime DEFAULT NULL, + `options` varchar(256) DEFAULT '', + `custom_data` varchar(256) DEFAULT '', + `next_cron_interval` int(11) default null comment '下次定时处理的间隔', + `next_cron_time` datetime default null comment '下次定时处理的时间', + `owner` varchar(128) not null default '' comment '正在处理全局事务的锁定者', + PRIMARY KEY (`id`,`gid`), + UNIQUE KEY `id` (`id`,`gid`), + UNIQUE KEY `gid` (`gid`), + key `owner`(`owner`), + key `status_next_cron_time` (`status`, `next_cron_time`) comment '这个索引用于查询超时的全局事务,能够合理的走索引' +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 shardkey=gid; +drop table IF EXISTS dtm.trans_branch_op; +CREATE TABLE IF NOT EXISTS dtm.trans_branch_op ( + `id` bigint(22) NOT NULL AUTO_INCREMENT, + `gid` varchar(128) NOT NULL COMMENT '事务全局id', + `url` varchar(128) NOT NULL COMMENT '动作关联的url', + `data` TEXT COMMENT '请求所携带的数据', + `bin_data` BLOB COMMENT 'grpc的二进制数据', + `branch_id` VARCHAR(128) NOT NULL COMMENT '事务分支ID', + `op` varchar(45) NOT NULL COMMENT '事务分支类型 saga_action | saga_compensate | xa', + `status` varchar(45) NOT NULL COMMENT '步骤的状态 submitted | finished | rollbacked', + `finish_time` datetime DEFAULT NULL, + `rollback_time` datetime DEFAULT NULL, + `create_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`,`gid`), + UNIQUE KEY `id` (`id`,`gid`), + UNIQUE KEY `gid_uniq` (`gid`, `branch_id`, `op`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 shardkey=gid;