mirror of https://github.com/dtm-labs/dtm.git
committed by
GitHub
167 changed files with 5615 additions and 4232 deletions
@ -0,0 +1,70 @@ |
|||
# For most projects, this workflow file will not need changing; you simply need |
|||
# to commit it to your repository. |
|||
# |
|||
# You may wish to alter this file to override the set of languages analyzed, |
|||
# or to provide custom queries or build logic. |
|||
# |
|||
# ******** NOTE ******** |
|||
# We have attempted to detect the languages in your repository. Please check |
|||
# the `language` matrix defined below to confirm you have the correct set of |
|||
# supported CodeQL languages. |
|||
# |
|||
name: "CodeQL" |
|||
|
|||
on: |
|||
push: |
|||
branches: [ main ] |
|||
pull_request: |
|||
# The branches below must be a subset of the branches above |
|||
branches: [ main ] |
|||
schedule: |
|||
- cron: '25 19 * * 2' |
|||
|
|||
jobs: |
|||
analyze: |
|||
name: Analyze |
|||
runs-on: ubuntu-latest |
|||
permissions: |
|||
actions: read |
|||
contents: read |
|||
security-events: write |
|||
|
|||
strategy: |
|||
fail-fast: false |
|||
matrix: |
|||
language: [ 'go' ] |
|||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] |
|||
# Learn more about CodeQL language support at https://git.io/codeql-language-support |
|||
|
|||
steps: |
|||
- name: Checkout repository |
|||
uses: actions/checkout@v2 |
|||
|
|||
# Initializes the CodeQL tools for scanning. |
|||
- name: Initialize CodeQL |
|||
uses: github/codeql-action/init@v1 |
|||
with: |
|||
languages: ${{ matrix.language }} |
|||
# If you wish to specify custom queries, you can do so here or in a config file. |
|||
# By default, queries listed here will override any specified in a config file. |
|||
# Prefix the list here with "+" to use these queries and those in the config file. |
|||
# queries: ./path/to/local/query, your-org/your-repo/queries@main |
|||
|
|||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). |
|||
# If this step fails, then you should remove it and run the build manually (see below) |
|||
- name: Autobuild |
|||
uses: github/codeql-action/autobuild@v1 |
|||
|
|||
# ℹ️ Command-line programs to run using the OS shell. |
|||
# 📚 https://git.io/JvXDl |
|||
|
|||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines |
|||
# and modify them (or add more) to build your code if your project |
|||
# uses a compiled language |
|||
|
|||
#- run: | |
|||
# make bootstrap |
|||
# make release |
|||
|
|||
- name: Perform CodeQL Analysis |
|||
uses: github/codeql-action/analyze@v1 |
|||
@ -0,0 +1,48 @@ |
|||
name: Tests |
|||
on: |
|||
push: |
|||
branches-ignore: |
|||
- 'tmp-*' |
|||
pull_request: |
|||
branches-ignore: |
|||
- 'tmp-*' |
|||
|
|||
jobs: |
|||
tests: |
|||
name: CI |
|||
runs-on: ubuntu-latest |
|||
services: |
|||
mysql: |
|||
image: 'mysql:5.7' |
|||
env: |
|||
MYSQL_ALLOW_EMPTY_PASSWORD: 1 |
|||
volumes: |
|||
- /etc/localtime:/etc/localtime:ro |
|||
- /etc/timezone:/etc/timezone:ro |
|||
ports: |
|||
- 3306:3306 |
|||
reids: |
|||
image: 'redis' |
|||
volumes: |
|||
- /etc/localtime:/etc/localtime:ro |
|||
- /etc/timezone:/etc/timezone:ro |
|||
ports: |
|||
- 6379:6379 |
|||
steps: |
|||
- name: Set up Go 1.16 |
|||
uses: actions/setup-go@v2 |
|||
with: |
|||
go-version: '1.16' |
|||
|
|||
- name: Check out code |
|||
uses: actions/checkout@v2 |
|||
|
|||
- name: Install dependencies |
|||
run: | |
|||
go mod download |
|||
|
|||
- name: Run CI lint |
|||
run: make lint |
|||
|
|||
- name: Run test cover |
|||
run: sh helper/test-cover.sh |
|||
@ -1,18 +0,0 @@ |
|||
language: go |
|||
go: |
|||
- 1.15.x |
|||
env: |
|||
- GO111MODULE=on |
|||
branches: |
|||
only: |
|||
- master |
|||
- main |
|||
- alpha |
|||
services: |
|||
- mysql |
|||
- redis-server |
|||
before_install: |
|||
- go get -t -v ./... |
|||
- go get github.com/yedf2/goveralls |
|||
script: |
|||
- $GOPATH/bin/goveralls -envs=TEST_STORE=redis,TEST_STORE=mysql,TEST_STORE=boltdb -flags '-gcflags=-l' -service=travis-ci -ignore="examples/*,dtmgrpc/dtmgimp/*.pb.go,bench/*,test/*" |
|||
@ -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/yedf/dtm/common" |
|||
"github.com/yedf/dtm/dtmcli" |
|||
"github.com/yedf/dtm/dtmcli/dtmimp" |
|||
"github.com/yedf/dtm/dtmsvr" |
|||
"github.com/yedf/dtm/dtmsvr/storage/registry" |
|||
"github.com/yedf/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 |
|||
} |
|||
dtmimp.Logf("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": |
|||
default: |
|||
// 下面是各类的例子
|
|||
examples.GrpcStartup() |
|||
examples.BaseAppStartup() |
|||
|
|||
sample := examples.Samples[os.Args[1]] |
|||
dtmimp.LogIfFatalf(sample == nil, "no sample name for %s", os.Args[1]) |
|||
sample.Action() |
|||
} |
|||
select {} |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
# All targets.
|
|||
default: bench |
|||
|
|||
bench: /usr/local/bin/go /etc/redis/redis.conf /usr/local/bin/docker-compose main.go |
|||
rm -f ../conf.sample.yml |
|||
go build -o bench |
|||
|
|||
go: /usr/local/bin/go |
|||
|
|||
redis: /etc/redis/redis.conf |
|||
|
|||
mysql: /usr/local/bin/docker-compose |
|||
|
|||
/usr/local/bin/go: |
|||
wget https://golang.org/dl/go1.17.1.linux-amd64.tar.gz |
|||
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.17.1.linux-amd64.tar.gz && cp -f /usr/local/go/bin/go /usr/local/bin/go && rm go1.* |
|||
|
|||
/etc/redis/redis.conf: |
|||
apt update |
|||
apt install -y redis redis-tools |
|||
|
|||
/usr/local/bin/docker-compose: |
|||
apt update |
|||
apt install -y sysbench apache2-utils mysql-client-core-8.0 |
|||
curl -fsSL https://get.docker.com | sh |
|||
curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose |
|||
chmod +x /usr/local/bin/docker-compose |
|||
cd .. && docker-compose -f helper/compose.mysql.yml up -d && cd bench |
|||
@ -0,0 +1,10 @@ |
|||
# !/bin/bash |
|||
apt update |
|||
apt install -y git |
|||
git clone https://github.com/dtm-labs/dtm.git && cd dtm && git checkout alpha && cd bench && make |
|||
|
|||
|
|||
echo 'all prepared. you shoud run following commands to test in different terminal' |
|||
echo |
|||
echo 'cd dtm && go run bench/main.go redis|boltdb|db' |
|||
echo 'cd dtm && bench/run-redis|boltdb|mysql.sh' |
|||
@ -1,8 +0,0 @@ |
|||
# !/bin/bash |
|||
|
|||
cd /usr/share/sysbench/ |
|||
echo 'create database sbtest;' > mysql -h 127.0.0.1 -uroot |
|||
|
|||
sysbench oltp_write_only.lua --time=60 --mysql-host=127.0.0.1 --mysql-port=3306 --mysql-user=root --mysql-password= --mysql-db=sbtest --table-size=1000000 --tables=10 --threads=10 --events=999999999 --report-interval=10 prepare |
|||
|
|||
sysbench oltp_write_only.lua --time=60 --mysql-host=127.0.0.1 --mysql-port=3306 --mysql-user=root --mysql-password= --mysql-db=sbtest --table-size=1000000 --tables=10 --threads=10 --events=999999999 --report-interval=10 run |
|||
@ -1,5 +0,0 @@ |
|||
# !/bin/bash |
|||
|
|||
# start all services |
|||
docker-compose -f helper/compose.mysql.yml up -d |
|||
go run app/main.go bench > /dev/nul |
|||
@ -0,0 +1,6 @@ |
|||
# !/bin/bash |
|||
apt update |
|||
apt install -y software-properties-common |
|||
add-apt-repository -y ppa:redislabs/redis |
|||
apt install -y redis redis-tools |
|||
|
|||
@ -0,0 +1,5 @@ |
|||
# !/bin/bash |
|||
|
|||
set -x |
|||
|
|||
ab -n 50000 -c 10 "http://127.0.0.1:8083/api/busi_bench/benchEmptyUrl" |
|||
@ -0,0 +1,27 @@ |
|||
# !/bin/bash |
|||
|
|||
set -x |
|||
|
|||
export LOG_LEVEL=warn |
|||
export STORE_DRIVER=redis |
|||
export STORE_HOST=localhost |
|||
export STORE_PORT=6379 |
|||
cd .. && bench/bench redis & |
|||
echo 'sleeping 3s for dtm bench to run up.' && sleep 3 |
|||
ab -n 1000000 -c 10 "http://127.0.0.1:8083/api/busi_bench/benchEmptyUrl" |
|||
pkill bench |
|||
|
|||
redis-benchmark -n 300000 SET 'abcdefg' 'ddddddd' |
|||
|
|||
redis-benchmark -n 300000 EVAL "redis.call('SET', 'abcdedf', 'ddddddd')" 0 |
|||
|
|||
redis-benchmark -n 300000 EVAL "redis.call('SET', KEYS[1], ARGV[1])" 1 'aaaaaaaaa' 'bbbbbbbbbb' |
|||
|
|||
redis-benchmark -n 3000000 -P 50 SET 'abcdefg' 'ddddddd' |
|||
|
|||
redis-benchmark -n 300000 EVAL "for k=1, 10 do; redis.call('SET', KEYS[1], ARGV[1]);end" 1 'aaaaaaaaa' 'bbbbbbbbbb' |
|||
|
|||
redis-benchmark -n 300000 -P 50 EVAL "redis.call('SET', KEYS[1], ARGV[1])" 1 'aaaaaaaaa' 'bbbbbbbbbb' |
|||
|
|||
redis-benchmark -n 300000 EVAL "for k=1,10 do;local c = cjson.decode(ARGV[1]);end" 1 'aaaaaaaaa' '{"aaaaa":"bbbbb","b":1,"t":"2012-01-01 14:00:00"}' |
|||
|
|||
@ -1,120 +0,0 @@ |
|||
package common |
|||
|
|||
import ( |
|||
"encoding/json" |
|||
"errors" |
|||
"io/ioutil" |
|||
"path/filepath" |
|||
|
|||
"github.com/yedf/dtm/dtmcli" |
|||
"github.com/yedf/dtm/dtmcli/dtmimp" |
|||
"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, |
|||
Passwrod: 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"` |
|||
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) |
|||
dtmimp.FatalIfError(err) |
|||
} |
|||
scont, err := json.MarshalIndent(&Config, "", " ") |
|||
dtmimp.FatalIfError(err) |
|||
dtmimp.Logf("config is: \n%s", scont) |
|||
err = checkConfig() |
|||
dtmimp.LogIfFatalf(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") |
|||
} |
|||
if Config.Store.Driver == BoltDb { |
|||
return nil |
|||
} |
|||
if Config.Store.Driver == 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 ") |
|||
} |
|||
} |
|||
return nil |
|||
} |
|||
@ -1,49 +0,0 @@ |
|||
package common |
|||
|
|||
import ( |
|||
"errors" |
|||
"os" |
|||
"testing" |
|||
|
|||
"github.com/go-playground/assert/v2" |
|||
) |
|||
|
|||
func TestLoadFromEnv(t *testing.T) { |
|||
assert.Equal(t, "MICRO_SERVICE_DRIVER", toUnderscoreUpper("MicroService_Driver")) |
|||
|
|||
ms := MicroService{} |
|||
os.Setenv("T_DRIVER", "d1") |
|||
loadFromEnv("T", &ms) |
|||
assert.Equal(t, "d1", ms.Driver) |
|||
} |
|||
|
|||
func TestCheckConfig(t *testing.T) { |
|||
config := &Config |
|||
retryIntervalErr := checkConfig() |
|||
retryIntervalExpect := errors.New("RetryInterval should not be less than 10") |
|||
assert.Equal(t, retryIntervalErr, retryIntervalExpect) |
|||
|
|||
config.RetryInterval = 10 |
|||
timeoutToFailErr := checkConfig() |
|||
timeoutToFailExpect := errors.New("TimeoutToFail should not be less than RetryInterval") |
|||
assert.Equal(t, timeoutToFailErr, timeoutToFailExpect) |
|||
|
|||
config.TimeoutToFail = 20 |
|||
driverErr := checkConfig() |
|||
assert.Equal(t, driverErr, nil) |
|||
|
|||
config.Store = Store{Driver: Mysql} |
|||
hostErr := checkConfig() |
|||
hostExpect := errors.New("Db host not valid ") |
|||
assert.Equal(t, hostErr, hostExpect) |
|||
|
|||
config.Store = Store{Driver: Mysql, Host: "127.0.0.1"} |
|||
portErr := checkConfig() |
|||
portExpect := errors.New("Db port not valid ") |
|||
assert.Equal(t, portErr, portExpect) |
|||
|
|||
config.Store = Store{Driver: Mysql, Host: "127.0.0.1", Port: 8686} |
|||
userErr := checkConfig() |
|||
userExpect := errors.New("Db user not valid ") |
|||
assert.Equal(t, userErr, userExpect) |
|||
} |
|||
@ -1,30 +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 ( |
|||
"fmt" |
|||
"sync" |
|||
|
|||
"github.com/go-redis/redis/v8" |
|||
"github.com/yedf/dtm/dtmcli/dtmimp" |
|||
) |
|||
|
|||
var rdb *redis.Client |
|||
var once sync.Once |
|||
|
|||
func RedisGet() *redis.Client { |
|||
once.Do(func() { |
|||
dtmimp.Logf("connecting to redis: %v", Config.Store) |
|||
rdb = redis.NewClient(&redis.Options{ |
|||
Addr: fmt.Sprintf("%s:%d", Config.Store.Host, Config.Store.Port), |
|||
Username: Config.Store.User, |
|||
Password: Config.Store.Password, |
|||
}) |
|||
}) |
|||
return rdb |
|||
} |
|||
@ -1,66 +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/stretchr/testify/assert" |
|||
"github.com/yedf/dtm/dtmcli/dtmimp" |
|||
) |
|||
|
|||
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 |
|||
} |
|||
@ -1,121 +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 ( |
|||
"bytes" |
|||
"encoding/json" |
|||
"io/ioutil" |
|||
"os" |
|||
"path/filepath" |
|||
"strings" |
|||
"time" |
|||
|
|||
"github.com/gin-gonic/gin" |
|||
"github.com/go-resty/resty/v2" |
|||
|
|||
"github.com/yedf/dtm/dtmcli" |
|||
"github.com/yedf/dtm/dtmcli/dtmimp" |
|||
) |
|||
|
|||
// GetGinApp init and return gin
|
|||
func GetGinApp() *gin.Engine { |
|||
gin.SetMode(gin.ReleaseMode) |
|||
app := gin.Default() |
|||
app.Use(func(c *gin.Context) { |
|||
body := "" |
|||
if c.Request.Body != nil { |
|||
rb, err := c.GetRawData() |
|||
dtmimp.E2P(err) |
|||
if len(rb) > 0 { |
|||
body = string(rb) |
|||
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(rb)) |
|||
} |
|||
} |
|||
began := time.Now() |
|||
dtmimp.Logf("begin %s %s query: %s body: %s", c.Request.Method, c.FullPath(), c.Request.URL.RawQuery, body) |
|||
c.Next() |
|||
dtmimp.Logf("used %d ms %s %s query: %s body: %s", time.Since(began).Milliseconds(), c.Request.Method, c.FullPath(), c.Request.URL.RawQuery, body) |
|||
|
|||
}) |
|||
app.Any("/api/ping", func(c *gin.Context) { c.JSON(200, map[string]interface{}{"msg": "pong"}) }) |
|||
return app |
|||
} |
|||
|
|||
// WrapHandler name is clear
|
|||
func WrapHandler(fn func(*gin.Context) (interface{}, error)) gin.HandlerFunc { |
|||
return func(c *gin.Context) { |
|||
r, err := func() (r interface{}, rerr error) { |
|||
defer dtmimp.P2E(&rerr) |
|||
return fn(c) |
|||
}() |
|||
var b = []byte{} |
|||
if resp, ok := r.(*resty.Response); ok { // 如果是response,则取出body直接处理
|
|||
b = resp.Body() |
|||
} else if err == nil { |
|||
b, err = json.Marshal(r) |
|||
} |
|||
if err != nil { |
|||
dtmimp.Logf("status: 500, code: 500 message: %s", err.Error()) |
|||
c.JSON(500, map[string]interface{}{"code": 500, "message": err.Error()}) |
|||
} else { |
|||
dtmimp.Logf("status: 200, content: %s", string(b)) |
|||
c.Status(200) |
|||
c.Writer.Header().Add("Content-Type", "application/json") |
|||
_, err = c.Writer.Write(b) |
|||
dtmimp.E2P(err) |
|||
} |
|||
} |
|||
} |
|||
|
|||
// MustGetwd must version of os.Getwd
|
|||
func MustGetwd() string { |
|||
wd, err := os.Getwd() |
|||
dtmimp.E2P(err) |
|||
return wd |
|||
} |
|||
|
|||
// GetSqlDir 获取调用该函数的caller源代码的目录,主要用于测试时,查找相关文件
|
|||
func GetSqlDir() string { |
|||
wd := MustGetwd() |
|||
if filepath.Base(wd) == "test" { |
|||
wd = filepath.Dir(wd) |
|||
} |
|||
return wd + "/sqls" |
|||
} |
|||
|
|||
func RecoverPanic(err *error) { |
|||
if x := recover(); x != nil { |
|||
e := dtmimp.AsError(x) |
|||
if err != nil { |
|||
*err = e |
|||
} |
|||
} |
|||
} |
|||
|
|||
func GetNextTime(second int64) *time.Time { |
|||
next := time.Now().Add(time.Duration(second) * time.Second) |
|||
return &next |
|||
} |
|||
|
|||
// RunSQLScript 1
|
|||
func RunSQLScript(conf dtmcli.DBConf, script string, skipDrop bool) { |
|||
con, err := dtmimp.StandaloneDB(conf) |
|||
dtmimp.FatalIfError(err) |
|||
defer func() { con.Close() }() |
|||
content, err := ioutil.ReadFile(script) |
|||
dtmimp.FatalIfError(err) |
|||
sqls := strings.Split(string(content), ";") |
|||
for _, sql := range sqls { |
|||
s := strings.TrimSpace(sql) |
|||
if s == "" || (skipDrop && strings.Contains(s, "drop")) { |
|||
continue |
|||
} |
|||
_, err = dtmimp.DBExec(con, s) |
|||
dtmimp.FatalIfError(err) |
|||
} |
|||
} |
|||
@ -0,0 +1,2 @@ |
|||
## 注意 |
|||
此包带imp后缀,主要被dtm内部使用,相关接口可能会发生变更,请勿使用这里的接口 |
|||
@ -0,0 +1,111 @@ |
|||
package logger |
|||
|
|||
import ( |
|||
"fmt" |
|||
"log" |
|||
"net/url" |
|||
"os" |
|||
|
|||
"github.com/natefinch/lumberjack" |
|||
"go.uber.org/zap" |
|||
"go.uber.org/zap/zapcore" |
|||
) |
|||
|
|||
//var logger *zap.SugaredLogger = nil
|
|||
|
|||
var logger Logger |
|||
|
|||
func init() { |
|||
InitLog(os.Getenv("LOG_LEVEL")) |
|||
} |
|||
|
|||
// Logger logger interface
|
|||
type Logger interface { |
|||
Debugf(format string, args ...interface{}) |
|||
Infof(format string, args ...interface{}) |
|||
Warnf(format string, args ...interface{}) |
|||
Errorf(format string, args ...interface{}) |
|||
} |
|||
|
|||
type lumberjackSink struct { |
|||
*lumberjack.Logger |
|||
} |
|||
|
|||
func (lumberjackSink) Sync() error { |
|||
return nil |
|||
} |
|||
|
|||
// WithLogger replaces default logger
|
|||
func WithLogger(log Logger) { |
|||
logger = log |
|||
} |
|||
|
|||
// InitLog is an initialization for a logger
|
|||
// level can be: debug info warn error
|
|||
func InitLog(level string) { |
|||
config := loadConfig(level) |
|||
p, err := config.Build(zap.AddCallerSkip(1)) |
|||
FatalIfError(err) |
|||
logger = p.Sugar() |
|||
} |
|||
|
|||
// InitRotateLog is an initialization for a rotated logger by lumberjack
|
|||
func InitRotateLog(logLevel string, ll *lumberjack.Logger) { |
|||
config := loadConfig(logLevel) |
|||
config.OutputPaths = []string{fmt.Sprintf("lumberjack:%s", ll.Filename), "stdout"} |
|||
err := zap.RegisterSink("lumberjack", func(*url.URL) (zap.Sink, error) { |
|||
return lumberjackSink{ |
|||
Logger: ll, |
|||
}, nil |
|||
}) |
|||
FatalIfError(err) |
|||
|
|||
p, err := config.Build(zap.AddCallerSkip(1)) |
|||
FatalIfError(err) |
|||
logger = p.Sugar() |
|||
} |
|||
|
|||
func loadConfig(logLevel string) zap.Config { |
|||
config := zap.NewProductionConfig() |
|||
err := config.Level.UnmarshalText([]byte(logLevel)) |
|||
FatalIfError(err) |
|||
config.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder |
|||
if os.Getenv("DTM_DEBUG") != "" { |
|||
config.Encoding = "console" |
|||
config.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder |
|||
} |
|||
return config |
|||
} |
|||
|
|||
// Debugf log to level debug
|
|||
func Debugf(fmt string, args ...interface{}) { |
|||
logger.Debugf(fmt, args...) |
|||
} |
|||
|
|||
// Infof log to level info
|
|||
func Infof(fmt string, args ...interface{}) { |
|||
logger.Infof(fmt, args...) |
|||
} |
|||
|
|||
// Warnf log to level warn
|
|||
func Warnf(fmt string, args ...interface{}) { |
|||
logger.Warnf(fmt, args...) |
|||
} |
|||
|
|||
// Errorf log to level error
|
|||
func Errorf(fmt string, args ...interface{}) { |
|||
logger.Errorf(fmt, args...) |
|||
} |
|||
|
|||
// FatalfIf log to level error
|
|||
func FatalfIf(cond bool, fmt string, args ...interface{}) { |
|||
if !cond { |
|||
return |
|||
} |
|||
log.Fatalf(fmt, args...) |
|||
} |
|||
|
|||
// FatalIfError if err is not nil, then log to level fatal and call os.Exit
|
|||
func FatalIfError(err error) { |
|||
FatalfIf(err != nil, "fatal error: %v", err) |
|||
} |
|||
@ -0,0 +1,52 @@ |
|||
package logger |
|||
|
|||
import ( |
|||
"os" |
|||
"testing" |
|||
|
|||
"github.com/natefinch/lumberjack" |
|||
"go.uber.org/zap" |
|||
) |
|||
|
|||
func TestInitLog(t *testing.T) { |
|||
os.Setenv("DTM_DEBUG", "1") |
|||
InitLog("debug") |
|||
Debugf("a debug msg") |
|||
Infof("a info msg") |
|||
Warnf("a warn msg") |
|||
Errorf("a error msg") |
|||
FatalfIf(false, "nothing") |
|||
FatalIfError(nil) |
|||
} |
|||
|
|||
func TestWithLogger(t *testing.T) { |
|||
logger := zap.NewExample().Sugar() |
|||
WithLogger(logger) |
|||
Debugf("a debug msg") |
|||
Infof("a info msg") |
|||
Warnf("a warn msg") |
|||
Errorf("a error msg") |
|||
FatalfIf(false, "nothing") |
|||
FatalIfError(nil) |
|||
} |
|||
|
|||
func TestInitRotateLog(t *testing.T) { |
|||
os.Setenv("DTM_DEBUG", "1") |
|||
ll := lumberjack.Logger{ |
|||
Filename: "test.log", |
|||
MaxSize: 1, |
|||
MaxBackups: 1, |
|||
MaxAge: 1, |
|||
Compress: false, |
|||
} |
|||
InitRotateLog("debug", &ll) |
|||
Debugf("a debug msg") |
|||
Infof("a info msg") |
|||
Warnf("a warn msg") |
|||
Errorf("a error msg") |
|||
FatalfIf(false, "nothing") |
|||
FatalIfError(nil) |
|||
s := lumberjackSink{&ll} |
|||
_ = s.Sync() |
|||
_ = os.Remove("test.log") |
|||
} |
|||
@ -0,0 +1,2 @@ |
|||
## 注意 |
|||
此包带imp后缀,主要被dtm内部使用,相关接口可能会发生变更,请勿使用这里的接口 |
|||
@ -1,510 +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. |
|||
*/ |
|||
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
|||
// versions:
|
|||
// protoc-gen-go v1.27.1
|
|||
// protoc v3.17.3
|
|||
// source: dtmgrpc/dtmgimp/dtmgimp.proto
|
|||
|
|||
package dtmgimp |
|||
|
|||
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) |
|||
) |
|||
|
|||
type DtmTransOptions struct { |
|||
state protoimpl.MessageState |
|||
sizeCache protoimpl.SizeCache |
|||
unknownFields protoimpl.UnknownFields |
|||
|
|||
WaitResult bool `protobuf:"varint,1,opt,name=WaitResult,proto3" json:"WaitResult,omitempty"` |
|||
TimeoutToFail int64 `protobuf:"varint,2,opt,name=TimeoutToFail,proto3" json:"TimeoutToFail,omitempty"` |
|||
RetryInterval int64 `protobuf:"varint,3,opt,name=RetryInterval,proto3" json:"RetryInterval,omitempty"` |
|||
} |
|||
|
|||
func (x *DtmTransOptions) Reset() { |
|||
*x = DtmTransOptions{} |
|||
if protoimpl.UnsafeEnabled { |
|||
mi := &file_dtmgrpc_dtmgimp_dtmgimp_proto_msgTypes[0] |
|||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|||
ms.StoreMessageInfo(mi) |
|||
} |
|||
} |
|||
|
|||
func (x *DtmTransOptions) String() string { |
|||
return protoimpl.X.MessageStringOf(x) |
|||
} |
|||
|
|||
func (*DtmTransOptions) ProtoMessage() {} |
|||
|
|||
func (x *DtmTransOptions) ProtoReflect() protoreflect.Message { |
|||
mi := &file_dtmgrpc_dtmgimp_dtmgimp_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 DtmTransOptions.ProtoReflect.Descriptor instead.
|
|||
func (*DtmTransOptions) Descriptor() ([]byte, []int) { |
|||
return file_dtmgrpc_dtmgimp_dtmgimp_proto_rawDescGZIP(), []int{0} |
|||
} |
|||
|
|||
func (x *DtmTransOptions) GetWaitResult() bool { |
|||
if x != nil { |
|||
return x.WaitResult |
|||
} |
|||
return false |
|||
} |
|||
|
|||
func (x *DtmTransOptions) GetTimeoutToFail() int64 { |
|||
if x != nil { |
|||
return x.TimeoutToFail |
|||
} |
|||
return 0 |
|||
} |
|||
|
|||
func (x *DtmTransOptions) GetRetryInterval() int64 { |
|||
if x != nil { |
|||
return x.RetryInterval |
|||
} |
|||
return 0 |
|||
} |
|||
|
|||
// DtmRequest request sent to dtm server
|
|||
type DtmRequest struct { |
|||
state protoimpl.MessageState |
|||
sizeCache protoimpl.SizeCache |
|||
unknownFields protoimpl.UnknownFields |
|||
|
|||
Gid string `protobuf:"bytes,1,opt,name=Gid,proto3" json:"Gid,omitempty"` |
|||
TransType string `protobuf:"bytes,2,opt,name=TransType,proto3" json:"TransType,omitempty"` |
|||
TransOptions *DtmTransOptions `protobuf:"bytes,3,opt,name=TransOptions,proto3" json:"TransOptions,omitempty"` |
|||
CustomedData string `protobuf:"bytes,4,opt,name=CustomedData,proto3" json:"CustomedData,omitempty"` |
|||
BinPayloads [][]byte `protobuf:"bytes,5,rep,name=BinPayloads,proto3" json:"BinPayloads,omitempty"` // for MSG/SAGA branch payloads
|
|||
QueryPrepared string `protobuf:"bytes,6,opt,name=QueryPrepared,proto3" json:"QueryPrepared,omitempty"` // for MSG
|
|||
Steps string `protobuf:"bytes,7,opt,name=Steps,proto3" json:"Steps,omitempty"` |
|||
} |
|||
|
|||
func (x *DtmRequest) Reset() { |
|||
*x = DtmRequest{} |
|||
if protoimpl.UnsafeEnabled { |
|||
mi := &file_dtmgrpc_dtmgimp_dtmgimp_proto_msgTypes[1] |
|||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|||
ms.StoreMessageInfo(mi) |
|||
} |
|||
} |
|||
|
|||
func (x *DtmRequest) String() string { |
|||
return protoimpl.X.MessageStringOf(x) |
|||
} |
|||
|
|||
func (*DtmRequest) ProtoMessage() {} |
|||
|
|||
func (x *DtmRequest) ProtoReflect() protoreflect.Message { |
|||
mi := &file_dtmgrpc_dtmgimp_dtmgimp_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 DtmRequest.ProtoReflect.Descriptor instead.
|
|||
func (*DtmRequest) Descriptor() ([]byte, []int) { |
|||
return file_dtmgrpc_dtmgimp_dtmgimp_proto_rawDescGZIP(), []int{1} |
|||
} |
|||
|
|||
func (x *DtmRequest) GetGid() string { |
|||
if x != nil { |
|||
return x.Gid |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
func (x *DtmRequest) GetTransType() string { |
|||
if x != nil { |
|||
return x.TransType |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
func (x *DtmRequest) GetTransOptions() *DtmTransOptions { |
|||
if x != nil { |
|||
return x.TransOptions |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func (x *DtmRequest) GetCustomedData() string { |
|||
if x != nil { |
|||
return x.CustomedData |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
func (x *DtmRequest) GetBinPayloads() [][]byte { |
|||
if x != nil { |
|||
return x.BinPayloads |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func (x *DtmRequest) GetQueryPrepared() string { |
|||
if x != nil { |
|||
return x.QueryPrepared |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
func (x *DtmRequest) GetSteps() string { |
|||
if x != nil { |
|||
return x.Steps |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
type DtmGidReply struct { |
|||
state protoimpl.MessageState |
|||
sizeCache protoimpl.SizeCache |
|||
unknownFields protoimpl.UnknownFields |
|||
|
|||
Gid string `protobuf:"bytes,1,opt,name=Gid,proto3" json:"Gid,omitempty"` |
|||
} |
|||
|
|||
func (x *DtmGidReply) Reset() { |
|||
*x = DtmGidReply{} |
|||
if protoimpl.UnsafeEnabled { |
|||
mi := &file_dtmgrpc_dtmgimp_dtmgimp_proto_msgTypes[2] |
|||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|||
ms.StoreMessageInfo(mi) |
|||
} |
|||
} |
|||
|
|||
func (x *DtmGidReply) String() string { |
|||
return protoimpl.X.MessageStringOf(x) |
|||
} |
|||
|
|||
func (*DtmGidReply) ProtoMessage() {} |
|||
|
|||
func (x *DtmGidReply) ProtoReflect() protoreflect.Message { |
|||
mi := &file_dtmgrpc_dtmgimp_dtmgimp_proto_msgTypes[2] |
|||
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 DtmGidReply.ProtoReflect.Descriptor instead.
|
|||
func (*DtmGidReply) Descriptor() ([]byte, []int) { |
|||
return file_dtmgrpc_dtmgimp_dtmgimp_proto_rawDescGZIP(), []int{2} |
|||
} |
|||
|
|||
func (x *DtmGidReply) GetGid() string { |
|||
if x != nil { |
|||
return x.Gid |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
type DtmBranchRequest struct { |
|||
state protoimpl.MessageState |
|||
sizeCache protoimpl.SizeCache |
|||
unknownFields protoimpl.UnknownFields |
|||
|
|||
Gid string `protobuf:"bytes,1,opt,name=Gid,proto3" json:"Gid,omitempty"` |
|||
TransType string `protobuf:"bytes,2,opt,name=TransType,proto3" json:"TransType,omitempty"` |
|||
BranchID string `protobuf:"bytes,3,opt,name=BranchID,proto3" json:"BranchID,omitempty"` |
|||
Op string `protobuf:"bytes,4,opt,name=Op,proto3" json:"Op,omitempty"` |
|||
Data map[string]string `protobuf:"bytes,5,rep,name=Data,proto3" json:"Data,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` |
|||
BusiPayload []byte `protobuf:"bytes,6,opt,name=BusiPayload,proto3" json:"BusiPayload,omitempty"` |
|||
} |
|||
|
|||
func (x *DtmBranchRequest) Reset() { |
|||
*x = DtmBranchRequest{} |
|||
if protoimpl.UnsafeEnabled { |
|||
mi := &file_dtmgrpc_dtmgimp_dtmgimp_proto_msgTypes[3] |
|||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|||
ms.StoreMessageInfo(mi) |
|||
} |
|||
} |
|||
|
|||
func (x *DtmBranchRequest) String() string { |
|||
return protoimpl.X.MessageStringOf(x) |
|||
} |
|||
|
|||
func (*DtmBranchRequest) ProtoMessage() {} |
|||
|
|||
func (x *DtmBranchRequest) ProtoReflect() protoreflect.Message { |
|||
mi := &file_dtmgrpc_dtmgimp_dtmgimp_proto_msgTypes[3] |
|||
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 DtmBranchRequest.ProtoReflect.Descriptor instead.
|
|||
func (*DtmBranchRequest) Descriptor() ([]byte, []int) { |
|||
return file_dtmgrpc_dtmgimp_dtmgimp_proto_rawDescGZIP(), []int{3} |
|||
} |
|||
|
|||
func (x *DtmBranchRequest) GetGid() string { |
|||
if x != nil { |
|||
return x.Gid |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
func (x *DtmBranchRequest) GetTransType() string { |
|||
if x != nil { |
|||
return x.TransType |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
func (x *DtmBranchRequest) GetBranchID() string { |
|||
if x != nil { |
|||
return x.BranchID |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
func (x *DtmBranchRequest) GetOp() string { |
|||
if x != nil { |
|||
return x.Op |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
func (x *DtmBranchRequest) GetData() map[string]string { |
|||
if x != nil { |
|||
return x.Data |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func (x *DtmBranchRequest) GetBusiPayload() []byte { |
|||
if x != nil { |
|||
return x.BusiPayload |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
var File_dtmgrpc_dtmgimp_dtmgimp_proto protoreflect.FileDescriptor |
|||
|
|||
var file_dtmgrpc_dtmgimp_dtmgimp_proto_rawDesc = []byte{ |
|||
0x0a, 0x1d, 0x64, 0x74, 0x6d, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, |
|||
0x70, 0x2f, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, |
|||
0x07, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, |
|||
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, |
|||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x7d, 0x0a, 0x0f, 0x44, 0x74, 0x6d, 0x54, 0x72, 0x61, 0x6e, |
|||
0x73, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x57, 0x61, 0x69, 0x74, |
|||
0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x57, 0x61, |
|||
0x69, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x69, 0x6d, 0x65, |
|||
0x6f, 0x75, 0x74, 0x54, 0x6f, 0x46, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, |
|||
0x0d, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x54, 0x6f, 0x46, 0x61, 0x69, 0x6c, 0x12, 0x24, |
|||
0x0a, 0x0d, 0x52, 0x65, 0x74, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, |
|||
0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x52, 0x65, 0x74, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, |
|||
0x72, 0x76, 0x61, 0x6c, 0x22, 0xfc, 0x01, 0x0a, 0x0a, 0x44, 0x74, 0x6d, 0x52, 0x65, 0x71, 0x75, |
|||
0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x47, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, |
|||
0x52, 0x03, 0x47, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x54, 0x79, |
|||
0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x54, |
|||
0x79, 0x70, 0x65, 0x12, 0x3c, 0x0a, 0x0c, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x70, 0x74, 0x69, |
|||
0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x64, 0x74, 0x6d, 0x67, |
|||
0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x70, 0x74, 0x69, |
|||
0x6f, 0x6e, 0x73, 0x52, 0x0c, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, |
|||
0x73, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x64, 0x44, 0x61, 0x74, |
|||
0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, |
|||
0x64, 0x44, 0x61, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x42, 0x69, 0x6e, 0x50, 0x61, 0x79, 0x6c, |
|||
0x6f, 0x61, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0b, 0x42, 0x69, 0x6e, 0x50, |
|||
0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, |
|||
0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, |
|||
0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x64, 0x12, 0x14, 0x0a, |
|||
0x05, 0x53, 0x74, 0x65, 0x70, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x53, 0x74, |
|||
0x65, 0x70, 0x73, 0x22, 0x1f, 0x0a, 0x0b, 0x44, 0x74, 0x6d, 0x47, 0x69, 0x64, 0x52, 0x65, 0x70, |
|||
0x6c, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x47, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, |
|||
0x03, 0x47, 0x69, 0x64, 0x22, 0x82, 0x02, 0x0a, 0x10, 0x44, 0x74, 0x6d, 0x42, 0x72, 0x61, 0x6e, |
|||
0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x47, 0x69, 0x64, |
|||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x47, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x54, |
|||
0x72, 0x61, 0x6e, 0x73, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, |
|||
0x54, 0x72, 0x61, 0x6e, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x42, 0x72, 0x61, |
|||
0x6e, 0x63, 0x68, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x42, 0x72, 0x61, |
|||
0x6e, 0x63, 0x68, 0x49, 0x44, 0x12, 0x0e, 0x0a, 0x02, 0x4f, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, |
|||
0x09, 0x52, 0x02, 0x4f, 0x70, 0x12, 0x37, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, |
|||
0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, |
|||
0x6d, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, |
|||
0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x44, 0x61, 0x74, 0x61, 0x12, 0x20, |
|||
0x0a, 0x0b, 0x42, 0x75, 0x73, 0x69, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x06, 0x20, |
|||
0x01, 0x28, 0x0c, 0x52, 0x0b, 0x42, 0x75, 0x73, 0x69, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, |
|||
0x1a, 0x37, 0x0a, 0x09, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, |
|||
0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, |
|||
0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, |
|||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, 0xb1, 0x02, 0x0a, 0x03, 0x44, 0x74, |
|||
0x6d, 0x12, 0x38, 0x0a, 0x06, 0x4e, 0x65, 0x77, 0x47, 0x69, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, |
|||
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, |
|||
0x70, 0x74, 0x79, 0x1a, 0x14, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, |
|||
0x6d, 0x47, 0x69, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x37, 0x0a, 0x06, 0x53, |
|||
0x75, 0x62, 0x6d, 0x69, 0x74, 0x12, 0x13, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, |
|||
0x44, 0x74, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, |
|||
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, |
|||
0x74, 0x79, 0x22, 0x00, 0x12, 0x38, 0x0a, 0x07, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x12, |
|||
0x13, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x52, 0x65, 0x71, |
|||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, |
|||
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x36, |
|||
0x0a, 0x05, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x12, 0x13, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, |
|||
0x70, 0x2e, 0x44, 0x74, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, |
|||
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, |
|||
0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x45, 0x0a, 0x0e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, |
|||
0x65, 0x72, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x19, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, |
|||
0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, |
|||
0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, |
|||
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x42, 0x0b, 0x5a, |
|||
0x09, 0x2e, 0x2f, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, |
|||
0x6f, 0x33, |
|||
} |
|||
|
|||
var ( |
|||
file_dtmgrpc_dtmgimp_dtmgimp_proto_rawDescOnce sync.Once |
|||
file_dtmgrpc_dtmgimp_dtmgimp_proto_rawDescData = file_dtmgrpc_dtmgimp_dtmgimp_proto_rawDesc |
|||
) |
|||
|
|||
func file_dtmgrpc_dtmgimp_dtmgimp_proto_rawDescGZIP() []byte { |
|||
file_dtmgrpc_dtmgimp_dtmgimp_proto_rawDescOnce.Do(func() { |
|||
file_dtmgrpc_dtmgimp_dtmgimp_proto_rawDescData = protoimpl.X.CompressGZIP(file_dtmgrpc_dtmgimp_dtmgimp_proto_rawDescData) |
|||
}) |
|||
return file_dtmgrpc_dtmgimp_dtmgimp_proto_rawDescData |
|||
} |
|||
|
|||
var file_dtmgrpc_dtmgimp_dtmgimp_proto_msgTypes = make([]protoimpl.MessageInfo, 5) |
|||
var file_dtmgrpc_dtmgimp_dtmgimp_proto_goTypes = []interface{}{ |
|||
(*DtmTransOptions)(nil), // 0: dtmgimp.DtmTransOptions
|
|||
(*DtmRequest)(nil), // 1: dtmgimp.DtmRequest
|
|||
(*DtmGidReply)(nil), // 2: dtmgimp.DtmGidReply
|
|||
(*DtmBranchRequest)(nil), // 3: dtmgimp.DtmBranchRequest
|
|||
nil, // 4: dtmgimp.DtmBranchRequest.DataEntry
|
|||
(*emptypb.Empty)(nil), // 5: google.protobuf.Empty
|
|||
} |
|||
var file_dtmgrpc_dtmgimp_dtmgimp_proto_depIdxs = []int32{ |
|||
0, // 0: dtmgimp.DtmRequest.TransOptions:type_name -> dtmgimp.DtmTransOptions
|
|||
4, // 1: dtmgimp.DtmBranchRequest.Data:type_name -> dtmgimp.DtmBranchRequest.DataEntry
|
|||
5, // 2: dtmgimp.Dtm.NewGid:input_type -> google.protobuf.Empty
|
|||
1, // 3: dtmgimp.Dtm.Submit:input_type -> dtmgimp.DtmRequest
|
|||
1, // 4: dtmgimp.Dtm.Prepare:input_type -> dtmgimp.DtmRequest
|
|||
1, // 5: dtmgimp.Dtm.Abort:input_type -> dtmgimp.DtmRequest
|
|||
3, // 6: dtmgimp.Dtm.RegisterBranch:input_type -> dtmgimp.DtmBranchRequest
|
|||
2, // 7: dtmgimp.Dtm.NewGid:output_type -> dtmgimp.DtmGidReply
|
|||
5, // 8: dtmgimp.Dtm.Submit:output_type -> google.protobuf.Empty
|
|||
5, // 9: dtmgimp.Dtm.Prepare:output_type -> google.protobuf.Empty
|
|||
5, // 10: dtmgimp.Dtm.Abort:output_type -> google.protobuf.Empty
|
|||
5, // 11: dtmgimp.Dtm.RegisterBranch:output_type -> google.protobuf.Empty
|
|||
7, // [7:12] is the sub-list for method output_type
|
|||
2, // [2:7] is the sub-list for method input_type
|
|||
2, // [2:2] is the sub-list for extension type_name
|
|||
2, // [2:2] is the sub-list for extension extendee
|
|||
0, // [0:2] is the sub-list for field type_name
|
|||
} |
|||
|
|||
func init() { file_dtmgrpc_dtmgimp_dtmgimp_proto_init() } |
|||
func file_dtmgrpc_dtmgimp_dtmgimp_proto_init() { |
|||
if File_dtmgrpc_dtmgimp_dtmgimp_proto != nil { |
|||
return |
|||
} |
|||
if !protoimpl.UnsafeEnabled { |
|||
file_dtmgrpc_dtmgimp_dtmgimp_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { |
|||
switch v := v.(*DtmTransOptions); i { |
|||
case 0: |
|||
return &v.state |
|||
case 1: |
|||
return &v.sizeCache |
|||
case 2: |
|||
return &v.unknownFields |
|||
default: |
|||
return nil |
|||
} |
|||
} |
|||
file_dtmgrpc_dtmgimp_dtmgimp_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { |
|||
switch v := v.(*DtmRequest); i { |
|||
case 0: |
|||
return &v.state |
|||
case 1: |
|||
return &v.sizeCache |
|||
case 2: |
|||
return &v.unknownFields |
|||
default: |
|||
return nil |
|||
} |
|||
} |
|||
file_dtmgrpc_dtmgimp_dtmgimp_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { |
|||
switch v := v.(*DtmGidReply); i { |
|||
case 0: |
|||
return &v.state |
|||
case 1: |
|||
return &v.sizeCache |
|||
case 2: |
|||
return &v.unknownFields |
|||
default: |
|||
return nil |
|||
} |
|||
} |
|||
file_dtmgrpc_dtmgimp_dtmgimp_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { |
|||
switch v := v.(*DtmBranchRequest); 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_dtmgrpc_dtmgimp_dtmgimp_proto_rawDesc, |
|||
NumEnums: 0, |
|||
NumMessages: 5, |
|||
NumExtensions: 0, |
|||
NumServices: 1, |
|||
}, |
|||
GoTypes: file_dtmgrpc_dtmgimp_dtmgimp_proto_goTypes, |
|||
DependencyIndexes: file_dtmgrpc_dtmgimp_dtmgimp_proto_depIdxs, |
|||
MessageInfos: file_dtmgrpc_dtmgimp_dtmgimp_proto_msgTypes, |
|||
}.Build() |
|||
File_dtmgrpc_dtmgimp_dtmgimp_proto = out.File |
|||
file_dtmgrpc_dtmgimp_dtmgimp_proto_rawDesc = nil |
|||
file_dtmgrpc_dtmgimp_dtmgimp_proto_goTypes = nil |
|||
file_dtmgrpc_dtmgimp_dtmgimp_proto_depIdxs = nil |
|||
} |
|||
@ -0,0 +1,534 @@ |
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
|||
// versions:
|
|||
// protoc-gen-go v1.27.1
|
|||
// protoc v3.17.3
|
|||
// source: dtmgrpc/dtmgpb/dtmgimp.proto
|
|||
|
|||
package dtmgpb |
|||
|
|||
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) |
|||
) |
|||
|
|||
type DtmTransOptions struct { |
|||
state protoimpl.MessageState |
|||
sizeCache protoimpl.SizeCache |
|||
unknownFields protoimpl.UnknownFields |
|||
|
|||
WaitResult bool `protobuf:"varint,1,opt,name=WaitResult,proto3" json:"WaitResult,omitempty"` |
|||
TimeoutToFail int64 `protobuf:"varint,2,opt,name=TimeoutToFail,proto3" json:"TimeoutToFail,omitempty"` |
|||
RetryInterval int64 `protobuf:"varint,3,opt,name=RetryInterval,proto3" json:"RetryInterval,omitempty"` |
|||
PassthroughHeaders []string `protobuf:"bytes,4,rep,name=PassthroughHeaders,proto3" json:"PassthroughHeaders,omitempty"` |
|||
BranchHeaders map[string]string `protobuf:"bytes,5,rep,name=BranchHeaders,proto3" json:"BranchHeaders,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` |
|||
} |
|||
|
|||
func (x *DtmTransOptions) Reset() { |
|||
*x = DtmTransOptions{} |
|||
if protoimpl.UnsafeEnabled { |
|||
mi := &file_dtmgrpc_dtmgpb_dtmgimp_proto_msgTypes[0] |
|||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|||
ms.StoreMessageInfo(mi) |
|||
} |
|||
} |
|||
|
|||
func (x *DtmTransOptions) String() string { |
|||
return protoimpl.X.MessageStringOf(x) |
|||
} |
|||
|
|||
func (*DtmTransOptions) ProtoMessage() {} |
|||
|
|||
func (x *DtmTransOptions) ProtoReflect() protoreflect.Message { |
|||
mi := &file_dtmgrpc_dtmgpb_dtmgimp_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 DtmTransOptions.ProtoReflect.Descriptor instead.
|
|||
func (*DtmTransOptions) Descriptor() ([]byte, []int) { |
|||
return file_dtmgrpc_dtmgpb_dtmgimp_proto_rawDescGZIP(), []int{0} |
|||
} |
|||
|
|||
func (x *DtmTransOptions) GetWaitResult() bool { |
|||
if x != nil { |
|||
return x.WaitResult |
|||
} |
|||
return false |
|||
} |
|||
|
|||
func (x *DtmTransOptions) GetTimeoutToFail() int64 { |
|||
if x != nil { |
|||
return x.TimeoutToFail |
|||
} |
|||
return 0 |
|||
} |
|||
|
|||
func (x *DtmTransOptions) GetRetryInterval() int64 { |
|||
if x != nil { |
|||
return x.RetryInterval |
|||
} |
|||
return 0 |
|||
} |
|||
|
|||
func (x *DtmTransOptions) GetPassthroughHeaders() []string { |
|||
if x != nil { |
|||
return x.PassthroughHeaders |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func (x *DtmTransOptions) GetBranchHeaders() map[string]string { |
|||
if x != nil { |
|||
return x.BranchHeaders |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
// DtmRequest request sent to dtm server
|
|||
type DtmRequest struct { |
|||
state protoimpl.MessageState |
|||
sizeCache protoimpl.SizeCache |
|||
unknownFields protoimpl.UnknownFields |
|||
|
|||
Gid string `protobuf:"bytes,1,opt,name=Gid,proto3" json:"Gid,omitempty"` |
|||
TransType string `protobuf:"bytes,2,opt,name=TransType,proto3" json:"TransType,omitempty"` |
|||
TransOptions *DtmTransOptions `protobuf:"bytes,3,opt,name=TransOptions,proto3" json:"TransOptions,omitempty"` |
|||
CustomedData string `protobuf:"bytes,4,opt,name=CustomedData,proto3" json:"CustomedData,omitempty"` |
|||
BinPayloads [][]byte `protobuf:"bytes,5,rep,name=BinPayloads,proto3" json:"BinPayloads,omitempty"` // for MSG/SAGA branch payloads
|
|||
QueryPrepared string `protobuf:"bytes,6,opt,name=QueryPrepared,proto3" json:"QueryPrepared,omitempty"` // for MSG
|
|||
Steps string `protobuf:"bytes,7,opt,name=Steps,proto3" json:"Steps,omitempty"` |
|||
} |
|||
|
|||
func (x *DtmRequest) Reset() { |
|||
*x = DtmRequest{} |
|||
if protoimpl.UnsafeEnabled { |
|||
mi := &file_dtmgrpc_dtmgpb_dtmgimp_proto_msgTypes[1] |
|||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|||
ms.StoreMessageInfo(mi) |
|||
} |
|||
} |
|||
|
|||
func (x *DtmRequest) String() string { |
|||
return protoimpl.X.MessageStringOf(x) |
|||
} |
|||
|
|||
func (*DtmRequest) ProtoMessage() {} |
|||
|
|||
func (x *DtmRequest) ProtoReflect() protoreflect.Message { |
|||
mi := &file_dtmgrpc_dtmgpb_dtmgimp_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 DtmRequest.ProtoReflect.Descriptor instead.
|
|||
func (*DtmRequest) Descriptor() ([]byte, []int) { |
|||
return file_dtmgrpc_dtmgpb_dtmgimp_proto_rawDescGZIP(), []int{1} |
|||
} |
|||
|
|||
func (x *DtmRequest) GetGid() string { |
|||
if x != nil { |
|||
return x.Gid |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
func (x *DtmRequest) GetTransType() string { |
|||
if x != nil { |
|||
return x.TransType |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
func (x *DtmRequest) GetTransOptions() *DtmTransOptions { |
|||
if x != nil { |
|||
return x.TransOptions |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func (x *DtmRequest) GetCustomedData() string { |
|||
if x != nil { |
|||
return x.CustomedData |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
func (x *DtmRequest) GetBinPayloads() [][]byte { |
|||
if x != nil { |
|||
return x.BinPayloads |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func (x *DtmRequest) GetQueryPrepared() string { |
|||
if x != nil { |
|||
return x.QueryPrepared |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
func (x *DtmRequest) GetSteps() string { |
|||
if x != nil { |
|||
return x.Steps |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
type DtmGidReply struct { |
|||
state protoimpl.MessageState |
|||
sizeCache protoimpl.SizeCache |
|||
unknownFields protoimpl.UnknownFields |
|||
|
|||
Gid string `protobuf:"bytes,1,opt,name=Gid,proto3" json:"Gid,omitempty"` |
|||
} |
|||
|
|||
func (x *DtmGidReply) Reset() { |
|||
*x = DtmGidReply{} |
|||
if protoimpl.UnsafeEnabled { |
|||
mi := &file_dtmgrpc_dtmgpb_dtmgimp_proto_msgTypes[2] |
|||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|||
ms.StoreMessageInfo(mi) |
|||
} |
|||
} |
|||
|
|||
func (x *DtmGidReply) String() string { |
|||
return protoimpl.X.MessageStringOf(x) |
|||
} |
|||
|
|||
func (*DtmGidReply) ProtoMessage() {} |
|||
|
|||
func (x *DtmGidReply) ProtoReflect() protoreflect.Message { |
|||
mi := &file_dtmgrpc_dtmgpb_dtmgimp_proto_msgTypes[2] |
|||
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 DtmGidReply.ProtoReflect.Descriptor instead.
|
|||
func (*DtmGidReply) Descriptor() ([]byte, []int) { |
|||
return file_dtmgrpc_dtmgpb_dtmgimp_proto_rawDescGZIP(), []int{2} |
|||
} |
|||
|
|||
func (x *DtmGidReply) GetGid() string { |
|||
if x != nil { |
|||
return x.Gid |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
type DtmBranchRequest struct { |
|||
state protoimpl.MessageState |
|||
sizeCache protoimpl.SizeCache |
|||
unknownFields protoimpl.UnknownFields |
|||
|
|||
Gid string `protobuf:"bytes,1,opt,name=Gid,proto3" json:"Gid,omitempty"` |
|||
TransType string `protobuf:"bytes,2,opt,name=TransType,proto3" json:"TransType,omitempty"` |
|||
BranchID string `protobuf:"bytes,3,opt,name=BranchID,proto3" json:"BranchID,omitempty"` |
|||
Op string `protobuf:"bytes,4,opt,name=Op,proto3" json:"Op,omitempty"` |
|||
Data map[string]string `protobuf:"bytes,5,rep,name=Data,proto3" json:"Data,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` |
|||
BusiPayload []byte `protobuf:"bytes,6,opt,name=BusiPayload,proto3" json:"BusiPayload,omitempty"` |
|||
} |
|||
|
|||
func (x *DtmBranchRequest) Reset() { |
|||
*x = DtmBranchRequest{} |
|||
if protoimpl.UnsafeEnabled { |
|||
mi := &file_dtmgrpc_dtmgpb_dtmgimp_proto_msgTypes[3] |
|||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|||
ms.StoreMessageInfo(mi) |
|||
} |
|||
} |
|||
|
|||
func (x *DtmBranchRequest) String() string { |
|||
return protoimpl.X.MessageStringOf(x) |
|||
} |
|||
|
|||
func (*DtmBranchRequest) ProtoMessage() {} |
|||
|
|||
func (x *DtmBranchRequest) ProtoReflect() protoreflect.Message { |
|||
mi := &file_dtmgrpc_dtmgpb_dtmgimp_proto_msgTypes[3] |
|||
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 DtmBranchRequest.ProtoReflect.Descriptor instead.
|
|||
func (*DtmBranchRequest) Descriptor() ([]byte, []int) { |
|||
return file_dtmgrpc_dtmgpb_dtmgimp_proto_rawDescGZIP(), []int{3} |
|||
} |
|||
|
|||
func (x *DtmBranchRequest) GetGid() string { |
|||
if x != nil { |
|||
return x.Gid |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
func (x *DtmBranchRequest) GetTransType() string { |
|||
if x != nil { |
|||
return x.TransType |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
func (x *DtmBranchRequest) GetBranchID() string { |
|||
if x != nil { |
|||
return x.BranchID |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
func (x *DtmBranchRequest) GetOp() string { |
|||
if x != nil { |
|||
return x.Op |
|||
} |
|||
return "" |
|||
} |
|||
|
|||
func (x *DtmBranchRequest) GetData() map[string]string { |
|||
if x != nil { |
|||
return x.Data |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func (x *DtmBranchRequest) GetBusiPayload() []byte { |
|||
if x != nil { |
|||
return x.BusiPayload |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
var File_dtmgrpc_dtmgpb_dtmgimp_proto protoreflect.FileDescriptor |
|||
|
|||
var file_dtmgrpc_dtmgpb_dtmgimp_proto_rawDesc = []byte{ |
|||
0x0a, 0x1c, 0x64, 0x74, 0x6d, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x64, 0x74, 0x6d, 0x67, 0x70, 0x62, |
|||
0x2f, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, |
|||
0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, |
|||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, |
|||
0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc2, 0x02, 0x0a, 0x0f, 0x44, 0x74, 0x6d, 0x54, 0x72, 0x61, 0x6e, |
|||
0x73, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x57, 0x61, 0x69, 0x74, |
|||
0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x57, 0x61, |
|||
0x69, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x69, 0x6d, 0x65, |
|||
0x6f, 0x75, 0x74, 0x54, 0x6f, 0x46, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, |
|||
0x0d, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x54, 0x6f, 0x46, 0x61, 0x69, 0x6c, 0x12, 0x24, |
|||
0x0a, 0x0d, 0x52, 0x65, 0x74, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, |
|||
0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x52, 0x65, 0x74, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, |
|||
0x72, 0x76, 0x61, 0x6c, 0x12, 0x2e, 0x0a, 0x12, 0x50, 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, 0x6f, |
|||
0x75, 0x67, 0x68, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, |
|||
0x52, 0x12, 0x50, 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x48, 0x65, 0x61, |
|||
0x64, 0x65, 0x72, 0x73, 0x12, 0x51, 0x0a, 0x0d, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x48, 0x65, |
|||
0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x64, 0x74, |
|||
0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x70, |
|||
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x48, 0x65, 0x61, 0x64, |
|||
0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, |
|||
0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x42, 0x72, 0x61, 0x6e, 0x63, |
|||
0x68, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, |
|||
0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, |
|||
0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, |
|||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xfc, 0x01, 0x0a, 0x0a, 0x44, 0x74, |
|||
0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x47, 0x69, 0x64, 0x18, |
|||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x47, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x72, |
|||
0x61, 0x6e, 0x73, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x54, |
|||
0x72, 0x61, 0x6e, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x3c, 0x0a, 0x0c, 0x54, 0x72, 0x61, 0x6e, |
|||
0x73, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, |
|||
0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x54, 0x72, 0x61, 0x6e, |
|||
0x73, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0c, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, |
|||
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, |
|||
0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x75, |
|||
0x73, 0x74, 0x6f, 0x6d, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x42, 0x69, |
|||
0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0c, 0x52, |
|||
0x0b, 0x42, 0x69, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x12, 0x24, 0x0a, 0x0d, |
|||
0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x64, 0x18, 0x06, 0x20, |
|||
0x01, 0x28, 0x09, 0x52, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, |
|||
0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x53, 0x74, 0x65, 0x70, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, |
|||
0x09, 0x52, 0x05, 0x53, 0x74, 0x65, 0x70, 0x73, 0x22, 0x1f, 0x0a, 0x0b, 0x44, 0x74, 0x6d, 0x47, |
|||
0x69, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x47, 0x69, 0x64, 0x18, 0x01, |
|||
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x47, 0x69, 0x64, 0x22, 0x82, 0x02, 0x0a, 0x10, 0x44, 0x74, |
|||
0x6d, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, |
|||
0x0a, 0x03, 0x47, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x47, 0x69, 0x64, |
|||
0x12, 0x1c, 0x0a, 0x09, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, |
|||
0x01, 0x28, 0x09, 0x52, 0x09, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, |
|||
0x0a, 0x08, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, |
|||
0x52, 0x08, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x49, 0x44, 0x12, 0x0e, 0x0a, 0x02, 0x4f, 0x70, |
|||
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x4f, 0x70, 0x12, 0x37, 0x0a, 0x04, 0x44, 0x61, |
|||
0x74, 0x61, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, |
|||
0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, |
|||
0x65, 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x44, |
|||
0x61, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x42, 0x75, 0x73, 0x69, 0x50, 0x61, 0x79, 0x6c, 0x6f, |
|||
0x61, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x42, 0x75, 0x73, 0x69, 0x50, 0x61, |
|||
0x79, 0x6c, 0x6f, 0x61, 0x64, 0x1a, 0x37, 0x0a, 0x09, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, |
|||
0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, |
|||
0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, |
|||
0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, 0xb1, |
|||
0x02, 0x0a, 0x03, 0x44, 0x74, 0x6d, 0x12, 0x38, 0x0a, 0x06, 0x4e, 0x65, 0x77, 0x47, 0x69, 0x64, |
|||
0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, |
|||
0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x14, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, |
|||
0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x47, 0x69, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, |
|||
0x12, 0x37, 0x0a, 0x06, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x12, 0x13, 0x2e, 0x64, 0x74, 0x6d, |
|||
0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, |
|||
0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, |
|||
0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x38, 0x0a, 0x07, 0x50, 0x72, 0x65, |
|||
0x70, 0x61, 0x72, 0x65, 0x12, 0x13, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, |
|||
0x74, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, |
|||
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, |
|||
0x79, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x05, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x12, 0x13, 0x2e, 0x64, |
|||
0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, |
|||
0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, |
|||
0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x45, 0x0a, 0x0e, 0x52, |
|||
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x19, 0x2e, |
|||
0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x42, 0x72, 0x61, 0x6e, 0x63, |
|||
0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, |
|||
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, |
|||
0x22, 0x00, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2f, 0x64, 0x74, 0x6d, 0x67, 0x70, 0x62, 0x62, 0x06, |
|||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, |
|||
} |
|||
|
|||
var ( |
|||
file_dtmgrpc_dtmgpb_dtmgimp_proto_rawDescOnce sync.Once |
|||
file_dtmgrpc_dtmgpb_dtmgimp_proto_rawDescData = file_dtmgrpc_dtmgpb_dtmgimp_proto_rawDesc |
|||
) |
|||
|
|||
func file_dtmgrpc_dtmgpb_dtmgimp_proto_rawDescGZIP() []byte { |
|||
file_dtmgrpc_dtmgpb_dtmgimp_proto_rawDescOnce.Do(func() { |
|||
file_dtmgrpc_dtmgpb_dtmgimp_proto_rawDescData = protoimpl.X.CompressGZIP(file_dtmgrpc_dtmgpb_dtmgimp_proto_rawDescData) |
|||
}) |
|||
return file_dtmgrpc_dtmgpb_dtmgimp_proto_rawDescData |
|||
} |
|||
|
|||
var file_dtmgrpc_dtmgpb_dtmgimp_proto_msgTypes = make([]protoimpl.MessageInfo, 6) |
|||
var file_dtmgrpc_dtmgpb_dtmgimp_proto_goTypes = []interface{}{ |
|||
(*DtmTransOptions)(nil), // 0: dtmgimp.DtmTransOptions
|
|||
(*DtmRequest)(nil), // 1: dtmgimp.DtmRequest
|
|||
(*DtmGidReply)(nil), // 2: dtmgimp.DtmGidReply
|
|||
(*DtmBranchRequest)(nil), // 3: dtmgimp.DtmBranchRequest
|
|||
nil, // 4: dtmgimp.DtmTransOptions.BranchHeadersEntry
|
|||
nil, // 5: dtmgimp.DtmBranchRequest.DataEntry
|
|||
(*emptypb.Empty)(nil), // 6: google.protobuf.Empty
|
|||
} |
|||
var file_dtmgrpc_dtmgpb_dtmgimp_proto_depIdxs = []int32{ |
|||
4, // 0: dtmgimp.DtmTransOptions.BranchHeaders:type_name -> dtmgimp.DtmTransOptions.BranchHeadersEntry
|
|||
0, // 1: dtmgimp.DtmRequest.TransOptions:type_name -> dtmgimp.DtmTransOptions
|
|||
5, // 2: dtmgimp.DtmBranchRequest.Data:type_name -> dtmgimp.DtmBranchRequest.DataEntry
|
|||
6, // 3: dtmgimp.Dtm.NewGid:input_type -> google.protobuf.Empty
|
|||
1, // 4: dtmgimp.Dtm.Submit:input_type -> dtmgimp.DtmRequest
|
|||
1, // 5: dtmgimp.Dtm.Prepare:input_type -> dtmgimp.DtmRequest
|
|||
1, // 6: dtmgimp.Dtm.Abort:input_type -> dtmgimp.DtmRequest
|
|||
3, // 7: dtmgimp.Dtm.RegisterBranch:input_type -> dtmgimp.DtmBranchRequest
|
|||
2, // 8: dtmgimp.Dtm.NewGid:output_type -> dtmgimp.DtmGidReply
|
|||
6, // 9: dtmgimp.Dtm.Submit:output_type -> google.protobuf.Empty
|
|||
6, // 10: dtmgimp.Dtm.Prepare:output_type -> google.protobuf.Empty
|
|||
6, // 11: dtmgimp.Dtm.Abort:output_type -> google.protobuf.Empty
|
|||
6, // 12: dtmgimp.Dtm.RegisterBranch:output_type -> google.protobuf.Empty
|
|||
8, // [8:13] is the sub-list for method output_type
|
|||
3, // [3:8] is the sub-list for method input_type
|
|||
3, // [3:3] is the sub-list for extension type_name
|
|||
3, // [3:3] is the sub-list for extension extendee
|
|||
0, // [0:3] is the sub-list for field type_name
|
|||
} |
|||
|
|||
func init() { file_dtmgrpc_dtmgpb_dtmgimp_proto_init() } |
|||
func file_dtmgrpc_dtmgpb_dtmgimp_proto_init() { |
|||
if File_dtmgrpc_dtmgpb_dtmgimp_proto != nil { |
|||
return |
|||
} |
|||
if !protoimpl.UnsafeEnabled { |
|||
file_dtmgrpc_dtmgpb_dtmgimp_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { |
|||
switch v := v.(*DtmTransOptions); i { |
|||
case 0: |
|||
return &v.state |
|||
case 1: |
|||
return &v.sizeCache |
|||
case 2: |
|||
return &v.unknownFields |
|||
default: |
|||
return nil |
|||
} |
|||
} |
|||
file_dtmgrpc_dtmgpb_dtmgimp_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { |
|||
switch v := v.(*DtmRequest); i { |
|||
case 0: |
|||
return &v.state |
|||
case 1: |
|||
return &v.sizeCache |
|||
case 2: |
|||
return &v.unknownFields |
|||
default: |
|||
return nil |
|||
} |
|||
} |
|||
file_dtmgrpc_dtmgpb_dtmgimp_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { |
|||
switch v := v.(*DtmGidReply); i { |
|||
case 0: |
|||
return &v.state |
|||
case 1: |
|||
return &v.sizeCache |
|||
case 2: |
|||
return &v.unknownFields |
|||
default: |
|||
return nil |
|||
} |
|||
} |
|||
file_dtmgrpc_dtmgpb_dtmgimp_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { |
|||
switch v := v.(*DtmBranchRequest); 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_dtmgrpc_dtmgpb_dtmgimp_proto_rawDesc, |
|||
NumEnums: 0, |
|||
NumMessages: 6, |
|||
NumExtensions: 0, |
|||
NumServices: 1, |
|||
}, |
|||
GoTypes: file_dtmgrpc_dtmgpb_dtmgimp_proto_goTypes, |
|||
DependencyIndexes: file_dtmgrpc_dtmgpb_dtmgimp_proto_depIdxs, |
|||
MessageInfos: file_dtmgrpc_dtmgpb_dtmgimp_proto_msgTypes, |
|||
}.Build() |
|||
File_dtmgrpc_dtmgpb_dtmgimp_proto = out.File |
|||
file_dtmgrpc_dtmgpb_dtmgimp_proto_rawDesc = nil |
|||
file_dtmgrpc_dtmgpb_dtmgimp_proto_goTypes = nil |
|||
file_dtmgrpc_dtmgpb_dtmgimp_proto_depIdxs = nil |
|||
} |
|||
@ -0,0 +1,107 @@ |
|||
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 is metric port
|
|||
DtmMetricsPort = 8889 |
|||
// Mysql is mysql driver
|
|||
Mysql = "mysql" |
|||
// Redis is redis driver
|
|||
Redis = "redis" |
|||
// BoltDb is boltdb driver
|
|||
BoltDb = "boltdb" |
|||
// Postgres is postgres driver
|
|||
Postgres = "postgres" |
|||
) |
|||
|
|||
// MicroService config type for micro service
|
|||
type MicroService struct { |
|||
Driver string `yaml:"Driver" default:"default"` |
|||
Target string `yaml:"Target"` |
|||
EndPoint string `yaml:"EndPoint"` |
|||
} |
|||
|
|||
// Log config customize log
|
|||
type Log struct { |
|||
Level string `yaml:"Level" default:"info"` |
|||
Output string `yaml:"Output" default:"console"` |
|||
FileName string `yaml:"FileName" default:"/tmp/dtm.log"` |
|||
FileMaxSize int64 `yaml:"FileMaxSize" default:"10"` |
|||
FileMaxBackups int64 `yaml:"FileMaxBackups" default:"5"` |
|||
FileMaxAge int64 `yaml:"FileMaxAge" default:"30"` |
|||
FileCompress int64 `yaml:"FileCompress" default:"0"` |
|||
} |
|||
|
|||
// Store defines storage relevant info
|
|||
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
|
|||
TransGlobalTable string `yaml:"TransGlobalTable" default:"dtm.trans_global"` |
|||
TransBranchOpTable string `yaml:"TransBranchOpTable" default:"dtm.trans_branch_op"` |
|||
} |
|||
|
|||
// IsDB checks config driver is mysql or postgres
|
|||
func (s *Store) IsDB() bool { |
|||
return s.Driver == dtmcli.DBTypeMysql || s.Driver == dtmcli.DBTypePostgres |
|||
} |
|||
|
|||
// GetDBConf returns db conf info
|
|||
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"` |
|||
RequestTimeout int64 `yaml:"RequestTimeout" default:"3"` |
|||
HTTPPort int64 `yaml:"HttpPort" default:"36789"` |
|||
GrpcPort int64 `yaml:"GrpcPort" default:"36790"` |
|||
MicroService MicroService `yaml:"MicroService"` |
|||
UpdateBranchSync int64 `yaml:"UpdateBranchSync"` |
|||
UpdateBranchAsyncGoroutineNum int64 `yaml:"UpdateBranchAsyncGoroutineNum" default:"1"` |
|||
Log Log `yaml:"Log"` |
|||
} |
|||
|
|||
// 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(&Config) |
|||
logger.FatalfIf(err != nil, `config error: '%v'. |
|||
please visit http://d.dtm.pub to see the config document.`, err)
|
|||
} |
|||
@ -0,0 +1,84 @@ |
|||
package config |
|||
|
|||
import ( |
|||
"errors" |
|||
"os" |
|||
"testing" |
|||
|
|||
"github.com/stretchr/testify/assert" |
|||
) |
|||
|
|||
func TestLoadFromEnv(t *testing.T) { |
|||
assert.Equal(t, "MICRO_SERVICE_DRIVER", toUnderscoreUpper("MicroService_Driver")) |
|||
|
|||
ms := MicroService{} |
|||
os.Setenv("T_DRIVER", "d1") |
|||
loadFromEnv("T", &ms) |
|||
assert.Equal(t, "d1", ms.Driver) |
|||
} |
|||
|
|||
func TestLoadConfig(t *testing.T) { |
|||
MustLoadConfig("../../conf.sample.yml") |
|||
} |
|||
func TestCheckConfig(t *testing.T) { |
|||
conf := Config |
|||
conf.RetryInterval = 1 |
|||
retryIntervalErr := checkConfig(&conf) |
|||
retryIntervalExpect := errors.New("RetryInterval should not be less than 10") |
|||
assert.Equal(t, retryIntervalErr, retryIntervalExpect) |
|||
|
|||
conf.RetryInterval = 10 |
|||
conf.TimeoutToFail = 5 |
|||
timeoutToFailErr := checkConfig(&conf) |
|||
timeoutToFailExpect := errors.New("TimeoutToFail should not be less than RetryInterval") |
|||
assert.Equal(t, timeoutToFailErr, timeoutToFailExpect) |
|||
|
|||
conf.TimeoutToFail = 20 |
|||
driverErr := checkConfig(&conf) |
|||
assert.Equal(t, driverErr, nil) |
|||
|
|||
conf.Store = Store{Driver: Mysql} |
|||
hostErr := checkConfig(&conf) |
|||
hostExpect := errors.New("Db host not valid ") |
|||
assert.Equal(t, hostErr, hostExpect) |
|||
|
|||
conf.Store = Store{Driver: Mysql, Host: "127.0.0.1"} |
|||
portErr := checkConfig(&conf) |
|||
portExpect := errors.New("Db port not valid ") |
|||
assert.Equal(t, portErr, portExpect) |
|||
|
|||
conf.Store = Store{Driver: Mysql, Host: "127.0.0.1", Port: 8686} |
|||
userErr := checkConfig(&conf) |
|||
userExpect := errors.New("Db user not valid ") |
|||
assert.Equal(t, userErr, userExpect) |
|||
|
|||
conf.Store = Store{Driver: Redis, Host: "", Port: 8686} |
|||
assert.Equal(t, errors.New("Redis host not valid"), checkConfig(&conf)) |
|||
|
|||
conf.Store = Store{Driver: Redis, Host: "127.0.0.1", Port: 0} |
|||
assert.Equal(t, errors.New("Redis port not valid"), checkConfig(&conf)) |
|||
|
|||
} |
|||
|
|||
func TestConfig(t *testing.T) { |
|||
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(&Config) |
|||
assert.NotEqual(t, "", str) |
|||
*fd = old |
|||
} |
|||
|
|||
func testConfigIntField(fd *int64, val int64, t *testing.T) { |
|||
old := *fd |
|||
*fd = val |
|||
str := checkConfig(&Config) |
|||
assert.NotEqual(t, "", str) |
|||
*fd = old |
|||
} |
|||
@ -1,257 +0,0 @@ |
|||
package storage |
|||
|
|||
import ( |
|||
"context" |
|||
"fmt" |
|||
"time" |
|||
|
|||
"github.com/go-redis/redis/v8" |
|||
"github.com/yedf/dtm/common" |
|||
"github.com/yedf/dtm/dtmcli/dtmimp" |
|||
"gorm.io/gorm" |
|||
) |
|||
|
|||
var ctx context.Context = context.Background() |
|||
|
|||
type RedisStore struct { |
|||
} |
|||
|
|||
func (s *RedisStore) Ping() error { |
|||
_, err := redisGet().Ping(ctx).Result() |
|||
return err |
|||
} |
|||
|
|||
func (s *RedisStore) PopulateData(skipDrop bool) { |
|||
_, err := redisGet().FlushAll(ctx).Result() |
|||
dtmimp.PanicIf(err != nil, err) |
|||
} |
|||
|
|||
func (s *RedisStore) FindTransGlobalStore(gid string) *TransGlobalStore { |
|||
r, err := redisGet().Get(ctx, config.Store.RedisPrefix+"_g_"+gid).Result() |
|||
if err == redis.Nil { |
|||
return nil |
|||
} |
|||
dtmimp.E2P(err) |
|||
trans := &TransGlobalStore{} |
|||
dtmimp.MustUnmarshalString(r, trans) |
|||
return trans |
|||
} |
|||
|
|||
func (s *RedisStore) ScanTransGlobalStores(position *string, limit int64) []TransGlobalStore { |
|||
lid := uint64(0) |
|||
if *position != "" { |
|||
lid = uint64(dtmimp.MustAtoi(*position)) |
|||
} |
|||
keys, cursor, err := redisGet().Scan(ctx, lid, config.Store.RedisPrefix+"_g_*", limit).Result() |
|||
dtmimp.E2P(err) |
|||
globals := []TransGlobalStore{} |
|||
if len(keys) > 0 { |
|||
values, err := redisGet().MGet(ctx, keys...).Result() |
|||
dtmimp.E2P(err) |
|||
for _, v := range values { |
|||
global := TransGlobalStore{} |
|||
dtmimp.MustUnmarshalString(v.(string), &global) |
|||
globals = append(globals, global) |
|||
} |
|||
} |
|||
if cursor > 0 { |
|||
*position = fmt.Sprintf("%d", cursor) |
|||
} else { |
|||
*position = "" |
|||
} |
|||
return globals |
|||
} |
|||
|
|||
func (s *RedisStore) FindBranches(gid string) []TransBranchStore { |
|||
sa, err := redisGet().LRange(ctx, config.Store.RedisPrefix+"_b_"+gid, 0, -1).Result() |
|||
dtmimp.E2P(err) |
|||
branches := make([]TransBranchStore, len(sa)) |
|||
for k, v := range sa { |
|||
dtmimp.MustUnmarshalString(v, &branches[k]) |
|||
} |
|||
return branches |
|||
} |
|||
|
|||
func (s *RedisStore) UpdateBranchesSql(branches []TransBranchStore, updates []string) *gorm.DB { |
|||
return nil // not implemented
|
|||
} |
|||
|
|||
type argList struct { |
|||
Keys []string |
|||
List []interface{} |
|||
} |
|||
|
|||
func newArgList() *argList { |
|||
a := &argList{} |
|||
return a.AppendRaw(config.Store.RedisPrefix).AppendObject(config.Store.DataExpire) |
|||
} |
|||
|
|||
func (a *argList) AppendGid(gid string) *argList { |
|||
a.Keys = append(a.Keys, config.Store.RedisPrefix+"_g_"+gid) |
|||
a.Keys = append(a.Keys, config.Store.RedisPrefix+"_b_"+gid) |
|||
a.Keys = append(a.Keys, config.Store.RedisPrefix+"_u") |
|||
return a |
|||
} |
|||
|
|||
func (a *argList) AppendRaw(v interface{}) *argList { |
|||
a.List = append(a.List, v) |
|||
return a |
|||
} |
|||
|
|||
func (a *argList) AppendObject(v interface{}) *argList { |
|||
return a.AppendRaw(dtmimp.MustMarshalString(v)) |
|||
} |
|||
|
|||
func (a *argList) AppendBranches(branches []TransBranchStore) *argList { |
|||
for _, b := range branches { |
|||
a.AppendRaw(dtmimp.MustMarshalString(b)) |
|||
} |
|||
return a |
|||
} |
|||
|
|||
func handleRedisResult(ret interface{}, err error) (string, error) { |
|||
dtmimp.Logf("result is: '%v', err: '%v'", ret, err) |
|||
if err != nil && err != redis.Nil { |
|||
return "", err |
|||
} |
|||
s, _ := ret.(string) |
|||
err = map[string]error{ |
|||
"NOT_FOUND": ErrNotFound, |
|||
"UNIQUE_CONFLICT": ErrUniqueConflict, |
|||
}[s] |
|||
return s, err |
|||
} |
|||
|
|||
func callLua(a *argList, lua string) (string, error) { |
|||
dtmimp.Logf("calling lua. args: %v\nlua:%s", a, lua) |
|||
ret, err := redisGet().Eval(ctx, lua, a.Keys, a.List...).Result() |
|||
return handleRedisResult(ret, err) |
|||
} |
|||
|
|||
func (s *RedisStore) MaySaveNewTrans(global *TransGlobalStore, branches []TransBranchStore) error { |
|||
a := newArgList(). |
|||
AppendGid(global.Gid). |
|||
AppendObject(global). |
|||
AppendRaw(global.NextCronTime.Unix()). |
|||
AppendBranches(branches) |
|||
global.Steps = nil |
|||
global.Payloads = nil |
|||
_, err := callLua(a, `-- MaySaveNewTrans |
|||
local gs = cjson.decode(ARGV[3]) |
|||
local g = redis.call('GET', KEYS[1]) |
|||
if g ~= false then |
|||
return 'UNIQUE_CONFLICT' |
|||
end |
|||
|
|||
redis.call('SET', KEYS[1], ARGV[3], 'EX', ARGV[2]) |
|||
redis.call('ZADD', KEYS[3], ARGV[4], gs.gid) |
|||
for k = 5, table.getn(ARGV) do |
|||
redis.call('RPUSH', KEYS[2], ARGV[k]) |
|||
end |
|||
redis.call('EXPIRE', KEYS[2], ARGV[2]) |
|||
`) |
|||
return err |
|||
} |
|||
|
|||
func (s *RedisStore) LockGlobalSaveBranches(gid string, status string, branches []TransBranchStore, branchStart int) { |
|||
args := newArgList(). |
|||
AppendGid(gid). |
|||
AppendObject(&TransGlobalStore{Gid: gid, Status: status}). |
|||
AppendRaw(branchStart). |
|||
AppendBranches(branches) |
|||
_, err := callLua(args, ` |
|||
local gs = cjson.decode(ARGV[3]) |
|||
local g = redis.call('GET', KEYS[1]) |
|||
if (g == false) then |
|||
return 'NOT_FOUND' |
|||
end |
|||
local js = cjson.decode(g) |
|||
if js.status ~= gs.status then |
|||
return 'NOT_FOUND' |
|||
end |
|||
local start = ARGV[4] |
|||
for k = 5, table.getn(ARGV) do |
|||
if start == "-1" then |
|||
redis.call('RPUSH', KEYS[2], ARGV[k]) |
|||
else |
|||
redis.call('LSET', KEYS[2], start+k-5, ARGV[k]) |
|||
end |
|||
end |
|||
redis.call('EXPIRE', KEYS[2], ARGV[2]) |
|||
`) |
|||
dtmimp.E2P(err) |
|||
} |
|||
|
|||
func (s *RedisStore) ChangeGlobalStatus(global *TransGlobalStore, newStatus string, updates []string, finished bool) { |
|||
old := global.Status |
|||
global.Status = newStatus |
|||
args := newArgList().AppendGid(global.Gid).AppendObject(global).AppendRaw(old).AppendRaw(finished) |
|||
_, err := callLua(args, `-- ChangeGlobalStatus |
|||
local gs = cjson.decode(ARGV[3]) |
|||
local old = redis.call('GET', KEYS[1]) |
|||
if old == false then |
|||
return 'NOT_FOUND' |
|||
end |
|||
local os = cjson.decode(old) |
|||
if os.status ~= ARGV[4] then |
|||
return 'NOT_FOUND' |
|||
end |
|||
redis.call('SET', KEYS[1], ARGV[3], 'EX', ARGV[2]) |
|||
redis.log(redis.LOG_WARNING, 'finished: ', ARGV[5]) |
|||
if ARGV[5] == '1' then |
|||
redis.call('ZREM', KEYS[3], gs.gid) |
|||
end |
|||
`) |
|||
dtmimp.E2P(err) |
|||
} |
|||
|
|||
func (s *RedisStore) LockOneGlobalTrans(expireIn time.Duration) *TransGlobalStore { |
|||
expired := time.Now().Add(expireIn).Unix() |
|||
next := time.Now().Add(time.Duration(config.RetryInterval) * time.Second).Unix() |
|||
args := newArgList().AppendGid("").AppendRaw(expired).AppendRaw(next) |
|||
lua := `-- LocakOneGlobalTrans |
|||
local r = redis.call('ZRANGE', KEYS[3], 0, 0, 'WITHSCORES') |
|||
local gid = r[1] |
|||
if gid == nil then |
|||
return 'NOT_FOUND' |
|||
end |
|||
|
|||
if tonumber(r[2]) > tonumber(ARGV[3]) then |
|||
return 'NOT_FOUND' |
|||
end |
|||
redis.call('ZADD', KEYS[3], ARGV[4], gid) |
|||
return gid |
|||
` |
|||
for { |
|||
r, err := callLua(args, lua) |
|||
if err == ErrNotFound { |
|||
return nil |
|||
} |
|||
dtmimp.E2P(err) |
|||
global := s.FindTransGlobalStore(r) |
|||
if global != nil { |
|||
return global |
|||
} |
|||
} |
|||
} |
|||
|
|||
func (s *RedisStore) TouchCronTime(global *TransGlobalStore, nextCronInterval int64) { |
|||
global.NextCronTime = common.GetNextTime(nextCronInterval) |
|||
global.UpdateTime = common.GetNextTime(0) |
|||
global.NextCronInterval = nextCronInterval |
|||
args := newArgList().AppendGid(global.Gid).AppendObject(global).AppendRaw(global.NextCronTime.Unix()) |
|||
_, err := callLua(args, `-- TouchCronTime |
|||
local g = cjson.decode(ARGV[3]) |
|||
local old = redis.call('GET', KEYS[1]) |
|||
if old == false then |
|||
return 'NOT_FOUND' |
|||
end |
|||
local os = cjson.decode(old) |
|||
if os.status ~= g.status then |
|||
return 'NOT_FOUND' |
|||
end |
|||
redis.call('ZADD', KEYS[3], ARGV[4], g.gid) |
|||
redis.call('SET', KEYS[1], ARGV[3], 'EX', ARGV[2]) |
|||
`) |
|||
dtmimp.E2P(err) |
|||
} |
|||
@ -0,0 +1,300 @@ |
|||
package redis |
|||
|
|||
import ( |
|||
"context" |
|||
"errors" |
|||
"fmt" |
|||
"sync" |
|||
"time" |
|||
|
|||
"github.com/go-redis/redis/v8" |
|||
|
|||
"github.com/dtm-labs/dtm/dtmcli/dtmimp" |
|||
"github.com/dtm-labs/dtm/dtmcli/logger" |
|||
"github.com/dtm-labs/dtm/dtmsvr/config" |
|||
"github.com/dtm-labs/dtm/dtmsvr/storage" |
|||
"github.com/dtm-labs/dtm/dtmutil" |
|||
) |
|||
|
|||
// TODO: optimize this, it's very strange to use pointer to dtmutil.Config
|
|||
var conf = &config.Config |
|||
|
|||
// TODO: optimize this, all function should have context as first parameter
|
|||
var ctx = context.Background() |
|||
|
|||
// Store is the storage with redis, all transaction information will bachend with redis
|
|||
type Store struct { |
|||
} |
|||
|
|||
// Ping execs ping cmd to redis
|
|||
func (s *Store) Ping() error { |
|||
_, err := redisGet().Ping(ctx).Result() |
|||
return err |
|||
} |
|||
|
|||
// PopulateData populates data to redis
|
|||
func (s *Store) PopulateData(skipDrop bool) { |
|||
if !skipDrop { |
|||
_, err := redisGet().FlushAll(ctx).Result() |
|||
logger.Infof("call redis flushall. result: %v", err) |
|||
dtmimp.PanicIf(err != nil, err) |
|||
} |
|||
} |
|||
|
|||
// FindTransGlobalStore finds GlobalTrans data by gid
|
|||
func (s *Store) FindTransGlobalStore(gid string) *storage.TransGlobalStore { |
|||
logger.Debugf("calling FindTransGlobalStore: %s", gid) |
|||
r, err := redisGet().Get(ctx, conf.Store.RedisPrefix+"_g_"+gid).Result() |
|||
if err == redis.Nil { |
|||
return nil |
|||
} |
|||
dtmimp.E2P(err) |
|||
trans := &storage.TransGlobalStore{} |
|||
dtmimp.MustUnmarshalString(r, trans) |
|||
return trans |
|||
} |
|||
|
|||
// ScanTransGlobalStores lists GlobalTrans data
|
|||
func (s *Store) ScanTransGlobalStores(position *string, limit int64) []storage.TransGlobalStore { |
|||
logger.Debugf("calling ScanTransGlobalStores: %s %d", *position, limit) |
|||
lid := uint64(0) |
|||
if *position != "" { |
|||
lid = uint64(dtmimp.MustAtoi(*position)) |
|||
} |
|||
keys, cursor, err := redisGet().Scan(ctx, lid, conf.Store.RedisPrefix+"_g_*", limit).Result() |
|||
dtmimp.E2P(err) |
|||
globals := []storage.TransGlobalStore{} |
|||
if len(keys) > 0 { |
|||
values, err := redisGet().MGet(ctx, keys...).Result() |
|||
dtmimp.E2P(err) |
|||
for _, v := range values { |
|||
global := storage.TransGlobalStore{} |
|||
dtmimp.MustUnmarshalString(v.(string), &global) |
|||
globals = append(globals, global) |
|||
} |
|||
} |
|||
if cursor > 0 { |
|||
*position = fmt.Sprintf("%d", cursor) |
|||
} else { |
|||
*position = "" |
|||
} |
|||
return globals |
|||
} |
|||
|
|||
// FindBranches finds Branch data by gid
|
|||
func (s *Store) FindBranches(gid string) []storage.TransBranchStore { |
|||
logger.Debugf("calling FindBranches: %s", gid) |
|||
sa, err := redisGet().LRange(ctx, conf.Store.RedisPrefix+"_b_"+gid, 0, -1).Result() |
|||
dtmimp.E2P(err) |
|||
branches := make([]storage.TransBranchStore, len(sa)) |
|||
for k, v := range sa { |
|||
dtmimp.MustUnmarshalString(v, &branches[k]) |
|||
} |
|||
return branches |
|||
} |
|||
|
|||
// UpdateBranches updates branches info
|
|||
func (s *Store) UpdateBranches(branches []storage.TransBranchStore, updates []string) (int, error) { |
|||
return 0, nil // not implemented
|
|||
} |
|||
|
|||
type argList struct { |
|||
Keys []string |
|||
List []interface{} |
|||
} |
|||
|
|||
func newArgList() *argList { |
|||
a := &argList{} |
|||
return a.AppendRaw(conf.Store.RedisPrefix).AppendObject(conf.Store.DataExpire) |
|||
} |
|||
|
|||
func (a *argList) AppendGid(gid string) *argList { |
|||
a.Keys = append(a.Keys, conf.Store.RedisPrefix+"_g_"+gid) |
|||
a.Keys = append(a.Keys, conf.Store.RedisPrefix+"_b_"+gid) |
|||
a.Keys = append(a.Keys, conf.Store.RedisPrefix+"_u") |
|||
a.Keys = append(a.Keys, conf.Store.RedisPrefix+"_s_"+gid) |
|||
return a |
|||
} |
|||
|
|||
func (a *argList) AppendRaw(v interface{}) *argList { |
|||
a.List = append(a.List, v) |
|||
return a |
|||
} |
|||
|
|||
func (a *argList) AppendObject(v interface{}) *argList { |
|||
return a.AppendRaw(dtmimp.MustMarshalString(v)) |
|||
} |
|||
|
|||
func (a *argList) AppendBranches(branches []storage.TransBranchStore) *argList { |
|||
for _, b := range branches { |
|||
a.AppendRaw(dtmimp.MustMarshalString(b)) |
|||
} |
|||
return a |
|||
} |
|||
|
|||
func handleRedisResult(ret interface{}, err error) (string, error) { |
|||
logger.Debugf("result is: '%v', err: '%v'", ret, err) |
|||
if err != nil && err != redis.Nil { |
|||
return "", err |
|||
} |
|||
s, _ := ret.(string) |
|||
err = map[string]error{ |
|||
"NOT_FOUND": storage.ErrNotFound, |
|||
"UNIQUE_CONFLICT": storage.ErrUniqueConflict, |
|||
}[s] |
|||
return s, err |
|||
} |
|||
|
|||
func callLua(a *argList, lua string) (string, error) { |
|||
logger.Debugf("calling lua. args: %v\nlua:%s", a, lua) |
|||
ret, err := redisGet().Eval(ctx, lua, a.Keys, a.List...).Result() |
|||
return handleRedisResult(ret, err) |
|||
} |
|||
|
|||
// MaySaveNewTrans creates a new trans
|
|||
func (s *Store) MaySaveNewTrans(global *storage.TransGlobalStore, branches []storage.TransBranchStore) error { |
|||
a := newArgList(). |
|||
AppendGid(global.Gid). |
|||
AppendObject(global). |
|||
AppendRaw(global.NextCronTime.Unix()). |
|||
AppendRaw(global.Gid). |
|||
AppendRaw(global.Status). |
|||
AppendBranches(branches) |
|||
global.Steps = nil |
|||
global.Payloads = nil |
|||
_, err := callLua(a, `-- MaySaveNewTrans |
|||
local g = redis.call('GET', KEYS[1]) |
|||
if g ~= false then |
|||
return 'UNIQUE_CONFLICT' |
|||
end |
|||
|
|||
redis.call('SET', KEYS[1], ARGV[3], 'EX', ARGV[2]) |
|||
redis.call('SET', KEYS[4], ARGV[6], 'EX', ARGV[2]) |
|||
redis.call('ZADD', KEYS[3], ARGV[4], ARGV[5]) |
|||
for k = 7, table.getn(ARGV) do |
|||
redis.call('RPUSH', KEYS[2], ARGV[k]) |
|||
end |
|||
redis.call('EXPIRE', KEYS[2], ARGV[2]) |
|||
`) |
|||
return err |
|||
} |
|||
|
|||
// LockGlobalSaveBranches creates branches
|
|||
func (s *Store) LockGlobalSaveBranches(gid string, status string, branches []storage.TransBranchStore, branchStart int) { |
|||
args := newArgList(). |
|||
AppendGid(gid). |
|||
AppendRaw(status). |
|||
AppendRaw(branchStart). |
|||
AppendBranches(branches) |
|||
_, err := callLua(args, `-- LockGlobalSaveBranches |
|||
local old = redis.call('GET', KEYS[4]) |
|||
if old ~= ARGV[3] then |
|||
return 'NOT_FOUND' |
|||
end |
|||
local start = ARGV[4] |
|||
for k = 5, table.getn(ARGV) do |
|||
if start == "-1" then |
|||
redis.call('RPUSH', KEYS[2], ARGV[k]) |
|||
else |
|||
redis.call('LSET', KEYS[2], start+k-5, ARGV[k]) |
|||
end |
|||
end |
|||
redis.call('EXPIRE', KEYS[2], ARGV[2]) |
|||
`) |
|||
dtmimp.E2P(err) |
|||
} |
|||
|
|||
// ChangeGlobalStatus changes global trans status
|
|||
func (s *Store) ChangeGlobalStatus(global *storage.TransGlobalStore, newStatus string, updates []string, finished bool) { |
|||
old := global.Status |
|||
global.Status = newStatus |
|||
args := newArgList(). |
|||
AppendGid(global.Gid). |
|||
AppendObject(global). |
|||
AppendRaw(old). |
|||
AppendRaw(finished). |
|||
AppendRaw(global.Gid). |
|||
AppendRaw(newStatus) |
|||
_, err := callLua(args, `-- ChangeGlobalStatus |
|||
local old = redis.call('GET', KEYS[4]) |
|||
if old ~= ARGV[4] then |
|||
return 'NOT_FOUND' |
|||
end |
|||
redis.call('SET', KEYS[1], ARGV[3], 'EX', ARGV[2]) |
|||
redis.call('SET', KEYS[4], ARGV[7], 'EX', ARGV[2]) |
|||
if ARGV[5] == '1' then |
|||
redis.call('ZREM', KEYS[3], ARGV[6]) |
|||
end |
|||
`) |
|||
dtmimp.E2P(err) |
|||
} |
|||
|
|||
// LockOneGlobalTrans finds GlobalTrans
|
|||
func (s *Store) LockOneGlobalTrans(expireIn time.Duration) *storage.TransGlobalStore { |
|||
expired := time.Now().Add(expireIn).Unix() |
|||
next := time.Now().Add(time.Duration(conf.RetryInterval) * time.Second).Unix() |
|||
args := newArgList().AppendGid("").AppendRaw(expired).AppendRaw(next) |
|||
lua := `-- LockOneGlobalTrans |
|||
local r = redis.call('ZRANGE', KEYS[3], 0, 0, 'WITHSCORES') |
|||
local gid = r[1] |
|||
if gid == nil then |
|||
return 'NOT_FOUND' |
|||
end |
|||
|
|||
if tonumber(r[2]) > tonumber(ARGV[3]) then |
|||
return 'NOT_FOUND' |
|||
end |
|||
redis.call('ZADD', KEYS[3], ARGV[4], gid) |
|||
return gid |
|||
` |
|||
for { |
|||
r, err := callLua(args, lua) |
|||
if errors.Is(err, storage.ErrNotFound) { |
|||
return nil |
|||
} |
|||
dtmimp.E2P(err) |
|||
global := s.FindTransGlobalStore(r) |
|||
if global != nil { |
|||
return global |
|||
} |
|||
} |
|||
} |
|||
|
|||
// TouchCronTime updates cronTime
|
|||
func (s *Store) TouchCronTime(global *storage.TransGlobalStore, nextCronInterval int64) { |
|||
global.NextCronTime = dtmutil.GetNextTime(nextCronInterval) |
|||
global.UpdateTime = dtmutil.GetNextTime(0) |
|||
global.NextCronInterval = nextCronInterval |
|||
args := newArgList(). |
|||
AppendGid(global.Gid). |
|||
AppendObject(global). |
|||
AppendRaw(global.NextCronTime.Unix()). |
|||
AppendRaw(global.Status). |
|||
AppendRaw(global.Gid) |
|||
_, err := callLua(args, `-- TouchCronTime |
|||
local old = redis.call('GET', KEYS[4]) |
|||
if old ~= ARGV[5] then |
|||
return 'NOT_FOUND' |
|||
end |
|||
redis.call('ZADD', KEYS[3], ARGV[4], ARGV[6]) |
|||
redis.call('SET', KEYS[1], ARGV[3], 'EX', ARGV[2]) |
|||
`) |
|||
dtmimp.E2P(err) |
|||
} |
|||
|
|||
var ( |
|||
rdb *redis.Client |
|||
once sync.Once |
|||
) |
|||
|
|||
func redisGet() *redis.Client { |
|||
once.Do(func() { |
|||
logger.Debugf("connecting to redis: %v", conf.Store) |
|||
rdb = redis.NewClient(&redis.Options{ |
|||
Addr: fmt.Sprintf("%s:%d", conf.Store.Host, conf.Store.Port), |
|||
Username: conf.Store.User, |
|||
Password: conf.Store.Password, |
|||
}) |
|||
}) |
|||
return rdb |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
package registry |
|||
|
|||
import ( |
|||
"sync" |
|||
|
|||
"github.com/dtm-labs/dtm/dtmsvr/storage" |
|||
) |
|||
|
|||
// SingletonFactory is the factory to build store in SINGLETON pattern.
|
|||
type SingletonFactory struct { |
|||
once sync.Once |
|||
|
|||
store storage.Store |
|||
|
|||
creatorFunction func() storage.Store |
|||
} |
|||
|
|||
// GetStorage implement the StorageFactory.GetStorage
|
|||
func (f *SingletonFactory) GetStorage() storage.Store { |
|||
f.once.Do(func() { |
|||
f.store = f.creatorFunction() |
|||
}) |
|||
|
|||
return f.store |
|||
} |
|||
@ -1,140 +0,0 @@ |
|||
package storage |
|||
|
|||
import ( |
|||
"fmt" |
|||
"math" |
|||
"time" |
|||
|
|||
"github.com/google/uuid" |
|||
"github.com/yedf/dtm/common" |
|||
"github.com/yedf/dtm/dtmcli/dtmimp" |
|||
"gorm.io/gorm" |
|||
"gorm.io/gorm/clause" |
|||
) |
|||
|
|||
type SqlStore struct { |
|||
} |
|||
|
|||
func (s *SqlStore) Ping() error { |
|||
db, err := dtmimp.StandaloneDB(config.Store.GetDBConf()) |
|||
dtmimp.E2P(err) |
|||
_, err = db.Exec("select 1") |
|||
return err |
|||
} |
|||
|
|||
func (s *SqlStore) PopulateData(skipDrop bool) { |
|||
file := fmt.Sprintf("%s/dtmsvr.storage.%s.sql", common.GetSqlDir(), config.Store.Driver) |
|||
common.RunSQLScript(config.Store.GetDBConf(), file, skipDrop) |
|||
} |
|||
|
|||
func (s *SqlStore) FindTransGlobalStore(gid string) *TransGlobalStore { |
|||
trans := &TransGlobalStore{} |
|||
dbr := dbGet().Model(trans).Where("gid=?", gid).First(trans) |
|||
if dbr.Error == gorm.ErrRecordNotFound { |
|||
return nil |
|||
} |
|||
dtmimp.E2P(dbr.Error) |
|||
return trans |
|||
} |
|||
|
|||
func (s *SqlStore) ScanTransGlobalStores(position *string, limit int64) []TransGlobalStore { |
|||
globals := []TransGlobalStore{} |
|||
lid := math.MaxInt64 |
|||
if *position != "" { |
|||
lid = dtmimp.MustAtoi(*position) |
|||
} |
|||
dbr := dbGet().Must().Where("id < ?", lid).Order("id desc").Limit(int(limit)).Find(&globals) |
|||
if dbr.RowsAffected < limit { |
|||
*position = "" |
|||
} else { |
|||
*position = fmt.Sprintf("%d", globals[len(globals)-1].ID) |
|||
} |
|||
return globals |
|||
} |
|||
|
|||
func (s *SqlStore) FindBranches(gid string) []TransBranchStore { |
|||
branches := []TransBranchStore{} |
|||
dbGet().Must().Where("gid=?", gid).Order("id asc").Find(&branches) |
|||
return branches |
|||
} |
|||
|
|||
func (s *SqlStore) UpdateBranchesSql(branches []TransBranchStore, updates []string) *gorm.DB { |
|||
return dbGet().Clauses(clause.OnConflict{ |
|||
OnConstraint: "trans_branch_op_pkey", |
|||
DoUpdates: clause.AssignmentColumns(updates), |
|||
}).Create(branches) |
|||
} |
|||
|
|||
func (s *SqlStore) LockGlobalSaveBranches(gid string, status string, branches []TransBranchStore, branchStart int) { |
|||
err := dbGet().Transaction(func(tx *gorm.DB) error { |
|||
g := &TransGlobalStore{} |
|||
dbr := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Model(g).Where("gid=? and status=?", gid, status).First(g) |
|||
if dbr.Error == nil { |
|||
dbr = tx.Save(branches) |
|||
} |
|||
return wrapError(dbr.Error) |
|||
}) |
|||
dtmimp.E2P(err) |
|||
} |
|||
|
|||
func (s *SqlStore) MaySaveNewTrans(global *TransGlobalStore, branches []TransBranchStore) error { |
|||
return dbGet().Transaction(func(db1 *gorm.DB) error { |
|||
db := &common.DB{DB: db1} |
|||
dbr := db.Must().Clauses(clause.OnConflict{ |
|||
DoNothing: true, |
|||
}).Create(global) |
|||
if dbr.RowsAffected <= 0 { // 如果这个不是新事务,返回错误
|
|||
return ErrUniqueConflict |
|||
} |
|||
if len(branches) > 0 { |
|||
db.Must().Clauses(clause.OnConflict{ |
|||
DoNothing: true, |
|||
}).Create(&branches) |
|||
} |
|||
return nil |
|||
}) |
|||
} |
|||
|
|||
func (s *SqlStore) ChangeGlobalStatus(global *TransGlobalStore, newStatus string, updates []string, finished bool) { |
|||
old := global.Status |
|||
global.Status = newStatus |
|||
dbr := dbGet().Must().Model(global).Where("status=? and gid=?", old, global.Gid).Select(updates).Updates(global) |
|||
if dbr.RowsAffected == 0 { |
|||
dtmimp.E2P(ErrNotFound) |
|||
} |
|||
} |
|||
|
|||
func (s *SqlStore) TouchCronTime(global *TransGlobalStore, nextCronInterval int64) { |
|||
global.NextCronTime = common.GetNextTime(nextCronInterval) |
|||
global.UpdateTime = common.GetNextTime(0) |
|||
global.NextCronInterval = nextCronInterval |
|||
dbGet().Must().Model(global).Where("status=? and gid=?", global.Status, global.Gid). |
|||
Select([]string{"next_cron_time", "update_time", "next_cron_interval"}).Updates(global) |
|||
} |
|||
|
|||
func (s *SqlStore) LockOneGlobalTrans(expireIn time.Duration) *TransGlobalStore { |
|||
db := dbGet() |
|||
getTime := func(second int) string { |
|||
return map[string]string{ |
|||
"mysql": fmt.Sprintf("date_add(now(), interval %d second)", second), |
|||
"postgres": fmt.Sprintf("current_timestamp + interval '%d second'", second), |
|||
}[config.Store.Driver] |
|||
} |
|||
expire := int(expireIn / time.Second) |
|||
whereTime := fmt.Sprintf("next_cron_time < %s", getTime(expire)) |
|||
owner := uuid.NewString() |
|||
global := &TransGlobalStore{} |
|||
dbr := db.Must().Model(global). |
|||
Where(whereTime + "and status in ('prepared', 'aborting', 'submitted')"). |
|||
Limit(1). |
|||
Select([]string{"owner", "next_cron_time"}). |
|||
Updates(&TransGlobalStore{ |
|||
Owner: owner, |
|||
NextCronTime: common.GetNextTime(common.Config.RetryInterval), |
|||
}) |
|||
if dbr.RowsAffected == 0 { |
|||
return nil |
|||
} |
|||
dbr = db.Must().Where("owner=?", owner).First(global) |
|||
return global |
|||
} |
|||
@ -0,0 +1,178 @@ |
|||
package sql |
|||
|
|||
import ( |
|||
"fmt" |
|||
"math" |
|||
"time" |
|||
|
|||
"github.com/lithammer/shortuuid/v3" |
|||
"gorm.io/gorm" |
|||
"gorm.io/gorm/clause" |
|||
|
|||
"github.com/dtm-labs/dtm/dtmcli/dtmimp" |
|||
"github.com/dtm-labs/dtm/dtmsvr/config" |
|||
"github.com/dtm-labs/dtm/dtmsvr/storage" |
|||
"github.com/dtm-labs/dtm/dtmutil" |
|||
) |
|||
|
|||
var conf = &config.Config |
|||
|
|||
// Store implements storage.Store, and storage with db
|
|||
type Store struct { |
|||
} |
|||
|
|||
// Ping execs ping cmd to db
|
|||
func (s *Store) Ping() error { |
|||
db, err := dtmimp.StandaloneDB(conf.Store.GetDBConf()) |
|||
dtmimp.E2P(err) |
|||
_, err = db.Exec("select 1") |
|||
return err |
|||
} |
|||
|
|||
// PopulateData populates data to db
|
|||
func (s *Store) PopulateData(skipDrop bool) { |
|||
file := fmt.Sprintf("%s/dtmsvr.storage.%s.sql", dtmutil.GetSQLDir(), conf.Store.Driver) |
|||
dtmutil.RunSQLScript(conf.Store.GetDBConf(), file, skipDrop) |
|||
} |
|||
|
|||
// FindTransGlobalStore finds GlobalTrans data by gid
|
|||
func (s *Store) FindTransGlobalStore(gid string) *storage.TransGlobalStore { |
|||
trans := &storage.TransGlobalStore{} |
|||
dbr := dbGet().Model(trans).Where("gid=?", gid).First(trans) |
|||
if dbr.Error == gorm.ErrRecordNotFound { |
|||
return nil |
|||
} |
|||
dtmimp.E2P(dbr.Error) |
|||
return trans |
|||
} |
|||
|
|||
// ScanTransGlobalStores lists GlobalTrans data
|
|||
func (s *Store) ScanTransGlobalStores(position *string, limit int64) []storage.TransGlobalStore { |
|||
globals := []storage.TransGlobalStore{} |
|||
lid := math.MaxInt64 |
|||
if *position != "" { |
|||
lid = dtmimp.MustAtoi(*position) |
|||
} |
|||
dbr := dbGet().Must().Where("id < ?", lid).Order("id desc").Limit(int(limit)).Find(&globals) |
|||
if dbr.RowsAffected < limit { |
|||
*position = "" |
|||
} else { |
|||
*position = fmt.Sprintf("%d", globals[len(globals)-1].ID) |
|||
} |
|||
return globals |
|||
} |
|||
|
|||
// FindBranches finds Branch data by gid
|
|||
func (s *Store) FindBranches(gid string) []storage.TransBranchStore { |
|||
branches := []storage.TransBranchStore{} |
|||
dbGet().Must().Where("gid=?", gid).Order("id asc").Find(&branches) |
|||
return branches |
|||
} |
|||
|
|||
// UpdateBranches update branches info
|
|||
func (s *Store) UpdateBranches(branches []storage.TransBranchStore, updates []string) (int, error) { |
|||
db := dbGet().Clauses(clause.OnConflict{ |
|||
OnConstraint: "trans_branch_op_pkey", |
|||
DoUpdates: clause.AssignmentColumns(updates), |
|||
}).Create(branches) |
|||
return int(db.RowsAffected), db.Error |
|||
} |
|||
|
|||
// LockGlobalSaveBranches creates branches
|
|||
func (s *Store) LockGlobalSaveBranches(gid string, status string, branches []storage.TransBranchStore, branchStart int) { |
|||
err := dbGet().Transaction(func(tx *gorm.DB) error { |
|||
g := &storage.TransGlobalStore{} |
|||
dbr := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Model(g).Where("gid=? and status=?", gid, status).First(g) |
|||
if dbr.Error == nil { |
|||
dbr = tx.Save(branches) |
|||
} |
|||
return wrapError(dbr.Error) |
|||
}) |
|||
dtmimp.E2P(err) |
|||
} |
|||
|
|||
// MaySaveNewTrans creates a new trans
|
|||
func (s *Store) MaySaveNewTrans(global *storage.TransGlobalStore, branches []storage.TransBranchStore) error { |
|||
return dbGet().Transaction(func(db1 *gorm.DB) error { |
|||
db := &dtmutil.DB{DB: db1} |
|||
dbr := db.Must().Clauses(clause.OnConflict{ |
|||
DoNothing: true, |
|||
}).Create(global) |
|||
if dbr.RowsAffected <= 0 { // 如果这个不是新事务,返回错误
|
|||
return storage.ErrUniqueConflict |
|||
} |
|||
if len(branches) > 0 { |
|||
db.Must().Clauses(clause.OnConflict{ |
|||
DoNothing: true, |
|||
}).Create(&branches) |
|||
} |
|||
return nil |
|||
}) |
|||
} |
|||
|
|||
// ChangeGlobalStatus changes global trans status
|
|||
func (s *Store) ChangeGlobalStatus(global *storage.TransGlobalStore, newStatus string, updates []string, finished bool) { |
|||
old := global.Status |
|||
global.Status = newStatus |
|||
dbr := dbGet().Must().Model(global).Where("status=? and gid=?", old, global.Gid).Select(updates).Updates(global) |
|||
if dbr.RowsAffected == 0 { |
|||
dtmimp.E2P(storage.ErrNotFound) |
|||
} |
|||
} |
|||
|
|||
// TouchCronTime updates cronTime
|
|||
func (s *Store) TouchCronTime(global *storage.TransGlobalStore, nextCronInterval int64) { |
|||
global.NextCronTime = dtmutil.GetNextTime(nextCronInterval) |
|||
global.UpdateTime = dtmutil.GetNextTime(0) |
|||
global.NextCronInterval = nextCronInterval |
|||
dbGet().Must().Model(global).Where("status=? and gid=?", global.Status, global.Gid). |
|||
Select([]string{"next_cron_time", "update_time", "next_cron_interval"}).Updates(global) |
|||
} |
|||
|
|||
// LockOneGlobalTrans finds GlobalTrans
|
|||
func (s *Store) LockOneGlobalTrans(expireIn time.Duration) *storage.TransGlobalStore { |
|||
db := dbGet() |
|||
getTime := func(second int) string { |
|||
return map[string]string{ |
|||
"mysql": fmt.Sprintf("date_add(now(), interval %d second)", second), |
|||
"postgres": fmt.Sprintf("current_timestamp + interval '%d second'", second), |
|||
}[conf.Store.Driver] |
|||
} |
|||
expire := int(expireIn / time.Second) |
|||
whereTime := fmt.Sprintf("next_cron_time < %s", getTime(expire)) |
|||
owner := shortuuid.New() |
|||
global := &storage.TransGlobalStore{} |
|||
dbr := db.Must().Model(global). |
|||
Where(whereTime + "and status in ('prepared', 'aborting', 'submitted')"). |
|||
Limit(1). |
|||
Select([]string{"owner", "next_cron_time"}). |
|||
Updates(&storage.TransGlobalStore{ |
|||
Owner: owner, |
|||
NextCronTime: dtmutil.GetNextTime(conf.RetryInterval), |
|||
}) |
|||
if dbr.RowsAffected == 0 { |
|||
return nil |
|||
} |
|||
db.Must().Where("owner=?", owner).First(global) |
|||
return global |
|||
} |
|||
|
|||
// SetDBConn sets db conn pool
|
|||
func SetDBConn(db *gorm.DB) { |
|||
sqldb, _ := db.DB() |
|||
sqldb.SetMaxOpenConns(int(conf.Store.MaxOpenConns)) |
|||
sqldb.SetMaxIdleConns(int(conf.Store.MaxIdleConns)) |
|||
sqldb.SetConnMaxLifetime(time.Duration(conf.Store.ConnMaxLifeTime) * time.Minute) |
|||
} |
|||
|
|||
func dbGet() *dtmutil.DB { |
|||
return dtmutil.DbGet(conf.Store.GetDBConf(), SetDBConn) |
|||
} |
|||
|
|||
func wrapError(err error) error { |
|||
if err == gorm.ErrRecordNotFound { |
|||
return storage.ErrNotFound |
|||
} |
|||
dtmimp.E2P(err) |
|||
return err |
|||
} |
|||
@ -1,16 +0,0 @@ |
|||
package storage |
|||
|
|||
import ( |
|||
"github.com/go-redis/redis/v8" |
|||
"github.com/yedf/dtm/common" |
|||
) |
|||
|
|||
var config = &common.Config |
|||
|
|||
func dbGet() *common.DB { |
|||
return common.DbGet(config.Store.GetDBConf()) |
|||
} |
|||
|
|||
func redisGet() *redis.Client { |
|||
return common.RedisGet() |
|||
} |
|||
@ -1,7 +0,0 @@ |
|||
package dtmsvr |
|||
|
|||
import ( |
|||
_ "github.com/ychensha/dtmdriver-polaris" |
|||
_ "github.com/yedf/dtmdriver-gozero" |
|||
_ "github.com/yedf/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" |
|||
) |
|||
@ -0,0 +1,157 @@ |
|||
/* |
|||
* 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 |
|||
|
|||
import ( |
|||
"bytes" |
|||
"encoding/json" |
|||
"errors" |
|||
"io/ioutil" |
|||
"net/http" |
|||
"os" |
|||
"path/filepath" |
|||
"strings" |
|||
"time" |
|||
|
|||
"github.com/gin-gonic/gin" |
|||
"github.com/go-resty/resty/v2" |
|||
|
|||
"github.com/dtm-labs/dtm/dtmcli" |
|||
"github.com/dtm-labs/dtm/dtmcli/dtmimp" |
|||
"github.com/dtm-labs/dtm/dtmcli/logger" |
|||
) |
|||
|
|||
// GetGinApp init and return gin
|
|||
func GetGinApp() *gin.Engine { |
|||
gin.SetMode(gin.ReleaseMode) |
|||
app := gin.New() |
|||
app.Use(gin.Recovery()) |
|||
app.Use(func(c *gin.Context) { |
|||
body := "" |
|||
if c.Request.Body != nil { |
|||
rb, err := c.GetRawData() |
|||
dtmimp.E2P(err) |
|||
if len(rb) > 0 { |
|||
body = string(rb) |
|||
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(rb)) |
|||
} |
|||
} |
|||
logger.Debugf("begin %s %s body: %s", c.Request.Method, c.Request.URL, body) |
|||
c.Next() |
|||
}) |
|||
app.Any("/api/ping", func(c *gin.Context) { c.JSON(200, map[string]interface{}{"msg": "pong"}) }) |
|||
return app |
|||
} |
|||
|
|||
// WrapHandler2 wrap a function te bo the handler of gin request
|
|||
func WrapHandler2(fn func(*gin.Context) interface{}) gin.HandlerFunc { |
|||
return func(c *gin.Context) { |
|||
began := time.Now() |
|||
var err error |
|||
r := func() interface{} { |
|||
defer dtmimp.P2E(&err) |
|||
return fn(c) |
|||
}() |
|||
|
|||
status := http.StatusOK |
|||
|
|||
// in dtm test/busi, there are some functions, which will return a resty response
|
|||
// pass resty response as gin's response
|
|||
if resp, ok := r.(*resty.Response); ok { |
|||
b := resp.Body() |
|||
status = resp.StatusCode() |
|||
r = nil |
|||
err = json.Unmarshal(b, &r) |
|||
} |
|||
|
|||
// error maybe returned in r, assign it to err
|
|||
if ne, ok := r.(error); ok && err == nil { |
|||
err = ne |
|||
} |
|||
|
|||
// if err != nil || r == nil. then set the status and dtm_result
|
|||
// dtm_result is for compatible with version lower than v1.10
|
|||
// when >= v1.10, result test should base on status, not dtm_result.
|
|||
result := map[string]interface{}{} |
|||
if err != nil { |
|||
if errors.Is(err, dtmcli.ErrFailure) { |
|||
status = http.StatusConflict |
|||
result["dtm_result"] = dtmcli.ResultFailure |
|||
} else if errors.Is(err, dtmcli.ErrOngoing) { |
|||
status = http.StatusTooEarly |
|||
result["dtm_result"] = dtmcli.ResultOngoing |
|||
} else if err != nil { |
|||
status = http.StatusInternalServerError |
|||
} |
|||
result["message"] = err.Error() |
|||
r = result |
|||
} else if r == nil { |
|||
result["dtm_result"] = dtmcli.ResultSuccess |
|||
r = result |
|||
} |
|||
|
|||
b, _ := json.Marshal(r) |
|||
cont := string(b) |
|||
if status == http.StatusOK || status == http.StatusTooEarly { |
|||
logger.Infof("%2dms %d %s %s %s", time.Since(began).Milliseconds(), status, c.Request.Method, c.Request.RequestURI, cont) |
|||
} else { |
|||
logger.Errorf("%2dms %d %s %s %s", time.Since(began).Milliseconds(), status, c.Request.Method, c.Request.RequestURI, cont) |
|||
} |
|||
c.JSON(status, r) |
|||
} |
|||
} |
|||
|
|||
// MustGetwd must version of os.Getwd
|
|||
func MustGetwd() string { |
|||
wd, err := os.Getwd() |
|||
dtmimp.E2P(err) |
|||
return wd |
|||
} |
|||
|
|||
// GetSQLDir 获取调用该函数的caller源代码的目录,主要用于测试时,查找相关文件
|
|||
func GetSQLDir() string { |
|||
wd := MustGetwd() |
|||
if filepath.Base(wd) == "test" { |
|||
wd = filepath.Dir(wd) |
|||
} |
|||
return wd + "/sqls" |
|||
} |
|||
|
|||
// RecoverPanic execs recovery operation
|
|||
func RecoverPanic(err *error) { |
|||
if x := recover(); x != nil { |
|||
e := dtmimp.AsError(x) |
|||
if err != nil { |
|||
*err = e |
|||
} |
|||
} |
|||
} |
|||
|
|||
// GetNextTime gets next time from second
|
|||
func GetNextTime(second int64) *time.Time { |
|||
next := time.Now().Add(time.Duration(second) * time.Second) |
|||
return &next |
|||
} |
|||
|
|||
// RunSQLScript 1
|
|||
func RunSQLScript(conf dtmcli.DBConf, script string, skipDrop bool) { |
|||
con, err := dtmimp.StandaloneDB(conf) |
|||
logger.FatalIfError(err) |
|||
defer func() { _ = con.Close() }() |
|||
content, err := ioutil.ReadFile(script) |
|||
logger.FatalIfError(err) |
|||
sqls := strings.Split(string(content), ";") |
|||
for _, sql := range sqls { |
|||
s := strings.TrimSpace(sql) |
|||
if s == "" || (skipDrop && strings.Contains(s, "drop")) { |
|||
continue |
|||
} |
|||
_, err = dtmimp.DBExec(con, s) |
|||
logger.FatalIfError(err) |
|||
logger.Infof("sql scripts finished: %s", s) |
|||
} |
|||
} |
|||
@ -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,192 +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" |
|||
"errors" |
|||
"fmt" |
|||
"strings" |
|||
"time" |
|||
|
|||
"github.com/gin-gonic/gin" |
|||
"github.com/yedf/dtm/common" |
|||
"github.com/yedf/dtm/dtmcli" |
|||
"github.com/yedf/dtm/dtmcli/dtmimp" |
|||
"gorm.io/driver/mysql" |
|||
"gorm.io/driver/postgres" |
|||
"gorm.io/gorm" |
|||
) |
|||
|
|||
const ( |
|||
// BusiAPI busi api prefix
|
|||
BusiAPI = "/api/busi" |
|||
// BusiPort busi server port
|
|||
BusiPort = 8081 |
|||
// BusiGrpcPort busi server port
|
|||
BusiGrpcPort = 58081 |
|||
) |
|||
|
|||
type setupFunc func(*gin.Engine) |
|||
|
|||
var setupFuncs = map[string]setupFunc{} |
|||
|
|||
// Busi busi service url prefix
|
|||
var Busi string = fmt.Sprintf("http://localhost:%d%s", BusiPort, BusiAPI) |
|||
|
|||
// BaseAppStartup base app startup
|
|||
func BaseAppStartup() *gin.Engine { |
|||
dtmimp.Logf("examples starting") |
|||
app := common.GetGinApp() |
|||
app.Use(func(c *gin.Context) { |
|||
v := MainSwitch.NextResult.Fetch() |
|||
if v != "" { |
|||
c.JSON(200, gin.H{"dtm_result": v}) |
|||
c.Abort() |
|||
return |
|||
} |
|||
c.Next() |
|||
}) |
|||
|
|||
BaseAddRoute(app) |
|||
for k, v := range setupFuncs { |
|||
dtmimp.Logf("initing %s", k) |
|||
v(app) |
|||
} |
|||
dtmimp.Logf("Starting busi at: %d", BusiPort) |
|||
go app.Run(fmt.Sprintf(":%d", BusiPort)) |
|||
|
|||
time.Sleep(100 * time.Millisecond) |
|||
return app |
|||
} |
|||
|
|||
// AutoEmptyString auto reset to empty when used once
|
|||
type AutoEmptyString struct { |
|||
value string |
|||
} |
|||
|
|||
// SetOnce set a value once
|
|||
func (s *AutoEmptyString) SetOnce(v string) { |
|||
s.value = v |
|||
} |
|||
|
|||
// Fetch fetch the stored value, then reset the value to empty
|
|||
func (s *AutoEmptyString) Fetch() string { |
|||
v := s.value |
|||
s.value = "" |
|||
return v |
|||
} |
|||
|
|||
type mainSwitchType struct { |
|||
TransInResult AutoEmptyString |
|||
TransOutResult AutoEmptyString |
|||
TransInConfirmResult AutoEmptyString |
|||
TransOutConfirmResult AutoEmptyString |
|||
TransInRevertResult AutoEmptyString |
|||
TransOutRevertResult AutoEmptyString |
|||
CanSubmitResult AutoEmptyString |
|||
NextResult AutoEmptyString |
|||
} |
|||
|
|||
// MainSwitch controls busi success or fail
|
|||
var MainSwitch mainSwitchType |
|||
|
|||
func handleGeneralBusiness(c *gin.Context, result1 string, result2 string, busi string) (interface{}, error) { |
|||
info := infoFromContext(c) |
|||
res := dtmimp.OrString(result1, result2, dtmcli.ResultSuccess) |
|||
dtmimp.Logf("%s %s result: %s", busi, info.String(), res) |
|||
if res == "ERROR" { |
|||
return nil, errors.New("ERROR from user") |
|||
} |
|||
return map[string]interface{}{"dtm_result": res}, nil |
|||
} |
|||
|
|||
func error2Resp(err error) (interface{}, error) { |
|||
if err != nil { |
|||
s := err.Error() |
|||
if strings.Contains(s, dtmcli.ResultFailure) || strings.Contains(s, dtmcli.ResultOngoing) { |
|||
return gin.H{"dtm_result": s}, nil |
|||
} |
|||
} |
|||
return nil, err |
|||
} |
|||
|
|||
// BaseAddRoute add base route handler
|
|||
func BaseAddRoute(app *gin.Engine) { |
|||
app.POST(BusiAPI+"/TransIn", common.WrapHandler(func(c *gin.Context) (interface{}, error) { |
|||
return handleGeneralBusiness(c, MainSwitch.TransInResult.Fetch(), reqFrom(c).TransInResult, "transIn") |
|||
})) |
|||
app.POST(BusiAPI+"/TransOut", common.WrapHandler(func(c *gin.Context) (interface{}, error) { |
|||
return handleGeneralBusiness(c, MainSwitch.TransOutResult.Fetch(), reqFrom(c).TransOutResult, "TransOut") |
|||
})) |
|||
app.POST(BusiAPI+"/TransInConfirm", common.WrapHandler(func(c *gin.Context) (interface{}, error) { |
|||
return handleGeneralBusiness(c, MainSwitch.TransInConfirmResult.Fetch(), "", "TransInConfirm") |
|||
})) |
|||
app.POST(BusiAPI+"/TransOutConfirm", common.WrapHandler(func(c *gin.Context) (interface{}, error) { |
|||
return handleGeneralBusiness(c, MainSwitch.TransOutConfirmResult.Fetch(), "", "TransOutConfirm") |
|||
})) |
|||
app.POST(BusiAPI+"/TransInRevert", common.WrapHandler(func(c *gin.Context) (interface{}, error) { |
|||
return handleGeneralBusiness(c, MainSwitch.TransInRevertResult.Fetch(), "", "TransInRevert") |
|||
})) |
|||
app.POST(BusiAPI+"/TransOutRevert", common.WrapHandler(func(c *gin.Context) (interface{}, error) { |
|||
return handleGeneralBusiness(c, MainSwitch.TransOutRevertResult.Fetch(), "", "TransOutRevert") |
|||
})) |
|||
app.GET(BusiAPI+"/CanSubmit", common.WrapHandler(func(c *gin.Context) (interface{}, error) { |
|||
dtmimp.Logf("%s CanSubmit", c.Query("gid")) |
|||
return dtmimp.OrString(MainSwitch.CanSubmitResult.Fetch(), dtmcli.ResultSuccess), nil |
|||
})) |
|||
app.POST(BusiAPI+"/TransInXa", common.WrapHandler(func(c *gin.Context) (interface{}, error) { |
|||
err := XaClient.XaLocalTransaction(c.Request.URL.Query(), func(db *sql.DB, xa *dtmcli.Xa) error { |
|||
if reqFrom(c).TransInResult == dtmcli.ResultFailure { |
|||
return dtmcli.ErrFailure |
|||
} |
|||
_, err := dtmimp.DBExec(db, "update dtm_busi.user_account set balance=balance+? where user_id=?", reqFrom(c).Amount, 2) |
|||
return err |
|||
}) |
|||
return error2Resp(err) |
|||
})) |
|||
app.POST(BusiAPI+"/TransOutXa", common.WrapHandler(func(c *gin.Context) (interface{}, error) { |
|||
err := XaClient.XaLocalTransaction(c.Request.URL.Query(), func(db *sql.DB, xa *dtmcli.Xa) error { |
|||
if reqFrom(c).TransOutResult == dtmcli.ResultFailure { |
|||
return dtmcli.ErrFailure |
|||
} |
|||
_, err := dtmimp.DBExec(db, "update dtm_busi.user_account set balance=balance-? where user_id=?", reqFrom(c).Amount, 1) |
|||
return err |
|||
}) |
|||
return error2Resp(err) |
|||
})) |
|||
|
|||
app.POST(BusiAPI+"/TransOutXaGorm", common.WrapHandler(func(c *gin.Context) (interface{}, error) { |
|||
err := XaClient.XaLocalTransaction(c.Request.URL.Query(), func(db *sql.DB, xa *dtmcli.Xa) error { |
|||
if reqFrom(c).TransOutResult == dtmcli.ResultFailure { |
|||
return dtmcli.ErrFailure |
|||
} |
|||
var dia gorm.Dialector = nil |
|||
if dtmcli.GetCurrentDBType() == dtmcli.DBTypeMysql { |
|||
dia = mysql.New(mysql.Config{Conn: db}) |
|||
} else if dtmcli.GetCurrentDBType() == dtmcli.DBTypePostgres { |
|||
dia = postgres.New(postgres.Config{Conn: db}) |
|||
} |
|||
gdb, err := gorm.Open(dia, &gorm.Config{}) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
dbr := gdb.Exec("update dtm_busi.user_account set balance=balance-? where user_id=?", reqFrom(c).Amount, 1) |
|||
return dbr.Error |
|||
}) |
|||
return error2Resp(err) |
|||
})) |
|||
|
|||
app.POST(BusiAPI+"/TestPanic", common.WrapHandler(func(c *gin.Context) (interface{}, error) { |
|||
if c.Query("panic_error") != "" { |
|||
panic(errors.New("panic_error")) |
|||
} else if c.Query("panic_string") != "" { |
|||
panic("panic_string") |
|||
} |
|||
return "SUCCESS", nil |
|||
})) |
|||
} |
|||
@ -1,107 +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" |
|||
"fmt" |
|||
|
|||
"github.com/gin-gonic/gin" |
|||
"github.com/yedf/dtm/common" |
|||
"github.com/yedf/dtm/dtmcli" |
|||
"github.com/yedf/dtm/dtmcli/dtmimp" |
|||
"github.com/yedf/dtm/dtmgrpc" |
|||
) |
|||
|
|||
// DtmHttpServer dtm service address
|
|||
var DtmHttpServer = fmt.Sprintf("http://localhost:%d/api/dtmsvr", 36789) |
|||
|
|||
// DtmGrpcServer dtm grpc service address
|
|||
var DtmGrpcServer = fmt.Sprintf("localhost:%d", 36790) |
|||
|
|||
// TransReq transaction request payload
|
|||
type TransReq struct { |
|||
Amount int `json:"amount"` |
|||
TransInResult string `json:"transInResult"` |
|||
TransOutResult string `json:"transOutResult"` |
|||
} |
|||
|
|||
func (t *TransReq) String() string { |
|||
return fmt.Sprintf("amount: %d transIn: %s transOut: %s", t.Amount, t.TransInResult, t.TransOutResult) |
|||
} |
|||
|
|||
// GenTransReq 1
|
|||
func GenTransReq(amount int, outFailed bool, inFailed bool) *TransReq { |
|||
return &TransReq{ |
|||
Amount: amount, |
|||
TransOutResult: dtmimp.If(outFailed, dtmcli.ResultFailure, "").(string), |
|||
TransInResult: dtmimp.If(inFailed, dtmcli.ResultFailure, "").(string), |
|||
} |
|||
} |
|||
|
|||
// GenBusiReq 1
|
|||
func GenBusiReq(amount int, outFailed bool, inFailed bool) *BusiReq { |
|||
return &BusiReq{ |
|||
Amount: int64(amount), |
|||
TransOutResult: dtmimp.If(outFailed, dtmcli.ResultFailure, "").(string), |
|||
TransInResult: dtmimp.If(inFailed, dtmcli.ResultFailure, "").(string), |
|||
} |
|||
} |
|||
|
|||
func reqFrom(c *gin.Context) *TransReq { |
|||
v, ok := c.Get("trans_req") |
|||
if !ok { |
|||
req := TransReq{} |
|||
err := c.BindJSON(&req) |
|||
dtmimp.FatalIfError(err) |
|||
c.Set("trans_req", &req) |
|||
v = &req |
|||
} |
|||
return v.(*TransReq) |
|||
} |
|||
|
|||
func infoFromContext(c *gin.Context) *dtmcli.BranchBarrier { |
|||
info := dtmcli.BranchBarrier{ |
|||
TransType: c.Query("trans_type"), |
|||
Gid: c.Query("gid"), |
|||
BranchID: c.Query("branch_id"), |
|||
Op: c.Query("op"), |
|||
} |
|||
return &info |
|||
} |
|||
|
|||
func dbGet() *common.DB { |
|||
return common.DbGet(config.ExamplesDB) |
|||
} |
|||
|
|||
func sdbGet() *sql.DB { |
|||
db, err := dtmimp.PooledDB(config.ExamplesDB) |
|||
dtmimp.FatalIfError(err) |
|||
return db |
|||
} |
|||
|
|||
func txGet() *sql.Tx { |
|||
db := sdbGet() |
|||
tx, err := db.Begin() |
|||
dtmimp.FatalIfError(err) |
|||
return tx |
|||
} |
|||
|
|||
// MustBarrierFromGin 1
|
|||
func MustBarrierFromGin(c *gin.Context) *dtmcli.BranchBarrier { |
|||
ti, err := dtmcli.BarrierFromQuery(c.Request.URL.Query()) |
|||
dtmimp.FatalIfError(err) |
|||
return ti |
|||
} |
|||
|
|||
// MustBarrierFromGrpc 1
|
|||
func MustBarrierFromGrpc(ctx context.Context) *dtmcli.BranchBarrier { |
|||
ti, err := dtmgrpc.BarrierFromGrpc(ctx) |
|||
dtmimp.FatalIfError(err) |
|||
return ti |
|||
} |
|||
@ -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/yedf/dtm/common" |
|||
"github.com/yedf/dtm/dtmcli/dtmimp" |
|||
) |
|||
|
|||
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) { |
|||
dtmimp.LogIfFatalf(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/yedf/dtm/dtmcli/dtmimp" |
|||
dtmgrpc "github.com/yedf/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() |
|||
dtmimp.FatalIfError(err) |
|||
return msg.Gid |
|||
}) |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue