mirror of https://github.com/dtm-labs/dtm.git
committed by
GitHub
93 changed files with 1468 additions and 1977 deletions
@ -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": [] |
|
||||
} |
|
||||
] |
|
||||
} |
|
||||
@ -1,3 +0,0 @@ |
|||||
{ |
|
||||
"go.formatTool": "gofmt" |
|
||||
} |
|
||||
@ -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 {} |
|
||||
} |
|
||||
@ -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 |
|
||||
} |
|
||||
@ -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 |
|
||||
} |
|
||||
@ -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)
|
||||
|
} |
||||
@ -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" |
|
||||
) |
|
||||
@ -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" |
||||
|
) |
||||
@ -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) |
|
||||
} |
|
||||
@ -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 |
|
||||
} |
|
||||
@ -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} |
|
||||
} |
|
||||
@ -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 |
|
||||
}) |
|
||||
} |
|
||||
@ -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 |
|
||||
}) |
|
||||
} |
|
||||
@ -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, "") |
|
||||
}) |
|
||||
} |
|
||||
@ -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 |
|
||||
}) |
|
||||
} |
|
||||
@ -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) |
|
||||
} |
|
||||
@ -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 |
|
||||
}) |
|
||||
|
|
||||
} |
|
||||
@ -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 |
|
||||
}) |
|
||||
} |
|
||||
@ -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 |
|
||||
}) |
|
||||
} |
|
||||
@ -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) |
|
||||
}) |
|
||||
} |
|
||||
@ -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 |
|
||||
}) |
|
||||
} |
|
||||
@ -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 |
|
||||
}) |
|
||||
} |
|
||||
@ -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) |
|
||||
}) |
|
||||
} |
|
||||
@ -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 |
|
||||
}) |
|
||||
} |
|
||||
@ -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 {} |
||||
|
} |
||||
@ -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) |
||||
|
} |
||||
@ -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, "") |
||||
|
}) |
||||
|
} |
||||
@ -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 |
||||
|
} |
||||
@ -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 |
||||
|
} |
||||
@ -1,9 +1,9 @@ |
|||||
syntax = "proto3"; |
syntax = "proto3"; |
||||
|
|
||||
package examples; |
package busi; |
||||
import "google/protobuf/empty.proto"; |
import "google/protobuf/empty.proto"; |
||||
|
|
||||
option go_package = "./examples"; |
option go_package = "./busi"; |
||||
|
|
||||
// DtmRequest request sent to dtm server |
// DtmRequest request sent to dtm server |
||||
message BusiReq { |
message BusiReq { |
||||
@ -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) |
||||
|
} |
||||
@ -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 |
||||
|
} |
||||
@ -0,0 +1,48 @@ |
|||||
|
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" |
||||
|
) |
||||
|
|
||||
|
func TestGeneralDB(t *testing.T) { |
||||
|
if conf.Store.IsDB() { |
||||
|
testSql(t) |
||||
|
testDbAlone(t) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func testSql(t *testing.T) { |
||||
|
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") |
||||
|
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) |
||||
|
} |
||||
|
|
||||
|
func TestMustGenGid(t *testing.T) { |
||||
|
dtmgrpc.MustGenGid(dtmutil.DefaultGrpcServer) |
||||
|
dtmcli.MustGenGid(dtmutil.DefaultHttpServer) |
||||
|
} |
||||
@ -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()) |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue