Showing preview only (1,096K chars total). Download the full file or copy to clipboard to get everything.
Repository: dtm-labs/dtm
Branch: main
Commit: 18146ee53baf
Files: 239
Total size: 1.0 MB
Directory structure:
gitextract_qlsxhq70/
├── .github/
│ └── workflows/
│ ├── codeql-analysis.yml
│ ├── docker.yml
│ ├── release.yml
│ └── tests.yml
├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── admin/
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── README.md
│ ├── index.html
│ ├── package.json
│ ├── postcss.config.js
│ ├── src/
│ │ ├── App.vue
│ │ ├── api/
│ │ │ └── api_dtm.ts
│ │ ├── assets/
│ │ │ └── css/
│ │ │ └── index.css
│ │ ├── components/
│ │ │ ├── Screenfull/
│ │ │ │ └── index.vue
│ │ │ └── SvgIcon/
│ │ │ └── index.vue
│ │ ├── components.d.ts
│ │ ├── icons/
│ │ │ └── readme.md
│ │ ├── layout/
│ │ │ ├── aside.vue
│ │ │ ├── components/
│ │ │ │ ├── content.vue
│ │ │ │ ├── header.vue
│ │ │ │ └── sidebar.vue
│ │ │ └── index.vue
│ │ ├── main.ts
│ │ ├── permission.ts
│ │ ├── router/
│ │ │ ├── asyncRouter.ts
│ │ │ └── index.ts
│ │ ├── store/
│ │ │ ├── index.ts
│ │ │ └── modules/
│ │ │ └── layout.ts
│ │ ├── type/
│ │ │ ├── index.d.ts
│ │ │ ├── shim.vue.d.ts
│ │ │ └── store/
│ │ │ └── layout.ts
│ │ ├── utils/
│ │ │ ├── request.ts
│ │ │ └── util.ts
│ │ └── views/
│ │ └── Dashboard/
│ │ ├── GlobalTransactions/
│ │ │ ├── AllTransactions.vue
│ │ │ ├── DialogTransactionDetail.vue
│ │ │ └── UnfinishedTransactions.vue
│ │ ├── KVPairs/
│ │ │ ├── Topics.vue
│ │ │ └── _Components/
│ │ │ ├── DialogTopicDetail.vue
│ │ │ └── DialogTopicSubscribe.vue
│ │ └── Nodes/
│ │ └── LivingNodes.vue
│ ├── tailwind.config.js
│ ├── tsconfig.json
│ └── vite.config.ts
├── charts/
│ ├── .helmignore
│ ├── Chart.yaml
│ ├── README.md
│ ├── templates/
│ │ ├── NOTES.txt
│ │ ├── _helpers.tpl
│ │ ├── configmap.yaml
│ │ ├── deployment.yaml
│ │ ├── hpa.yaml
│ │ ├── ingress.yaml
│ │ ├── service.yaml
│ │ └── tests/
│ │ └── test-connection.yaml
│ └── values.yaml
├── client/
│ ├── README.md
│ ├── dtmcli/
│ │ ├── barrier.go
│ │ ├── barrier_mongo.go
│ │ ├── barrier_redis.go
│ │ ├── consts.go
│ │ ├── cover_test.go
│ │ ├── dtmimp/
│ │ │ ├── README-cn.md
│ │ │ ├── README.md
│ │ │ ├── consts.go
│ │ │ ├── db_special.go
│ │ │ ├── db_special_test.go
│ │ │ ├── trans_base.go
│ │ │ ├── trans_xa_base.go
│ │ │ ├── types.go
│ │ │ ├── types_test.go
│ │ │ ├── utils.go
│ │ │ ├── utils_test.go
│ │ │ └── vars.go
│ │ ├── logger/
│ │ │ └── logger.go
│ │ ├── trans_msg.go
│ │ ├── trans_saga.go
│ │ ├── trans_tcc.go
│ │ ├── types.go
│ │ ├── types_test.go
│ │ ├── utils.go
│ │ └── xa.go
│ ├── dtmgrpc/
│ │ ├── barrier.go
│ │ ├── dtmgimp/
│ │ │ ├── README-cn.md
│ │ │ ├── README.md
│ │ │ ├── grpc_clients.go
│ │ │ ├── types.go
│ │ │ └── utils.go
│ │ ├── dtmgpb/
│ │ │ ├── dtmgimp.pb.go
│ │ │ ├── dtmgimp.proto
│ │ │ └── dtmgimp_grpc.pb.go
│ │ ├── msg.go
│ │ ├── options.go
│ │ ├── options_test.go
│ │ ├── saga.go
│ │ ├── tcc.go
│ │ ├── type.go
│ │ ├── type_test.go
│ │ └── xa.go
│ └── workflow/
│ ├── dummyReadCloser.go
│ ├── factory.go
│ ├── imp.go
│ ├── rpc.go
│ ├── server.go
│ ├── utils.go
│ ├── wfpb/
│ │ ├── wf.pb.go
│ │ ├── wf.proto
│ │ └── wf_grpc.pb.go
│ ├── workflow.go
│ └── workflow_test.go
├── conf.sample.yml
├── dtmsvr/
│ ├── api.go
│ ├── api_grpc.go
│ ├── api_http.go
│ ├── api_json_rpc.go
│ ├── config/
│ │ ├── config.go
│ │ ├── config_test.go
│ │ └── config_utils.go
│ ├── cron.go
│ ├── entry/
│ │ └── main.go
│ ├── metrics.go
│ ├── microservices/
│ │ └── drivers.go
│ ├── storage/
│ │ ├── boltdb/
│ │ │ ├── boltdb.go
│ │ │ └── boltdb_test.go
│ │ ├── redis/
│ │ │ └── redis.go
│ │ ├── registry/
│ │ │ ├── factory.go
│ │ │ └── registry.go
│ │ ├── sql/
│ │ │ └── sql.go
│ │ ├── store.go
│ │ └── trans.go
│ ├── svr.go
│ ├── topics.go
│ ├── trans_class.go
│ ├── trans_process.go
│ ├── trans_status.go
│ ├── trans_type_msg.go
│ ├── trans_type_saga.go
│ ├── trans_type_tcc.go
│ ├── trans_type_workflow.go
│ ├── trans_type_xa.go
│ ├── utils.go
│ └── utils_test.go
├── dtmutil/
│ ├── consts.go
│ ├── db.go
│ ├── utils.go
│ └── utils_test.go
├── go.mod
├── go.sum
├── helper/
│ ├── .goreleaser.yml
│ ├── Dockerfile-release
│ ├── README-cn.md
│ ├── README-en.md
│ ├── bench/
│ │ ├── Makefile
│ │ ├── main.go
│ │ ├── prepare.sh
│ │ ├── setup-redis6.sh
│ │ ├── setup.sh
│ │ ├── svr/
│ │ │ └── http.go
│ │ ├── test-boltdb.sh
│ │ ├── test-flash-sales.sh
│ │ ├── test-mysql.sh
│ │ └── test-redis.sh
│ ├── compose.store.yml
│ ├── golint.sh
│ ├── sync-client.sh
│ └── test-cover.sh
├── main.go
├── qs/
│ └── main.go
├── revive.toml
├── sqls/
│ ├── busi.mongo.js
│ ├── busi.mysql.sql
│ ├── busi.postgres.sql
│ ├── dtmcli.barrier.mongo.js
│ ├── dtmcli.barrier.mysql.sql
│ ├── dtmcli.barrier.postgres.sql
│ ├── dtmsvr.storage.mysql.sql
│ ├── dtmsvr.storage.postgres.sql
│ ├── dtmsvr.storage.sqlserver.sql
│ └── dtmsvr.storage.tdsql.sql
└── test/
├── api_test.go
├── base_test.go
├── busi/
│ ├── barrier.go
│ ├── base_grpc.go
│ ├── base_http.go
│ ├── base_jrpc.go
│ ├── base_types.go
│ ├── busi.pb.go
│ ├── busi.proto
│ ├── busi_grpc.pb.go
│ ├── data.go
│ ├── quick_start.go
│ ├── startup.go
│ └── utils.go
├── common_test.go
├── dtmsvr_test.go
├── main_test.go
├── msg_barrier_mongo_test.go
├── msg_barrier_redis_test.go
├── msg_barrier_test.go
├── msg_delay_test.go
├── msg_grpc_barrier_redis_test.go
├── msg_grpc_barrier_test.go
├── msg_grpc_test.go
├── msg_jrpc_test.go
├── msg_options_test.go
├── msg_test.go
├── msg_webhook_test.go
├── saga_barrier_mongo_test.go
├── saga_barrier_redis_test.go
├── saga_barrier_test.go
├── saga_compatible_test.go
├── saga_concurrent_test.go
├── saga_grpc_barrier_test.go
├── saga_grpc_test.go
├── saga_options_test.go
├── saga_test.go
├── store_test.go
├── tcc_barrier_test.go
├── tcc_cover_test.go
├── tcc_grpc_cover_test.go
├── tcc_grpc_test.go
├── tcc_jrpc_test.go
├── tcc_old_test.go
├── tcc_test.go
├── topic_test.go
├── types.go
├── workflow_base_test.go
├── workflow_grpc_test.go
├── workflow_http_ret_test.go
├── workflow_http_test.go
├── workflow_interceptor_test.go
├── workflow_ongoing_test.go
├── workflow_xa_test.go
├── xa_cover_test.go
├── xa_grpc_test.go
└── xa_test.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/codeql-analysis.yml
================================================
# 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
================================================
FILE: .github/workflows/docker.yml
================================================
name: Build Docker
on:
push:
tags:
- 'v*.*.*'
jobs:
docker:
name: Build docker
runs-on: ubuntu-latest
steps:
- name: Get Release Version
run: |
export RELEASE_VERSION=${GITHUB_REF#refs/*/}
echo RELEASE_VERSION: ${RELEASE_VERSION}
echo "RELEASE_VERSION=${RELEASE_VERSION}" >> $GITHUB_ENV
- name: Check out code
uses: actions/checkout@v3
- name: Create Docker
id: meta
uses: docker/metadata-action@v3
with:
images: |
yedf/dtm
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: ./helper/Dockerfile-release
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
RELEASE_VERSION=${{ env.RELEASE_VERSION }}
================================================
FILE: .github/workflows/release.yml
================================================
name: Release
on:
push:
tags:
- 'v*.*.*'
jobs:
release:
name: Release on GitHub
runs-on: ubuntu-latest
steps:
- name: Get Release Version
run: |
export RELEASE_VERSION=${GITHUB_REF#refs/*/}
echo RELEASE_VERSION: ${RELEASE_VERSION}
echo "RELEASE_VERSION=${RELEASE_VERSION}" >> $GITHUB_ENV
- name: Check out code
uses: actions/checkout@v3
- name: Validates GO releaser config
uses: docker://goreleaser/goreleaser:v1.7.0
with:
args: check
- name: Create release on GitHub
uses: docker://goreleaser/goreleaser:v1.7.0
with:
args: release -f helper/.goreleaser.yml --rm-dist
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Setup node
uses: actions/setup-node@v3
with:
node-version: 14
- name: Build admin
run: |
cd admin
npm install -g yarn
yarn
VITE_ADMIN_VERSION=${{ env.RELEASE_VERSION }} yarn build
cd ..
- name: Scp admin
env:
host: 'ubuntu@en.dtm.pub'
host2: 'ubuntu@dtm.pub'
dest: '/data/dtm-admin/'
run: |
cd admin
echo "${{secrets.DEPLOY_KEY}}" > deploy_key
chmod 600 ./deploy_key
tar -cvzf dist.tar.gz dist
scp -i deploy_key -o StrictHostKeyChecking=no dist.tar.gz ${{env.host}}:${{env.dest}}
ssh -i deploy_key -o StrictHostKeyChecking=no ${{env.host}} 'cd ${{env.dest}} && tar -zvxf dist.tar.gz'
scp -i deploy_key -o StrictHostKeyChecking=no dist.tar.gz ${{env.host2}}:${{env.dest}}
ssh -i deploy_key -o StrictHostKeyChecking=no ${{env.host2}} 'cd ${{env.dest}} && tar -zvxf dist.tar.gz'
rm deploy_key dist.tar.gz
echo > dist/placeholder
cd ..
================================================
FILE: .github/workflows/tests.yml
================================================
name: Tests
on:
push:
branches-ignore:
- 'tmp-*'
pull_request:
branches-ignore:
- 'tmp-*'
jobs:
tests:
name: CI
runs-on: ubuntu-latest
services:
mysql:
image: 'mysql:8'
env:
MYSQL_ALLOW_EMPTY_PASSWORD: 1
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
ports:
- 3306:3306
redis:
image: 'redis'
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
ports:
- 6379:6379
postgres:
image: 'yedf/postgres-xa'
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
env:
POSTGRES_PASSWORD: mysecretpassword
POSTGRES_DB: dtm
ports:
- '5432:5432'
mongo:
image: 'yedf/mongo-rs'
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
ports:
- 27017:27017
sqlserver:
image: mcr.microsoft.com/mssql/server:2019-latest
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
env:
ACCEPT_EULA: Y
MSSQL_SA_PASSWORD: p@ssw0rd
ports:
- '1433:1433'
steps:
- name: Set up Go 1.23
uses: actions/setup-go@v2
with:
go-version: '1.23.3'
- name: Check out code
uses: actions/checkout@v2
- name: Install dependencies
run: |
go mod download
- name: Run CI lint
run: sh helper/golint.sh
- name: Run test cover
run: sh helper/test-cover.sh
- name: Upload coverage to Codecov
run: bash <(curl -s https://codecov.io/bash)
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
================================================
FILE: .gitignore
================================================
conf.yml
*.out
*.log
# dist
.idea/**
.vscode
default.etcd
*/**/*.bolt
bench/bench
helper/bench/bench
helper/qs/qs
# Output file of unit test coverage
coverage.*
profile.*
test.sh
dtm
dtm-*
dtm.*
cache
================================================
FILE: LICENSE
================================================
BSD 3-Clause License
Copyright (c) 2021, yedf
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: Makefile
================================================
# dev env https://www.dtm.pub/other/develop.html
all: fmt lint test_redis
.PHONY: all
fmt:
@gofmt -s -w ./
lint:
revive -config revive.toml ./...
.PHONY: test
test:
@go test ./...
test_redis:
TEST_STORE=redis go test ./...
test_all:
TEST_STORE=redis go test ./...
TEST_STORE=boltdb go test ./...
TEST_STORE=mysql go test ./...
TEST_STORE=postgres go test ./...
cover_test:
./helper/test-cover.sh
================================================
FILE: README.md
================================================


[](https://codecov.io/gh/dtm-labs/dtm)
[](https://goreportcard.com/report/github.com/dtm-labs/dtm)
[](https://pkg.go.dev/github.com/dtm-labs/dtm)
[](https://github.com/avelino/awesome-go#database)
English | [简体中文](https://github.com/dtm-labs/dtm/blob/main/helper/README-cn.md)
# Distributed Transactions Manager
## What is DTM
DTM is a distributed transaction framework which provides cross-service eventual data consistency. It provides saga, tcc, xa, 2-phase message, outbox, workflow patterns for a variety of application scenarios. It also supports multiple languages and multiple store engine to form up a transaction as following:
<img alt="function-picture" src="https://en.dtm.pub/assets/function.7d5618f8.png" height=250 />
## Who's using DTM (partial)
[Tencent](https://en.dtm.pub/other/using.html#tencent)
[Bytedance](https://en.dtm.pub/other/using.html#bytedance)
[Ivydad](https://en.dtm.pub/other/using.html#ivydad)
[More](https://en.dtm.pub/other/using.html)
## Features
* Support for multiple transaction modes: SAGA, TCC, XA, Workflow, Outbox
* Multiple languages support: SDK for Go, Java, PHP, C#, Python, Nodejs
* Better Outbox: 2-phase messages, a more elegant solution than Outbox, support multi-databases
* Multiple database transaction support: MySQL/MariaDB, Redis, MongoDB, Postgres, TDSQL, etc.
* Support for multiple storage engines: MySQL/MariaDB (common), Redis (high performance), BoltDB (dev&test), MongoDB (under planning)
* Support for multiple microservices architectures: [go-zero](https://github.com/zeromicro/go-zero), go-kratos/kratos, polarismesh/polaris
* Support for high availability and easy horizontal scaling
## Application scenarios.
DTM can be applied to data consistency issues in a large number of scenarios, here are a few common ones
* [cache management](https://en.dtm.pub/app/cache.html): thoroughly guarantee the cache final consistency and strong consistency
* [flash-sales to deduct inventory](https://en.dtm.pub/app/flash.html): in extreme cases, it is also possible to ensure that the precise inventory in Redis is exactly the same as the final order created, without the need for manual adjustment
* [Non-monolithic order system](https://en.dtm.pub/app/order.html): Dramatically simplifies the architecture
* [Event publishing/subscription](https://en.dtm.pub/practice/msg.html): better outbox pattern
## [Cook Book](https://en.dtm.pub)
## Quick start
### run dtm
``` bash
git clone https://github.com/dtm-labs/dtm && cd dtm
go run main.go
```
### Start an example
Suppose we want to perform an inter-bank transfer. The operations of transfer out (TransOut) and transfer in (TransIn) are coded in separate micro-services.
Here is an example to illustrate a solution of dtm to this problem:
``` bash
git clone https://github.com/dtm-labs/quick-start-sample.git && cd quick-start-sample/workflow-grpc
go run main.go
```
## Code
### Usage
``` go
wfName := "workflow-grpc"
err = workflow.Register(wfName, func(wf *workflow.Workflow, data []byte) error {
// ...
// Define a transaction branch for TransOut
wf.NewBranch().OnRollback(func(bb *dtmcli.BranchBarrier) error {
// compensation for TransOut
_, err := busiCli.TransOutRevert(wf.Context, &req)
return err
})
_, err = busiCli.TransOut(wf.Context, &req)
// check error
// Define another transaction branch for TransIn
wf.NewBranch().OnRollback(func(bb *dtmcli.BranchBarrier) error {
_, err := busiCli.TransInRevert(wf.Context, &req)
return err
})
_, err = busiCli.TransIn(wf.Context, &req)
return err
}
// ...
req := busi.BusiReq{Amount: 30, TransInResult: ""}
data, err := proto.Marshal(&req)
// Execute workflow
_, err = workflow.ExecuteCtx(wfName, shortuuid.New(), data)
logger.Infof("result of workflow.Execute is: %v", err)
```
When the above code runs, we can see in the console that services `TransOut`, `TransIn` has been called.
#### Rollback upon failure
If any forward operation fails, DTM invokes the corresponding compensating operation of each sub-transaction to roll back, after which the transaction is successfully rolled back.
Let's purposely trigger the failure of the second sub-transaction and watch what happens
``` go
// req := busi.BusiReq{Amount: 30, TransInResult: ""}
req := busi.BusiReq{Amount: 30, TransInResult: "FAILURE"}
})
```
we can see in the console that services `TransOut`, `TransIn`, `TransOutRevert` has been called
## More examples
If you want more quick start examples, please refer to [dtm-labs/quick-start-sample](https://github.com/dtm-labs/quick-start-sample)
The above example mainly demonstrates the flow of a distributed transaction. More on this, including practical examples of how to interact with an actual database, how to do compensation, how to do rollback, etc. please refer to [dtm-examples](https://github.com/dtm-labs/dtm-examples) for more examples.
## Give a star! ⭐
If you think this project is interesting, or helpful to you, please give a star!
================================================
FILE: admin/.eslintrc.js
================================================
module.exports = {
parser: 'vue-eslint-parser',
env: {
browser: true,
es2021: true
},
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:vue/vue3-recommended'
],
parserOptions: {
parser: '@typescript-eslint/parser',
sourceType: 'module',
ecmaFeature: {
jsx: true,
tsx: true
}
},
plugins: [
'@typescript-eslint'
],
rules: {
'vue/max-attributes-per-line': ['error', {
singleline: 10,
multiline: {
max: 1
}
}],
'vue/multi-word-component-names': 0,
'vue/singleline-html-element-content-newline': 'off',
'vue/multiline-html-element-content-newline': 'off',
'vue/html-indent': ['error', 4],
indent: ['error', 4], // 4行缩进
'vue/script-indent': ['error', 4],
quotes: ['error', 'single'], // 单引号
// 'vue/html-quotes': ['error', 'single'],
semi: ['error', 'never'], // 禁止使用分号
'space-infix-ops': ['error', {
int32Hint: false
}], // 要求操作符周围有空格
'no-multi-spaces': 'error', // 禁止多个空格
'no-whitespace-before-property': 'error', // 禁止在属性前使用空格
'space-before-blocks': 'error', // 在块之前强制保持一致的间距
'space-before-function-paren': ['error', 'never'], // 在“ function”定义打开括号之前强制不加空格
'space-in-parens': ['error', 'never'], // 强制括号左右的不加空格
'spaced-comment': ['error', 'always'], // 注释间隔
'template-tag-spacing': ['error', 'always'], // 在模板标签及其文字之间需要空格
'no-var': 'error',
'prefer-destructuring': ['error', { // 优先使用数组和对象解构
array: true,
object: true
}, {
enforceForRenamedProperties: false
}],
'comma-dangle': ['error', 'never'], // 最后一个属性不允许有逗号
'arrow-spacing': 'error', // 箭头函数空格
'prefer-template': 'error',
'template-curly-spacing': 'error',
'quote-props': ['error', 'as-needed'], // 对象字面量属性名称使用引号
'object-curly-spacing': ['error', 'always'], // 强制在花括号中使用一致的空格
'no-unneeded-ternary': 'error', // 禁止可以表达为更简单结构的三元操作符
'no-restricted-syntax': ['error', 'WithStatement', 'BinaryExpression[operator="in"]'], // 禁止with/in语句
'no-lonely-if': 'error', // 禁止 if 语句作为唯一语句出现在 else 语句块中
'newline-per-chained-call': ['error', {
ignoreChainWithDepth: 2
}], // 要求方法链中每个调用都有一个换行符
// 路径别名设置
'no-submodule-imports': ['off', '/@'],
'no-implicit-dependencies': ['off', ['/@']],
'@typescript-eslint/no-explicit-any': 'off' // 类型可以使用any
}
}
================================================
FILE: admin/.gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
================================================
FILE: admin/README.md
================================================
# DTM-Admin
================================================
FILE: admin/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="<%= PUBLIC_PATH %>/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Dtm</title>
<script type="text/javascript">
window.basePath = '<%= PUBLIC_PATH %>';
window.__assetsPathBuilder = function (importer) {
return window.basePath + "/" + importer;
};
</script>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
================================================
FILE: admin/package.json
================================================
{
"name": "dtm-admin",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build && echo > dist/placeholder",
"preview": "vite preview",
"lint": "eslint --ext .tsx,.ts,vue src/",
"lint:fix": "eslint --ext .tsx,.ts,vue src/ --fix"
},
"dependencies": {
"ant-design-vue": "^3.1.1",
"vue": "^3.2.25",
"vue-demi": "^0.13.11",
"vue-request": "^1.2.4"
},
"devDependencies": {
"@types/node": "^17.0.23",
"@types/nprogress": "^0.2.0",
"@typescript-eslint/eslint-plugin": "^5.18.0",
"@typescript-eslint/parser": "^5.18.0",
"@vitejs/plugin-vue": "^4.0.0",
"autoprefixer": "^10.4.4",
"axios": "^1.7.4",
"eslint": "^8.33.0",
"eslint-plugin-vue": "^8.6.0",
"fast-glob": "^3.2.11",
"nprogress": "^0.2.0",
"pinia": "^2.0.0-rc.10",
"postcss": "^8.4.31",
"postcss-import": "^14.1.0",
"postcss-nested": "^5.0.6",
"postcss-simple-vars": "^6.0.3",
"prettier": "^2.8.3",
"prettier-eslint": "^15.0.1",
"screenfull": "^6.0.1",
"tailwindcss": "^3.0.24",
"typescript": "^4.5.4",
"unplugin-vue-components": "^0.25.1",
"vite": "^3.2.11",
"vite-plugin-ejs": "^1.6.4",
"vite-plugin-svg-icons": "^2.0.1",
"vue-router": "^4.0.13",
"vue-tsc": "^0.29.8"
}
}
================================================
FILE: admin/postcss.config.js
================================================
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {}
}
}
================================================
FILE: admin/src/App.vue
================================================
<template>
<router-view />
</template>
<script setup lang="ts"></script>
================================================
FILE: admin/src/api/api_dtm.ts
================================================
import { AxiosResponse } from 'axios'
import request from '/@/utils/request'
export interface IListAllTransactionsReq {
gid?: string;
limit: number;
position?: string;
}
export interface IListAllKVReq {
cat: string;
limit: number;
position?: string;
}
export function listAllTransactions<T>(
payload: IListAllTransactionsReq
): Promise<AxiosResponse<T>> {
return request({
url: '/api/dtmsvr/all',
method: 'get',
params: payload
})
}
export function forceStopTransaction(gid: string): Promise<AxiosResponse> {
return request({
url: '/api/dtmsvr/forceStop',
method: 'post',
data: { gid }
})
}
export function queryKVPair<T>(payload: {
cat: string;
key: string;
}): Promise<AxiosResponse<T>> {
return request({
url: '/api/dtmsvr/queryKV',
method: 'get',
params: payload
})
}
export function listKVPairs<T>(
payload: IListAllKVReq
): Promise<AxiosResponse<T>> {
return request({
url: '/api/dtmsvr/scanKV',
method: 'get',
params: payload
})
}
export function deleteTopic<T>(topicName: string): Promise<AxiosResponse<T>> {
return request({
url: `/api/dtmsvr/topic/${topicName}`,
method: 'delete'
})
}
export function subscribe<T>(payload: {
topic: string;
url: string;
remark: string;
}): Promise<AxiosResponse<T>> {
return request({
url: '/api/dtmsvr/subscribe',
method: 'get',
params: payload
})
}
export function unsubscribe(payload: {
topic: string;
url: string;
}): Promise<AxiosResponse> {
return request({
url: '/api/dtmsvr/unsubscribe',
method: 'get',
params: payload
})
}
export function getTransaction<T>(payload: {
gid: string;
}): Promise<AxiosResponse<T>> {
return request({
url: '/api/dtmsvr/query',
method: 'get',
params: payload
})
}
export function resetNextCronTime(gid: string): Promise<AxiosResponse> {
return request({
url: '/api/dtmsvr/resetNextCronTime',
method: 'post',
data: { gid }
})
}
export function getDtmVersion(): Promise<AxiosResponse<any>> {
return request({
url: '/api/dtmsvr/version',
method: 'get'
})
}
================================================
FILE: admin/src/assets/css/index.css
================================================
/* @tailwind base; */
@tailwind components;
@tailwind utilities;
================================================
FILE: admin/src/components/Screenfull/index.vue
================================================
<template>
<div class="hidden-xs-only px-2">
<svg-icon v-if="!isFulScreen" class-name="cursor-pointer" icon-class="svg-fullscreen" @click="changeScreenfull(identity)" />
<svg-icon v-else class-name="cursor-pointer" icon-class="svg-exit-fullscreen" @click="changeScreenfull(identity)" />
</div>
</template>
<script setup lang='ts'>
import { notification } from 'ant-design-vue'
import { onMounted, onUnmounted, ref } from 'vue'
import screenfull from 'screenfull'
const isFulScreen = ref(false)
const changeScreenfull = (identity: string) => {
if (!screenfull.isEnabled) {
notification.open({
message: '浏览器不支持全屏',
type: 'warning'
})
} else if (identity) {
const element = document.getElementById(identity)
screenfull.toggle(element as HTMLElement)
} else {
screenfull.toggle()
}
}
const change = () => {
if (screenfull.isEnabled) isFulScreen.value = screenfull.isFullscreen
}
defineProps({
identity: {
type: String,
default: null
}
})
const emits = defineEmits(['screen'])
onMounted(() => screenfull.isEnabled && screenfull.on('change', change) && emits('screen'))
onUnmounted(() => screenfull.isEnabled && screenfull.off('change', change))
</script>
================================================
FILE: admin/src/components/SvgIcon/index.vue
================================================
<template>
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" />
<svg v-else :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName" />
</svg>
</template>
<script setup lang='ts'>
const props = defineProps({
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ''
}
})
const isExternal = /^(https?:|mailto:|tel:)/.test(props.iconClass)
const iconName = `#icon-${props.iconClass}`
const svgClass = props.className ? `svg-icon ${props.className}` : 'svg-icon '
const styleExternalIcon = () => {
return {
mask: `url(${props.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${props.iconClass}) no-repeat 50% 50%`
}
}
</script>
<style lang="postcss" scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
.svg-external-icon {
background-color: currentColor;
mask-size: cover !important;
display: inline-block;
}
</style>
================================================
FILE: admin/src/components.d.ts
================================================
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
export {}
declare module 'vue' {
export interface GlobalComponents {
AAlert: typeof import('ant-design-vue/es')['Alert']
ABreadcrumb: typeof import('ant-design-vue/es')['Breadcrumb']
ABreadcrumbItem: typeof import('ant-design-vue/es')['BreadcrumbItem']
AButton: typeof import('ant-design-vue/es')['Button']
ADescriptions: typeof import('ant-design-vue/es')['Descriptions']
ADescriptionsItem: typeof import('ant-design-vue/es')['DescriptionsItem']
ADivider: typeof import('ant-design-vue/es')['Divider']
AForm: typeof import('ant-design-vue/es')['Form']
AFormItem: typeof import('ant-design-vue/es')['FormItem']
AInput: typeof import('ant-design-vue/es')['Input']
ALayout: typeof import('ant-design-vue/es')['Layout']
ALayoutContent: typeof import('ant-design-vue/es')['LayoutContent']
ALayoutHeader: typeof import('ant-design-vue/es')['LayoutHeader']
ALayoutSider: typeof import('ant-design-vue/es')['LayoutSider']
AMenu: typeof import('ant-design-vue/es')['Menu']
AMenuItem: typeof import('ant-design-vue/es')['MenuItem']
AModal: typeof import('ant-design-vue/es')['Modal']
APopconfirm: typeof import('ant-design-vue/es')['Popconfirm']
ARangePicker: typeof import('ant-design-vue/es')['RangePicker']
ASelect: typeof import('ant-design-vue/es')['Select']
ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
ASubMenu: typeof import('ant-design-vue/es')['SubMenu']
ATable: typeof import('ant-design-vue/es')['Table']
ATag: typeof import('ant-design-vue/es')['Tag']
ATextarea: typeof import('ant-design-vue/es')['Textarea']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
Screenfull: typeof import('./components/Screenfull/index.vue')['default']
SvgIcon: typeof import('./components/SvgIcon/index.vue')['default']
}
}
================================================
FILE: admin/src/icons/readme.md
================================================
# ICon Component
================================================
FILE: admin/src/layout/aside.vue
================================================
<template>
<a-layout>
<a-layout-sider width="200" style="background: #fff">
<Sidebar />
</a-layout-sider>
<a-layout style="padding: 0 24px 24px">
<div v-if="layout.dtmVersion && layout.dtmVersion != dashVer" style="color:#f00"> !!! admin version: {{ dashVer }} != dtm version: {{ layout.dtmVersion }}. </div>
<a-breadcrumb style="margin: 16px 0">
<a-breadcrumb-item>{{ mainNav }}</a-breadcrumb-item>
<a-breadcrumb-item>{{ subNav }}</a-breadcrumb-item>
<a-breadcrumb-item>{{ page }}</a-breadcrumb-item>
</a-breadcrumb>
<a-layout-content
:style="{ background: '#fff', padding: '24px', margin: 0, minHeight: '280px' }"
>
<Content />
</a-layout-content>
</a-layout>
</a-layout>
</template>
<script setup lang='ts'>
import Sidebar from './components/sidebar.vue'
import Content from './components/content.vue'
import { useRoute } from 'vue-router'
import { useLayoutStore } from '../store/modules/layout'
import { findCurrentMenubar } from '../utils/util'
import { computed, onMounted } from 'vue'
const dashVer = import.meta.env.VITE_ADMIN_VERSION
const route = useRoute()
const layout = useLayoutStore()
const mainNav = computed(() => {
const currentMenubar = findCurrentMenubar(layout.getMenubar.menuList, true)
return currentMenubar?.meta.title
})
const subNav = computed(() => {
let subNav = ''
const currentMenubar = findCurrentMenubar(layout.getMenubar.menuList, true)
currentMenubar.children?.forEach(v => {
if (route.path.indexOf(v.path) !== -1) {
subNav = v.meta.title
}
})
return subNav
})
const page = computed(() => {
let page = ''
const currentMenubar = findCurrentMenubar(layout.getMenubar.menuList, true)
currentMenubar.children?.forEach(v => {
v.children?.forEach(vv => {
if (route.path == vv.path) {
page = vv.meta.title
}
})
})
return page
})
onMounted(() => {
layout.loadDtmVersion()
})
</script>
<style lang="postcss" scoped>
.ant-layout.ant-layout-has-sider {
min-height: calc(100vh - 64px);
}
</style>
================================================
FILE: admin/src/layout/components/content.vue
================================================
<template>
<router-view v-slot="{Component}">
<transition name="fade-transform" mode="out-in">
<keep-alive>
<div>
<a-alert
v-if="errLines[0]"
type="error"
closable
@close="onClose"
>
<template #description>
<span v-for="(ln, index) of errLines" :key="index">{{ ln }} <br> </span>
</template>
</a-alert>
<component :is="Component" :key="key" />
</div>
</keep-alive>
</transition>
</router-view>
</template>
<script setup lang='ts'>
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import { sleep } from '/@/utils/util'
import { useLayoutStore } from '/@/store/modules/layout'
const route = useRoute()
const key = computed(() => route.path)
const layoutStore = useLayoutStore()
const errLines = computed(() => layoutStore.globalError.split('\n'))
const onClose = async() => {
await sleep(1000)
layoutStore.setGlobalError('')
}
</script>
================================================
FILE: admin/src/layout/components/header.vue
================================================
<template>
<div>
<a-layout-header class="flex header">
<div class="flex items-center h-16 logo">
<svg-icon style="width: 36px; height: 36px; margin-right: 84px;" icon-class="svg-logo" />
<span class="text-lg text-gray-400">DTM admin {{ version }}</span>
</div>
<a-menu
v-model:selectedKeys="activeMenu"
theme="dark"
mode="horizontal"
:style="{ lineHeight: '64px' }"
@select="onOpenChange"
>
<a-menu-item v-for="v in getMenubar.menuList" :key="v.path">{{ v.meta.title }}</a-menu-item>
</a-menu>
</a-layout-header>
</div>
</template>
<script setup lang='ts'>
import { ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useLayoutStore } from '/@/store/modules/layout'
const route = useRoute()
const router = useRouter()
const { getMenubar } = useLayoutStore()
const firstRedirectPath = '/admin'
const version = import.meta.env.VITE_ADMIN_VERSION
const activeMenu = ref([route.meta.activeMenu !== firstRedirectPath ? route.meta.activeMenu : '/'])
const onOpenChange = (d:any) => {
router.push({ path: d.key })
}
</script>
<style scoped>
.logo {
margin-right: 20px;
}
</style>
================================================
FILE: admin/src/layout/components/sidebar.vue
================================================
<template>
<a-menu
v-model:selectedKeys="activeMenu"
v-model:openKeys="openKeys"
mode="inline"
:style="{ height: '100%', borderRight: 0 }"
@select="onOpenChange"
>
<a-sub-menu v-for="v in filterSubMenubarData" :key="v.path">
<template #title>
<span>
{{ v.meta.title }}
</span>
</template>
<a-menu-item v-for="vv in v.children" :key="vv.path">{{ vv.meta.title }}</a-menu-item>
</a-sub-menu>
</a-menu>
</template>
<script setup lang='ts'>
import { computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useLayoutStore } from '/@/store/modules/layout'
import { IMenubarList } from '/@/type/store/layout'
import { findCurrentMenubar } from '/@/utils/util'
const route = useRoute()
const router = useRouter()
const { getMenubar } = useLayoutStore()
const filterSubMenubarData = computed(() => {
return findCurrentMenubar(getMenubar.menuList) as IMenubarList[]
})
const activeMenu = computed({
get: () => {
return [route.path]
},
// eslint-disable-next-line @typescript-eslint/no-unused-vars
set: (val) => {
// do nothing, just for eliminate warn
}
})
const openKeys = computed({
get: () => {
const pos = route.path.lastIndexOf('/')
return [route.path.substring(0, pos)]
},
// eslint-disable-next-line @typescript-eslint/no-unused-vars
set: (val) => {
// do onthing, just for eliminate warn
}
})
const onOpenChange = (d:any) => {
router.push({ path: d.key })
}
</script>
================================================
FILE: admin/src/layout/index.vue
================================================
<script setup lang="ts">
import Header from './components/header.vue'
</script>
<template>
<a-layout>
<a-layout-header class="header">
<Header />
</a-layout-header>
<router-view />
</a-layout>
</template>
================================================
FILE: admin/src/main.ts
================================================
import { createApp } from 'vue'
import App from './App.vue'
import router from '/@/router/index'
import { pinia } from '/@/store'
import { useLayoutStore } from '/@/store/modules/layout'
import '/@/permission'
import 'ant-design-vue/dist/antd.css'
import '/@/assets/css/index.css'
import 'virtual:svg-icons-register'
const app = createApp(App)
app.use(router)
app.use(pinia)
app.mount('#app')
window.onunhandledrejection = (ev: PromiseRejectionEvent) => {
showAlert(ev.reason.stack || ev.reason.message)
}
window.onerror = err => {
if (typeof err === 'string') {
return showAlert(err)
}
showAlert(JSON.stringify(err))
}
function showAlert(msg: string) {
const layout = useLayoutStore()
if (!layout.globalError) {
layout.setGlobalError(msg)
}
}
================================================
FILE: admin/src/permission.ts
================================================
import router from '/@/router'
import { configure, start, done } from 'nprogress'
import { useLayoutStore } from './store/modules/layout'
configure({ showSpinner: false })
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const defaultRoutePath = '/'
router.beforeEach((to) => {
start()
const { getMenubar, concatAllowRoutes } = useLayoutStore()
if (getMenubar.menuList.length === 0) {
concatAllowRoutes()
return to.fullPath
}
})
router.afterEach(() => {
done()
})
================================================
FILE: admin/src/router/asyncRouter.ts
================================================
const modules = import.meta.glob('../views/**/**.vue')
const components: IObject<() => Promise<typeof import('*.vue')>> = {
LayoutHeader: (() => import('/@/layout/index.vue')) as unknown as () => Promise<typeof import('*.vue')>
}
Object.keys(modules).forEach(key => {
const nameMatch = key.match(/^\.\.\/views\/(.+)\.vue/)
if (!nameMatch) return
if (nameMatch[1].includes('_Components')) return
const indexMatch = nameMatch[1].match(/(.*)\/Index$/i)
let name = indexMatch ? indexMatch[1] : nameMatch[1];
[name] = name.split('/').splice(-1)
components[name] = modules[key] as () => Promise<typeof import('*.vue')>
})
export {
components
}
================================================
FILE: admin/src/router/index.ts
================================================
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import { IMenubarList } from '../type/store/layout'
import { components } from './asyncRouter'
const Components: IObject<() => Promise<typeof import('*.vue')>> =
Object.assign({}, components, {
LayoutHeader: (() =>
import('/@/layout/index.vue')) as unknown as () => Promise<
typeof import('*.vue')
>,
LayoutMain: (() =>
import('/@/layout/aside.vue')) as unknown as () => Promise<
typeof import('*.vue')
>
})
export const allowRouter: Array<IMenubarList> = [
{
name: 'Admin',
path: '/',
redirect: '/admin/global-transactions/all',
component: Components['LayoutHeader'],
meta: { title: 'Admin', activeMenu: '/admin' },
children: [
{
// name: 'Nodes',
// path: '/admin/nodes',
// component: Components['LayoutMain'],
// meta: { title: 'Nodes' },
// children: [
// {
// name: 'LivingNodes',
// path: '/admin/nodes/living',
// component: Components['LivingNodes'],
// meta: { title: 'Living Nodes' },
// }
// ]
// }, {
name: 'GlobalTransactions',
path: '/admin/global-transactions',
component: Components['LayoutMain'],
meta: { title: 'Global Transactions' },
children: [
{
name: 'AllTransactions',
path: '/admin/global-transactions/all',
component: Components['AllTransactions'],
meta: { title: 'All Transactions' }
// }, {
// name: 'UnfinishedTransactions',
// path: '/admin/global-transactions/unfinished',
// component: Components['UnfinishedTransactions'],
// meta: { title: 'Unfinished Transactions' },
},
{
name: 'TransactionDetail',
path: '/admin/global-transactions/detail/:gid',
component: Components['DialogTransactionDetail'],
meta: { title: 'Transaction Detail' }
},
]
},
{
name: 'KVPairs',
path: '/admin/kv',
component: Components['LayoutMain'],
meta: { title: 'Key-Value Pairs' },
children: [
{
name: 'Topics',
path: '/admin/kv/topics',
component: Components['Topics'],
meta: { title: 'Topics' }
}
]
}
]
}
]
const router = createRouter({
history: createWebHistory(window.basePath || undefined),
routes: allowRouter as RouteRecordRaw[]
})
export default router
================================================
FILE: admin/src/store/index.ts
================================================
import { createPinia } from 'pinia'
export const pinia = createPinia()
================================================
FILE: admin/src/store/modules/layout.ts
================================================
import { defineStore } from 'pinia'
import { allowRouter } from '/@/router'
import { ILayout, IMenubar, IMenubarList, IStatus } from '/@/type/store/layout'
import { getDtmVersion } from '/@/api/api_dtm'
export const useLayoutStore = defineStore({
id: 'layout',
state: (): ILayout => ({
menubar: {
menuList: []
},
status: {
isLoading: false
},
dtmVersion: '',
globalError: ''
}),
getters: {
getMenubar(): IMenubar {
return this.menubar
},
getStatus(): IStatus {
return this.status
}
},
actions: {
setRoutes(data: Array<IMenubarList>): void {
this.menubar.menuList = data
},
setGlobalError(err: string) {
this.globalError = err
},
concatAllowRoutes(): void {
allowRouter.reverse().forEach(v => this.menubar.menuList.unshift(v))
},
async loadDtmVersion(): Promise<void> {
const { data: { version } } = await getDtmVersion()
this.dtmVersion = version
console.log('dtm version: ', this.dtmVersion)
}
}
})
================================================
FILE: admin/src/type/index.d.ts
================================================
export { }
declare global {
interface IObject<T> {
[index: string]: T
}
interface ImportMetaEnv {
VITE_APP_TITLE: string
VITE_PORT: number
VITE_PROXY: string
VITE_ADMIN_VERSION: string
}
interface ITable<T = any> {
data: Array<T>
next_position: number,
size: number
}
interface Window {
basePath: string;
}
}
================================================
FILE: admin/src/type/shim.vue.d.ts
================================================
declare module '*.vue' {
import { defineComponent } from 'vue'
const Component: ReturnType<typeof defineComponent>
export default Component
}
================================================
FILE: admin/src/type/store/layout.ts
================================================
export interface IMenubar {
menuList: Array<IMenubarList>
}
export interface ILayout {
menubar: IMenubar
status: IStatus
dtmVersion: string
globalError: string
}
export interface IStatus {
isLoading: boolean
}
export interface IMenubarList {
parentId?: number | string
id?: number | string
name: string
path: string
redirect?: string
meta: {
icon?: string
title: string
permission?: string[]
activeMenu?: string
hidden?: boolean
alwaysShow?: boolean
}
component: (() => Promise<typeof import('*.vue')>) | string
children?: Array<IMenubarList>
}
================================================
FILE: admin/src/utils/request.ts
================================================
import axios from 'axios'
const request = axios.create({
timeout: 60000
})
export default request
================================================
FILE: admin/src/utils/util.ts
================================================
import { useRoute } from 'vue-router'
import { IMenubarList } from '../type/store/layout'
export const findCurrentMenubar = (menuList: IMenubarList[], root?: boolean) => {
const route = useRoute()
let arr: IMenubarList[] | IMenubarList = []
for (let i = 0; i < menuList.length; i++) {
const v = menuList[i]
const usePath = v.meta.activeMenu || v.redirect || v.path
const pos = usePath.lastIndexOf('/')
const rootPath = pos == 0 ? usePath : usePath.substring(0, pos)
if (route.path.indexOf(rootPath) !== -1) {
if (!root) {
arr = v.children as IMenubarList[]
} else {
arr = v
}
break
}
}
return arr
}
export const sleep = async(ms: number) => {
return new Promise(resolve => setTimeout(resolve, ms))
}
================================================
FILE: admin/src/views/Dashboard/GlobalTransactions/AllTransactions.vue
================================================
<template>
<div>
<a-form
layout="inline"
:model="{}"
@finish="searchFinish"
>
<a-form-item>
<a-input v-model:value="gid" placeholder="gid" />
</a-form-item>
<a-form-item>
<a-select
ref="select"
v-model:value="status"
style="width: 200px"
>
<a-select-option value="">-- Status --</a-select-option>
<a-select-option value="prepared">prepared</a-select-option>
<a-select-option value="submitted">submitted</a-select-option>
<a-select-option value="succeed">succeed</a-select-option>
<a-select-option value="failed">failed</a-select-option>
<a-select-option value="aborting">aborting</a-select-option>
</a-select>
</a-form-item>
<a-form-item>
<a-select
ref="select"
v-model:value="transType"
style="width: 200px"
>
<a-select-option value="">-- Trans Type --</a-select-option>
<a-select-option value="workflow">workflow</a-select-option>
<a-select-option value="saga">saga</a-select-option>
<a-select-option value="tcc">tcc</a-select-option>
<a-select-option value="msg">msg</a-select-option>
<a-select-option value="xa">xa</a-select-option>
</a-select>
</a-form-item>
<a-form-item>
<a-range-picker
v-model:value="createTimeRange"
format="YYYY-MM-DD HH:mm:ss"
:placeholder ="['CreateTime Start', 'CreateTime End']"
/>
</a-form-item>
<a-form-item>
<a-button
type="primary"
html-type="submit"
>
Search
</a-button>
</a-form-item>
</a-form>
</div>
<a-divider />
<div>
<a-table :columns="columns" :data-source="dataSource" :loading="loading" :pagination="false" :scroll="{ x: true }" size="small" >
<template #bodyCell="{column, record}">
<template v-if="column.key === 'status'">
<span>
<a-tag
:key="record.status"
:color="record.status === 'succeed' ? 'green' : 'volcano'"
>{{ record.status }}</a-tag>
</span>
</template>
<template v-else-if="column.key === 'action'">
<span style="width: 90px; display: block;">
<a class="mr-2 font-medium" @click="handleTransactionDetail(record.gid)">Dialog</a>
<a class="mr-2 font-medium" target="_blank" :href="'./detail/'+record.gid">Page</a>
</span>
</template>
</template>
</a-table>
<div v-if="canPrev || canNext" class="flex justify-center mt-2 text-lg pager">
<a-button type="text" :disabled="!canPrev" @click="handlePrevPage">Previous</a-button>
<a-button type="text" :disabled="!canNext" @click="handleNextPage">Next</a-button>
</div>
<DialogTransactionDetail ref="transactionDetail" />
</div>
</template>
<script setup lang="ts">
import { IListAllTransactionsReq, listAllTransactions } from '/@/api/api_dtm'
import { computed, ref } from 'vue-demi'
import { usePagination } from 'vue-request'
import DialogTransactionDetail from './DialogTransactionDetail.vue'
const gid = ref('')
const status = ref('')
const transType = ref('')
const createTimeRange = ref()
const searchFinish = function() {
curPage.value = 1
innerSearch('')
}
const innerSearch = function(position: string) {
const params = {
position: position,
gid: gid.value,
status: status.value,
transType: transType.value,
createTimeStart: createTimeRange.value? createTimeRange.value[0].valueOf(): '',
createTimeEnd: createTimeRange.value? createTimeRange.value[1].valueOf(): '',
limit: pageSize.value
}
run(params)
}
const columns = [
{
title: 'Action',
key: 'action'
}, {
title: 'GID',
dataIndex: 'gid',
key: 'gid'
}, {
title: 'TransType',
dataIndex: 'trans_type',
key: 'trans_type'
}, {
title: 'Status',
dataIndex: 'status',
key: 'status'
}, {
title: 'Protocol',
dataIndex: 'protocol',
key: 'protocol'
}, {
title: 'CreateTime',
dataIndex: 'create_time',
key: 'create_time'
},{
title: 'UpdateTime',
dataIndex: 'update_time',
key: 'update_time'
},{
title: 'FinishTime',
dataIndex: 'finish_time',
key: 'finish_time'
},{
title: 'RollbackTime',
dataIndex: 'rollback_time',
key: 'rollback_time'
}, {
title: 'NextCronInterval',
dataIndex: 'next_cron_interval',
key: 'next_cron_interval'
}, {
title: 'NextCronTime',
dataIndex: 'next_cron_time',
key: 'next_cron_time'
},
]
const pages = ref([''])
const curPage = ref(1)
const canPrev = computed(() => {
return curPage.value > 1
})
const canNext = computed(() => {
return data.value?.data.next_position !== ''
})
type Data = {
transactions: {
gid: string
trans_type: string
status: string
protocol: string
create_time: string
}[]
next_position: string
}
const queryData = (params: IListAllTransactionsReq) => {
return listAllTransactions<Data>(params)
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { data, run, current, loading, pageSize } = usePagination(queryData, {
defaultParams: [
{
limit: 10
}
],
pagination: {
pageSizeKey: 'limit'
}
})
const dataSource = computed(() => data.value?.data.transactions || [])
const handlePrevPage = () => {
curPage.value -= 1
let position = pages.value[curPage.value] as string;
innerSearch(position);
}
const handleNextPage = () => {
curPage.value += 1
pages.value[curPage.value] = data.value?.data.next_position as string
let position = data.value?.data.next_position || '';
innerSearch(position);
}
const transactionDetail = ref<null | { open: (gid: string) => null }>(null)
const handleTransactionDetail = (gid: string) => {
transactionDetail.value?.open(gid)
}
</script>
<style lang="postcss" scoped>
::v-deep .ant-pagination-item {
display: none;
}
.pager .ant-btn-text {
font-weight: 500;
}
.pager .ant-btn {
padding: 6px;
}
</style>
================================================
FILE: admin/src/views/Dashboard/GlobalTransactions/DialogTransactionDetail.vue
================================================
<template>
<div>
<a-modal v-model:visible="visible" :closable="closeable" title="Transaction Detail" width="100%" wrap-class-name="full-modal">
<template #footer>
<a-button type="primary" @click="close" v-if="closeable">Close</a-button>
</template>
<h2>Transaction Info</h2>
<a-button type="primary" @click="refresh" :loading="loading" class="action-button">Refresh</a-button>
<a-popconfirm
title="Force stop it?"
ok-text="Yes, stop it"
ok-type="danger"
cancel-text="No"
class="action-button"
:disabled="transaction?.status==='failed' || transaction?.status==='succeed'"
@confirm="handleTransactionStop(<string>transaction?.gid)"
>
<a-button danger type="default" :disabled="transaction?.status==='failed' || transaction?.status==='succeed'"
>ForceStop</a-button>
</a-popconfirm>
<!-- todo enable condition -->
<a-popconfirm
title="Reset next cron time to current time?"
ok-text="Yes, reset"
cancel-text="No"
class="action-button"
@confirm="handleSetNextCronTimeToNow(<string>transaction?.gid)" >
<a-button type="default">Reset next cron time</a-button>
</a-popconfirm>
<a-descriptions bordered size="small" :column="{ xxl: 4, xl: 3, lg: 3, md: 3, sm: 2, xs: 1 }">
<a-descriptions-item label="Status">
<a-tag :color="transaction?.status === 'succeed' ? 'green' : 'volcano'">{{ transaction?.status }}</a-tag>
</a-descriptions-item>
<a-descriptions-item label="Id">{{ transaction?.id }}</a-descriptions-item>
<a-descriptions-item label="GID">{{ transaction?.gid }}</a-descriptions-item>
<a-descriptions-item label="TransType">{{ transaction?.trans_type }}</a-descriptions-item>
<a-descriptions-item label="Protocol">{{ transaction?.protocol }}</a-descriptions-item>
<a-descriptions-item label="CreateTime">{{ transaction?.create_time }}</a-descriptions-item>
<a-descriptions-item label="FinishTime">{{ transaction?.finish_time }}</a-descriptions-item>
<a-descriptions-item label="UpdateTime">{{ transaction?.update_time }}</a-descriptions-item>
<a-descriptions-item label="NextCronInterval">{{ transaction?.next_cron_interval }}</a-descriptions-item>
<a-descriptions-item label="NextCronTime">{{ transaction?.next_cron_time }}</a-descriptions-item>
<a-descriptions-item label="RollbackReason">{{ transaction?.rollback_reason }}</a-descriptions-item>
</a-descriptions>
<h2>Branches</h2>
<a-table :columns="columns" :data-source="dataSource" :pagination="false" :scroll="{ x: true}">
<!-- eslint-disable-next-line vue/no-unused-vars -->
<template #bodyCell="{column, record}" />
</a-table>
<div class="relative mt-10">
<a-textarea id="qs" v-model:value="textVal" :auto-size="{ minRows: 10, maxRows: 10 }" />
<screenfull class="absolute z-50 right-2 top-3" identity="qs" />
</div>
</a-modal>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { getTransaction } from '/@/api/api_dtm'
import screenfull from '/@/components/Screenfull/index.vue'
import { useRoute } from 'vue-router';
import { string } from 'vue-types';
import { forceStopTransaction, resetNextCronTime } from '/@/api/api_dtm'
// import VueJsonPretty from 'vue-json-pretty';
// import 'vue-json-pretty/lib/styles.css'
const route = useRoute();
const loading = ref(false)
const dataSource = ref<Branches[]>([])
const transaction = ref<Transaction>()
const visible = ref(false)
const textVal = ref('')
const closeable = ref(true)
let _gid = <string>route.params.gid;
const open = async(gid: string) => {
_gid = gid;
loading.value = true;
const d = await getTransaction<Data>({ gid: gid })
dataSource.value = d.data.branches
transaction.value = d.data.transaction
textVal.value = JSON.stringify(d.data, null, 2)
visible.value = true
loading.value = false;
}
if(_gid) {
open(<string>route.params.gid);
closeable.value = false;
}
const close = async() => {
visible.value = false;
}
const refresh = async() => {
open(_gid);
}
const columns = [
{
title: 'BranchID',
dataIndex: 'branch_id',
key: 'branch_id'
}, {
title: 'Op',
dataIndex: 'op',
key: 'op'
}, {
title: 'Status',
dataIndex: 'status',
key: 'status'
}, {
title: 'CreateTime',
dataIndex: 'create_time',
key: 'create_time'
}, {
title: 'UpdateTime',
dataIndex: 'update_time',
key: 'update_time'
}, {
title: 'Url',
dataIndex: 'url',
key: 'url'
}
]
const handleTransactionStop = async(gid: string) => {
await forceStopTransaction(gid);
refresh();
}
const handleSetNextCronTimeToNow = async(gid: string) => {
await resetNextCronTime(gid);
refresh();
}
type Data = {
branches: {
gid: string
branch_id: string
op: string
status: string
create_time: string
update_time: string
url: string
}[]
transaction: {
id: number
create_time: string
update_time: string
gid: string
trans_type: string
status: string
protocol: string
finish_time: string
options: string
next_cron_interval: number
next_cron_time: string
concurrent: boolean
rollback_reason: string
}
}
interface Transaction {
id: number
create_time: string
update_time: string
gid: string
trans_type: string
status: string
protocol: string
finish_time: string
options: string
next_cron_interval: number
next_cron_time: string
concurrent: boolean
rollback_reason: string
}
interface Branches {
gid: string
branch_id: string
op: string
status: string
create_time: string
update_time: string
url: string
}
defineExpose({
open
})
</script>
<style lang="postcss">
.full-modal .ant-modal {
max-width: 100%;
top: 0;
padding-bottom: 0;
margin: 0;
}
.full-modal .ant-modal-content {
display: flex;
flex-direction: column;
height: calc(100vh);
}
.full-modal .ant-modal-body {
flex: 1;
}
.ant-modal {
height: 100%;
}
.action-button {
margin-right: 10px;
}
</style>
================================================
FILE: admin/src/views/Dashboard/GlobalTransactions/UnfinishedTransactions.vue
================================================
<template>
<h1>Coming Soon</h1>
</template>
<script setup lang="ts">
</script>
================================================
FILE: admin/src/views/Dashboard/KVPairs/Topics.vue
================================================
<template>
<div>
<a-button type="primary" class="mb-2" @click="handleTopicSubscribe('')">Subscribe</a-button>
<a-table :columns="columns" :data-source="dataSource" :loading="loading" :pagination="false">
<template #bodyCell="{column, record}">
<template v-if="column.key === 'subscribers'">
<span>{{ JSON.parse(record.v).length }}</span>
</template>
<template v-if="column.key === 'action'">
<span>
<a class="mr-2 font-medium" @click="handleTopicSubscribe(record.k)">Subscribe</a>
<a class="mr-2 font-medium" @click="handleTopicDetail(record.k,record.v)">Detail</a>
<a class="font-medium text-red-400" @click="handleDeleteTopic(record.k)">Delete</a>
</span>
</template>
</template>
</a-table>
<div v-if="canPrev || canNext" class="flex justify-center mt-2 text-lg pager">
<a-button type="text" :disabled="!canPrev" @click="handlePrevPage">Previous</a-button>
<a-button type="text" :disabled="!canNext" @click="handleNextPage">Next</a-button>
</div>
<DialogTopicDetail ref="topicDetail" @unsubscribed="handleRefreshData" />
<DialogTopicSubscribe ref="topicSubscribe" @subscribed="handleRefreshData" />
</div>
</template>
<script setup lang="ts">
import DialogTopicDetail from './_Components/DialogTopicDetail.vue'
import DialogTopicSubscribe from './_Components/DialogTopicSubscribe.vue'
import { deleteTopic, IListAllKVReq, listKVPairs } from '/@/api/api_dtm'
import { computed, ref } from 'vue-demi'
import { usePagination } from 'vue-request'
import { message, Modal } from 'ant-design-vue'
const columns = [
{
title: 'Name',
dataIndex: 'k',
key: 'name'
}, {
title: 'Subscribers',
dataIndex: 'v',
key: 'subscribers'
}, {
title: 'Version',
dataIndex: 'version',
key: 'version'
}, {
title: 'Action',
key: 'action'
}
]
const pages = ref([''])
const curPage = ref(1)
const canPrev = computed(() => {
return curPage.value > 1
})
const canNext = computed(() => {
return data.value?.data.next_position !== ''
})
type Data = {
kv: {
k: string
v: string
version: number
}[]
next_position: string
}
const queryData = (params: IListAllKVReq) => {
return listKVPairs<Data>(params)
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { data, run, current, loading, pageSize } = usePagination(queryData, {
defaultParams: [
{
cat: 'topics',
limit: 10
}
],
pagination: {
pageSizeKey: 'limit'
}
})
const dataSource = computed(() => data.value?.data.kv || [])
const handlePrevPage = () => {
curPage.value -= 1
const params = {
cat: 'topics',
limit: pageSize.value,
position: pages.value[curPage.value] as string
}
run(params)
}
const handleNextPage = () => {
curPage.value += 1
pages.value[curPage.value] = data.value?.data.next_position as string
run({
cat: 'topics',
position: data.value?.data.next_position,
limit: pageSize.value
})
}
const handleRefreshData = () => {
run({ cat: 'topics', limit: pageSize.value })
}
const handleDeleteTopic = (topic: string) => {
Modal.confirm({
title: 'Delete',
content: 'Do you want delete this topic? ',
okText: 'Yes',
okType: 'danger',
cancelText: 'Cancel',
onOk: async() => {
await deleteTopic(topic)
message.success('Delete topic succeed')
run({ cat: 'topics', limit: pageSize.value })
}
})
}
const topicDetail = ref<null | { open: (topic: string, subscribers: string) => null }>(null)
const handleTopicDetail = (topic: string, subscribers: string) => {
topicDetail.value?.open(topic, subscribers)
}
const topicSubscribe = ref<null | { open: (topic: string) => null }>(null)
const handleTopicSubscribe = (topic: string) => {
topicSubscribe.value?.open(topic)
}
</script>
<style lang="postcss" scoped>
::deep .ant-pagination-item {
display: none;
}
.pager .ant-btn-text {
font-weight: 500;
}
.pager .ant-btn {
padding: 6px;
}
</style>
================================================
FILE: admin/src/views/Dashboard/KVPairs/_Components/DialogTopicDetail.vue
================================================
<template>
<div>
<a-modal v-model:visible="visible" :title="topicName" width="100%" wrap-class-name="full-modal" :footer="null">
<a-table :columns="columns" :data-source="dataSource" :pagination="false">
<template #bodyCell="{column, record}">
<template v-if="column.key === 'action'">
<span>
<a class="text-red-400 font-medium" @click="handleUnsubscribe(record.url)">Unsubscribe</a>
</span>
</template>
</template>
</a-table>
<!-- <div class="mt-10 relative">
<a-textarea id="qs" v-model:value="textVal" :auto-size="{ minRows: 10, maxRows: 10 }" />
<screenfull class="absolute right-2 top-3 z-50" identity="qs" />
</div> -->
</a-modal>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { unsubscribe } from '/@/api/api_dtm'
import { message, Modal } from 'ant-design-vue'
// import VueJsonPretty from 'vue-json-pretty';
// import 'vue-json-pretty/lib/styles.css'
const dataSource = ref<Subscriber[]>([])
const visible = ref(false)
const topicName = ref<string>('')
const open = async(topic: string, subscribers: string) => {
dataSource.value = JSON.parse(subscribers)
topicName.value = topic
visible.value = true
}
const columns = [
{
title: 'URL',
dataIndex: 'url',
key: 'url'
}, {
title: 'Remark',
dataIndex: 'remark',
key: 'remark'
}, {
title: 'Action',
key: 'action'
}
]
interface Subscriber {
url: string
remark: string
}
const handleUnsubscribe = async(url: string) => {
Modal.confirm({
title: 'Unsubscribe',
content: 'Do you want unsubscribe this topic?',
okText: 'Yes',
okType: 'danger',
cancelText: 'Cancel',
onOk: async() => {
await unsubscribe({
topic: topicName.value,
url: url
})
message.success('Unsubscribe topic succeed')
location.reload()
}
})
}
defineExpose({
open
})
</script>
<style lang="postcss">
.full-modal .ant-modal {
max-width: 100%;
top: 0;
padding-bottom: 0;
margin: 0;
}
.full-modal .ant-modal-content {
display: flex;
flex-direction: column;
height: calc(100vh);
}
.full-modal .ant-modal-body {
flex: 1;
}
</style>
================================================
FILE: admin/src/views/Dashboard/KVPairs/_Components/DialogTopicSubscribe.vue
================================================
<template>
<div>
<a-modal
v-model:visible="visible"
width="60%"
title="Topic Subscribe"
:confirm-loading="confirmLoading"
@ok="handleSubscribe"
>
<a-form v-bind="layout" :mode="form">
<a-form-item label="Topic: ">
<a-input v-model:value="form.topic" placeholder="Please input your topic..." />
</a-form-item>
<a-form-item label="URL: ">
<a-input v-model:value="form.url" placeholder="Please input your url..." />
</a-form-item>
<a-form-item label="Remark">
<a-textarea v-model:value="form.remark" :rows="6" placeholder="Please input your remark..." />
</a-form-item>
</a-form>
</a-modal>
</div>
</template>
<script setup lang="ts">
import { message } from 'ant-design-vue'
import { reactive, ref } from 'vue'
import { subscribe } from '/@/api/api_dtm'
interface formState {
topic: string
url: string
remark: string
}
const layout = {
labelCol: { span: 4 },
wrapperCol: { span: 16 }
}
const form = reactive<formState>({
topic: '',
url: '',
remark: ''
})
const visible = ref(false)
const open = async(topic: string) => {
form.topic = topic
visible.value = true
}
const emit = defineEmits(['subscribed'])
const confirmLoading = ref<boolean>(false)
const handleSubscribe = async() => {
confirmLoading.value = true
await subscribe<string>(form).then(
() => {
visible.value = false
message.success('Subscribe succeed')
confirmLoading.value = false
emit('subscribed')
}
)
.catch(() => {
message.error('Failed')
confirmLoading.value = false
return
})
}
defineExpose({
open
})
</script>
================================================
FILE: admin/src/views/Dashboard/Nodes/LivingNodes.vue
================================================
<template>
<h1>Coming Soon</h1>
</template>
<script setup lang="ts">
</script>
================================================
FILE: admin/tailwind.config.js
================================================
module.exports = {
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
theme: {
extend: {}
},
plugins: []
}
================================================
FILE: admin/tsconfig.json
================================================
{
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"baseUrl": ".",
"paths": {
"/@/*": ["src/*"],
},
"lib": ["esnext", "dom"],
"types": ["vite/client", "node"]
},
"include": ["**/*.ts", "**/*.d.ts", "**/*.tsx", "**/*.vue"],
"exclude": ["node_modules"]
}
================================================
FILE: admin/vite.config.ts
================================================
import { ConfigEnv, UserConfigExport } from 'vite'
import path from 'path'
import vue from '@vitejs/plugin-vue'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import Components from 'unplugin-vue-components/vite'
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers'
import { ViteEjsPlugin } from 'vite-plugin-ejs'
import dns from 'dns'
const setAlias = (alias: [string, string][]) =>
alias.map((v) => {
return { find: v[0], replacement: path.resolve(__dirname, v[1]) }
})
// https://cn.vitejs.dev/config/server-options.html#server-host
dns.setDefaultResultOrder('verbatim')
export default ({ mode }: ConfigEnv): UserConfigExport => {
return {
resolve: {
alias: setAlias([['/@', 'src']])
},
plugins: [
vue(),
createSvgIconsPlugin({
iconDirs: [path.resolve(process.cwd(), 'src/icons')],
symbolId: 'icon-[dir]-[name]'
}),
Components({
dts: 'src/components.d.ts',
resolvers: [AntDesignVueResolver()]
}),
ViteEjsPlugin({
PUBLIC_PATH: mode !== 'development' ? 'PUBLIC-PATH-VARIABLE' : ''
})
],
experimental: {
renderBuiltUrl(
filename: string,
{
hostType
}: {
hostId: string;
hostType: 'js' | 'css' | 'html';
type: 'asset' | 'public';
}
) {
if (hostType === 'js') {
return {
runtime: `window.__assetsPathBuilder(${JSON.stringify(filename)})`
}
}
return filename
}
},
server: {
host: 'localhost',
port: 6789,
base: 'admin',
proxy: {
'/api': {
changeOrigin: true,
target: 'http://localhost:36789'
}
}
},
css: {
postcss: {
plugins: [
require('autoprefixer'),
require('tailwindcss'),
require('postcss-simple-vars'),
require('postcss-import')
]
}
}
}
}
================================================
FILE: charts/.helmignore
================================================
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
================================================
FILE: charts/Chart.yaml
================================================
apiVersion: v2
name: dtm
description: A Helm chart for Kubernetes
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "1.12.2"
================================================
FILE: charts/README.md
================================================
# DTM charts
## Usage
Install the dtm chart:
```bash
helm install --create-namespace -n dtm-system dtm ./charts
```
Upgrade the dtm chart:
```bash
helm upgrade -n dtm-system dtm ./charts
```
Uninstall the chart:
```bash
helm delete -n dtm-system dtm
```
## Parameters
### Configuration parameters
| Key | Description | Value |
|-----------------|---------------------------------------------------------------------------------------------------------------------------------------|-------|
| `configuration` | DTM configuration. Specify content for `config.yaml`, ref: [sample config](https://github.com/dtm-labs/dtm/blob/main/conf.sample.yml) | `""` |
### Autoscaling Parameters
| Name | Description | Value |
|-------------------------------------------------|-------------------------------------------|---------|
| `autoscaling.enabled` | Enable Horizontal POD autoscaling for DTM | `false` |
| `autoscaling.minReplicas` | Minimum number of DTM replicas | `1` |
| `autoscaling.maxReplicas` | Maximum number of DTM replicas | `10` |
| `autoscaling.targetCPUUtilizationPercentage` | Target CPU utilization percentage | `80` |
| `autoscaling.targetMemoryUtilizationPercentage` | Target Memory utilization percentage | `80` |
### Ingress parameters
| Key | Description | Value |
|--------------------------------|-------------------------------------------------------------------------------|---------------------|
| `ingress.enabled` | Enable ingress record generation for DTM | `false` |
| `ingress.className` | IngressClass that will be used to implement the Ingress (Kubernetes 1.18+) | `"nginx"` |
| `ingress.annotations` | To enable certificate auto generation, place here your cert-manager annotations. | `{}` |
| `ingress.hosts.host` | Default host for the ingress record. | `"your-domain.com"` |
| `ingress.hosts.paths.path` | Default path for the ingress record | `"/"` |
| `ingress.hosts.paths.pathType` | Ingress path type | `"Prefix"` |
| `ingress.tls` | Enable TLS configuration for the host defined at ingress.hostname parameter | `[]` |
================================================
FILE: charts/templates/NOTES.txt
================================================
1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range $host := .Values.ingress.hosts }}
{{- range .paths }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
{{- end }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "dtm.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "dtm.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "dtm.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "dtm.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
{{- end }}
================================================
FILE: charts/templates/_helpers.tpl
================================================
{{/*
Expand the name of the chart.
*/}}
{{- define "dtm.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "dtm.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "dtm.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "dtm.labels" -}}
helm.sh/chart: {{ include "dtm.chart" . }}
{{ include "dtm.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "dtm.selectorLabels" -}}
app.kubernetes.io/name: {{ include "dtm.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "dtm.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "dtm.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
================================================
FILE: charts/templates/configmap.yaml
================================================
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "dtm.fullname" . }}-conf
labels:
{{- include "dtm.labels" . | nindent 4 }}
data:
config.yaml: |-
{{- .Values.configuration | nindent 4 }}
================================================
FILE: charts/templates/deployment.yaml
================================================
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "dtm.fullname" . }}
labels:
{{- include "dtm.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "dtm.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "dtm.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
args:
- "-c=/app/dtm/configs/config.yaml"
volumeMounts:
- mountPath: /app/dtm/configs
name: config
ports:
- containerPort: 36789
protocol: TCP
name: http
- containerPort: 36790
protocol: TCP
name: grpc
livenessProbe:
httpGet:
path: /api/ping
port: 36789
scheme: HTTP
readinessProbe:
httpGet:
path: /api/ping
port: 36789
scheme: HTTP
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
- name: config
configMap:
name: {{ include "dtm.fullname" . }}-conf
================================================
FILE: charts/templates/hpa.yaml
================================================
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "dtm.fullname" . }}
labels:
{{- include "dtm.labels" . | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "dtm.fullname" . }}
minReplicas: {{ .Values.autoscaling.minReplicas }}
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
metrics:
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
- type: Resource
resource:
name: cpu
targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
{{- end }}
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
- type: Resource
resource:
name: memory
targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
{{- end }}
{{- end }}
================================================
FILE: charts/templates/ingress.yaml
================================================
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "dtm.fullname" . -}}
{{- $svcPort := .Values.service.ports.http -}}
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
{{- end }}
{{- end }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
{{- include "dtm.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
pathType: {{ .pathType }}
{{- end }}
backend:
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- else }}
serviceName: {{ $fullName }}
servicePort: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
================================================
FILE: charts/templates/service.yaml
================================================
apiVersion: v1
kind: Service
metadata:
name: {{ include "dtm.fullname" . }}
labels:
{{- include "dtm.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.ports.http }}
targetPort: http
protocol: TCP
name: http
- port: {{ .Values.service.ports.grpc }}
targetPort: grpc
protocol: TCP
name: grpc
selector:
{{- include "dtm.selectorLabels" . | nindent 4 }}
================================================
FILE: charts/templates/tests/test-connection.yaml
================================================
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "dtm.fullname" . }}-test-connection"
labels:
{{- include "dtm.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
spec:
containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ include "dtm.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never
================================================
FILE: charts/values.yaml
================================================
# Default values for dtm.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
# DTM configuration. Specify content for config.yaml
# ref: https://github.com/dtm-labs/dtm/blob/main/conf.sample.yml
configuration: |-
Store: # specify which engine to store trans status
Driver: 'boltdb' # default store engine
# replicaCount Number of dtm replicas to deploy
replicaCount: 1
# dtm image version
image:
repository: yedf/dtm
tag: "latest"
pullPolicy: IfNotPresent
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
podSecurityContext: {}
# fsGroup: 2000
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
resources:
requests:
cpu: 200m
memory: 200Mi
nodeSelector: {}
tolerations: []
affinity: {}
service:
type: ClusterIP
ports:
http: 36789
grpc: 36790
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 10
targetCPUUtilizationPercentage: 80
targetMemoryUtilizationPercentage: 80
ingress:
enabled: false
className: "nginx"
annotations:
{}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: your-domain.com
paths:
- path: /
pathType: Prefix
tls: []
# - secretName: chart-example-tls
# hosts:
# - your-domain.com
================================================
FILE: client/README.md
================================================
# Go Client for DTM
There are there packages:
## workflow
Workflow is a new client for DTM. It support the mixed usage of patterns saga, tcc, xa. And it also support the mixed usage of http, grpc and local transactions.
This pattern offers maximum flexibility and can handle a wide range of scenarios. This pattern is highly recommended for transactions that need to be rolled back
Quick start for workflow using http can be found here: [https://github.com/dtm-labs/quick-start-sample/tree/main/workflow-http](https://github.com/dtm-labs/quick-start-sample/tree/main/workflow-http)
Quick start for workflow using grpc can be found here: [https://github.com/dtm-labs/quick-start-sample/tree/main/workflow-grpc](https://github.com/dtm-labs/quick-start-sample/tree/main/workflow-grpc)
Detailed examples can be found here: [https://github.com/dtm-labs/dtm-examples](https://github.com/dtm-labs/dtm-examples)
## dtmcli
dtmcli is the http client for patterns: saga, tcc, msg, xa
Quick start for dtmcli can be found here: [https://github.com/dtm-labs/quick-start-sample/tree/main/dtmcli-qs](https://github.com/dtm-labs/quick-start-sample/tree/main/dtmcli-qs)
Detailed examples can be found here: [https://github.com/dtm-labs/dtm-examples](https://github.com/dtm-labs/dtm-examples)
## dtmgrpc
dtmcli is the grpc client for patterns: saga, tcc, msg, xa
Quick start for dtmgrpc can be found here: [https://github.com/dtm-labs/quick-start-sample/tree/main/dtmgrpc-qs](https://github.com/dtm-labs/quick-start-sample/tree/main/dtmgrpc-qs)
Detailed examples can be found here: [https://github.com/dtm-labs/dtm-examples](https://github.com/dtm-labs/dtm-examples)
================================================
FILE: client/dtmcli/barrier.go
================================================
/*
* 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 dtmcli
import (
"database/sql"
"fmt"
"net/url"
"github.com/dtm-labs/dtm/client/dtmcli/dtmimp"
"github.com/dtm-labs/logger"
)
// BarrierBusiFunc type for busi func
type BarrierBusiFunc func(tx *sql.Tx) error
// BranchBarrier every branch info
type BranchBarrier struct {
TransType string
Gid string
BranchID string
Op string
BarrierID int
DBType string // DBTypeMysql | DBTypePostgres
BarrierTableName string
}
func (bb *BranchBarrier) String() string {
return fmt.Sprintf("transInfo: %s %s %s %s", bb.TransType, bb.Gid, bb.BranchID, bb.Op)
}
func (bb *BranchBarrier) newBarrierID() string {
bb.BarrierID++
return fmt.Sprintf("%02d", bb.BarrierID)
}
// BarrierFromQuery construct transaction info from request
func BarrierFromQuery(qs url.Values) (*BranchBarrier, error) {
return BarrierFrom(dtmimp.EscapeGet(qs, "trans_type"), dtmimp.EscapeGet(qs, "gid"), dtmimp.EscapeGet(qs, "branch_id"), dtmimp.EscapeGet(qs, "op"))
}
// BarrierFrom construct transaction info from request
func BarrierFrom(transType, gid, branchID, op string) (*BranchBarrier, error) {
ti := &BranchBarrier{
TransType: transType,
Gid: gid,
BranchID: branchID,
Op: op,
}
if ti.TransType == "" || ti.Gid == "" || ti.BranchID == "" || ti.Op == "" {
return nil, fmt.Errorf("invalid trans info: %v", ti)
}
return ti, nil
}
// Call see detail description in https://en.dtm.pub/practice/barrier.html
// tx: local transaction connection
// busiCall: busi func
func (bb *BranchBarrier) Call(tx *sql.Tx, busiCall BarrierBusiFunc) (rerr error) {
bid := bb.newBarrierID()
defer dtmimp.DeferDo(&rerr, func() error {
return tx.Commit()
}, func() error {
return tx.Rollback()
})
originOp := map[string]string{
dtmimp.OpCancel: dtmimp.OpTry, // tcc
dtmimp.OpCompensate: dtmimp.OpAction, // saga
dtmimp.OpRollback: dtmimp.OpAction, // workflow
}[bb.Op]
originAffected, oerr := dtmimp.InsertBarrier(tx, bb.TransType, bb.Gid, bb.BranchID, originOp, bid, bb.Op, bb.DBType, bb.BarrierTableName)
currentAffected, rerr := dtmimp.InsertBarrier(tx, bb.TransType, bb.Gid, bb.BranchID, bb.Op, bid, bb.Op, bb.DBType, bb.BarrierTableName)
logger.Debugf("originAffected: %d currentAffected: %d", originAffected, currentAffected)
if rerr == nil && bb.Op == dtmimp.MsgDoOp && currentAffected == 0 { // for msg's DoAndSubmit, repeated insert should be rejected.
return ErrDuplicated
}
if rerr == nil {
rerr = oerr
}
if (bb.Op == dtmimp.OpCancel || bb.Op == dtmimp.OpCompensate || bb.Op == dtmimp.OpRollback) && originAffected > 0 || // null compensate
currentAffected == 0 { // repeated request or dangled request
return
}
if rerr == nil {
rerr = busiCall(tx)
}
return
}
// CallWithDB the same as Call, but with *sql.DB
func (bb *BranchBarrier) CallWithDB(db *sql.DB, busiCall BarrierBusiFunc) error {
tx, err := db.Begin()
if err == nil {
err = bb.Call(tx, busiCall)
}
return err
}
// QueryPrepared queries prepared data
func (bb *BranchBarrier) QueryPrepared(db *sql.DB) error {
_, err := dtmimp.InsertBarrier(db, bb.TransType, bb.Gid, dtmimp.MsgDoBranch0, dtmimp.MsgDoOp, dtmimp.MsgDoBarrier1, dtmimp.OpRollback, bb.DBType, bb.BarrierTableName)
var reason string
if err == nil {
sql := fmt.Sprintf("select reason from %s where gid=? and branch_id=? and op=? and barrier_id=?", dtmimp.BarrierTableName)
sql = dtmimp.GetDBSpecial(bb.DBType).GetPlaceHoldSQL(sql)
logger.Debugf("queryrow: %s", sql, bb.Gid, dtmimp.MsgDoBranch0, dtmimp.MsgDoOp, dtmimp.MsgDoBarrier1)
err = db.QueryRow(sql, bb.Gid, dtmimp.MsgDoBranch0, dtmimp.MsgDoOp, dtmimp.MsgDoBarrier1).Scan(&reason)
}
if reason == dtmimp.OpRollback {
return ErrFailure
}
return err
}
================================================
FILE: client/dtmcli/barrier_mongo.go
================================================
package dtmcli
import (
"context"
"strings"
"github.com/dtm-labs/dtm/client/dtmcli/dtmimp"
"github.com/dtm-labs/logger"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)
// MongoCall sub-trans barrier for mongo. see http://dtm.pub/practice/barrier
// experimental
func (bb *BranchBarrier) MongoCall(mc *mongo.Client, busiCall func(mongo.SessionContext) error) (rerr error) {
bid := bb.newBarrierID()
return mc.UseSession(context.Background(), func(sc mongo.SessionContext) (rerr error) {
rerr = sc.StartTransaction()
if rerr != nil {
return nil
}
defer dtmimp.DeferDo(&rerr, func() error {
return sc.CommitTransaction(sc)
}, func() error {
return sc.AbortTransaction(sc)
})
originOp := map[string]string{
dtmimp.OpCancel: dtmimp.OpTry,
dtmimp.OpCompensate: dtmimp.OpAction,
}[bb.Op]
originAffected, oerr := mongoInsertBarrier(sc, mc, bb.TransType, bb.Gid, bb.BranchID, originOp, bid, bb.Op)
currentAffected, rerr := mongoInsertBarrier(sc, mc, bb.TransType, bb.Gid, bb.BranchID, bb.Op, bid, bb.Op)
logger.Debugf("originAffected: %d currentAffected: %d", originAffected, currentAffected)
if rerr == nil && bb.Op == dtmimp.MsgDoOp && currentAffected == 0 { // for msg's DoAndSubmit, repeated insert should be rejected.
return ErrDuplicated
}
if rerr == nil {
rerr = oerr
}
if (bb.Op == dtmimp.OpCancel || bb.Op == dtmimp.OpCompensate) && originAffected > 0 || // null compensate
currentAffected == 0 { // repeated request or dangled request
return
}
if rerr == nil {
rerr = busiCall(sc)
}
return
})
}
// MongoQueryPrepared query prepared for redis
// experimental
func (bb *BranchBarrier) MongoQueryPrepared(mc *mongo.Client) error {
_, err := mongoInsertBarrier(context.Background(), mc, bb.TransType, bb.Gid, dtmimp.MsgDoBranch0, dtmimp.MsgDoOp, dtmimp.MsgDoBarrier1, dtmimp.OpRollback)
var result bson.M
if err == nil {
fs := strings.Split(dtmimp.BarrierTableName, ".")
barrier := mc.Database(fs[0]).Collection(fs[1])
err = barrier.FindOne(context.Background(), bson.D{
{Key: "gid", Value: bb.Gid},
{Key: "branch_id", Value: dtmimp.MsgDoBranch0},
{Key: "op", Value: dtmimp.MsgDoOp},
{Key: "barrier_id", Value: dtmimp.MsgDoBarrier1},
}).Decode(&result)
}
var reason string
if err == nil {
reason, _ = result["reason"].(string)
}
if err == nil && reason == dtmimp.OpRollback {
return ErrFailure
}
return err
}
func mongoInsertBarrier(sc context.Context, mc *mongo.Client, transType string, gid string, branchID string, op string, barrierID string, reason string) (int64, error) {
if op == "" {
return 0, nil
}
fs := strings.Split(dtmimp.BarrierTableName, ".")
barrier := mc.Database(fs[0]).Collection(fs[1])
r := barrier.FindOne(sc, bson.D{
{Key: "gid", Value: gid},
{Key: "branch_id", Value: branchID},
{Key: "op", Value: op},
{Key: "barrier_id", Value: barrierID},
})
err := r.Err()
if err == mongo.ErrNoDocuments {
_, err = barrier.InsertOne(sc,
bson.D{
{Key: "trans_type", Value: transType},
{Key: "gid", Value: gid},
{Key: "branch_id", Value: branchID},
{Key: "op", Value: op},
{Key: "barrier_id", Value: barrierID},
{Key: "reason", Value: reason},
})
return 1, err
}
return 0, err
}
================================================
FILE: client/dtmcli/barrier_redis.go
================================================
package dtmcli
import (
"context"
"fmt"
"github.com/dtm-labs/dtm/client/dtmcli/dtmimp"
"github.com/dtm-labs/logger"
"github.com/redis/go-redis/v9"
)
// RedisCheckAdjustAmount check the value of key is valid and >= amount. then adjust the amount
func (bb *BranchBarrier) RedisCheckAdjustAmount(rd redis.Cmdable, key string, amount int, barrierExpire int) error {
bid := bb.newBarrierID()
bkey1 := fmt.Sprintf("%s-%s-%s-%s", bb.Gid, bb.BranchID, bb.Op, bid)
originOp := map[string]string{
dtmimp.OpCancel: dtmimp.OpTry,
dtmimp.OpCompensate: dtmimp.OpAction,
}[bb.Op]
bkey2 := fmt.Sprintf("%s-%s-%s-%s", bb.Gid, bb.BranchID, originOp, bid)
v, err := rd.Eval(context.Background(), ` -- RedisCheckAdjustAmount
local v = redis.call('GET', KEYS[1])
local e1 = redis.call('GET', KEYS[2])
if v == false or v + ARGV[1] < 0 then
return 'FAILURE'
end
if e1 ~= false then
return 'DUPLICATE'
end
redis.call('SET', KEYS[2], 'op', 'EX', ARGV[3])
if ARGV[2] ~= '' then
local e2 = redis.call('GET', KEYS[3])
if e2 == false then
redis.call('SET', KEYS[3], 'rollback', 'EX', ARGV[3])
return
end
end
redis.call('INCRBY', KEYS[1], ARGV[1])
`, []string{key, bkey1, bkey2}, amount, originOp, barrierExpire).Result()
logger.Debugf("lua return v: %v err: %v", v, err)
if err == redis.Nil {
err = nil
}
if err == nil && bb.Op == dtmimp.MsgDoOp && v == "DUPLICATE" { // msg DoAndSubmit should be rejected when duplicate
return ErrDuplicated
}
if err == nil && v == ResultFailure {
err = ErrFailure
}
return err
}
// RedisQueryPrepared query prepared for redis
func (bb *BranchBarrier) RedisQueryPrepared(rd redis.Cmdable, barrierExpire int) error {
bkey1 := fmt.Sprintf("%s-%s-%s-%s", bb.Gid, dtmimp.MsgDoBranch0, dtmimp.MsgDoOp, dtmimp.MsgDoBarrier1)
v, err := rd.Eval(context.Background(), ` -- RedisQueryPrepared
local v = redis.call('GET', KEYS[1])
if v == false then
redis.call('SET', KEYS[1], 'rollback', 'EX', ARGV[1])
v = 'rollback'
end
if v == 'rollback' then
return 'FAILURE'
end
`, []string{bkey1}, barrierExpire).Result()
logger.Debugf("lua return v: %v err: %v", v, err)
if err == redis.Nil {
err = nil
}
if err == nil && v == ResultFailure {
err = ErrFailure
}
return err
}
================================================
FILE: client/dtmcli/consts.go
================================================
/*
* 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 dtmcli
import (
"github.com/dtm-labs/dtm/client/dtmcli/dtmimp"
)
const (
// StatusPrepared status for global/branch trans status.
// first step, tx preparation period
StatusPrepared = "prepared"
// StatusSubmitted status for global trans status.
StatusSubmitted = "submitted"
// StatusSucceed status for global/branch trans status.
StatusSucceed = "succeed"
// StatusFailed status for global/branch trans status.
// NOTE: change global status to failed can stop trigger (Not recommended in production env)
StatusFailed = "failed"
// StatusAborting status for global trans status.
StatusAborting = "aborting"
// ResultSuccess for result of a trans/trans branch
ResultSuccess = dtmimp.ResultSuccess
// ResultFailure for result of a trans/trans branch
ResultFailure = dtmimp.ResultFailure
// ResultOngoing for result of a trans/trans branch
ResultOngoing = dtmimp.ResultOngoing
// DBTypeMysql const for driver mysql
DBTypeMysql = dtmimp.DBTypeMysql
// DBTypePostgres const for driver postgres
DBTypePostgres = dtmimp.DBTypePostgres
// DBTypeSQLServer const for driver SQLServer
DBTypeSQLServer = dtmimp.DBTypeSQLServer
)
// MapSuccess HTTP result of SUCCESS
var MapSuccess = dtmimp.MapSuccess
// MapFailure HTTP result of FAILURE
var MapFailure = dtmimp.MapFailure
// ErrFailure error for returned failure
var ErrFailure = dtmimp.ErrFailure
// ErrOngoing error for returned ongoing
var ErrOngoing = dtmimp.ErrOngoing
// ErrDuplicated error of DUPLICATED for only msg
// if QueryPrepared executed before call. then DoAndSubmit return this error
var ErrDuplicated = dtmimp.ErrDuplicated
================================================
FILE: client/dtmcli/cover_test.go
================================================
/*
* 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 dtmcli
import (
"net/url"
"testing"
"github.com/stretchr/testify/assert"
)
func TestQuery(t *testing.T) {
qs, err := url.ParseQuery("a=b")
assert.Nil(t, err)
_, err = XaFromQuery(qs)
assert.Error(t, err)
_, err = TccFromQuery(qs)
assert.Error(t, err)
_, err = BarrierFromQuery(qs)
assert.Error(t, err)
}
================================================
FILE: client/dtmcli/dtmimp/README-cn.md
================================================
## 注意
此包带imp后缀,主要被dtm内部使用,相关接口可能会发生变更,请勿使用这里的接口
================================================
FILE: client/dtmcli/dtmimp/README.md
================================================
## Notice
Please donot use this package, and this package should only be used in dtm internally. The interfaces are not stable, and package name has postfix "imp"
================================================
FILE: client/dtmcli/dtmimp/consts.go
================================================
/*
* 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 dtmimp
const (
// ResultFailure for result of a trans/trans branch
// Same as HTTP status 409 and GRPC code 10
ResultFailure = "FAILURE"
// ResultSuccess for result of a trans/trans branch
// Same as HTTP status 200 and GRPC code 0
ResultSuccess = "SUCCESS"
// ResultOngoing for result of a trans/trans branch
// Same as HTTP status 425 and GRPC code 9
ResultOngoing = "ONGOING"
// OpTry branch type for TCC
OpTry = "try"
// OpConfirm branch type for TCC
OpConfirm = "confirm"
// OpCancel branch type for TCC
OpCancel = "cancel"
// OpAction branch type for message, SAGA, XA
OpAction = "action"
// OpCompensate branch type for SAGA
OpCompensate = "compensate"
// OpCommit branch type for XA
OpCommit = "commit"
// OpRollback branch type for XA
OpRollback = "rollback"
// DBTypeMysql const for driver mysql
DBTypeMysql = "mysql"
// DBTypePostgres const for driver postgres
DBTypePostgres = "postgres"
// DBTypeSQLServer const for driver SQLServer
DBTypeSQLServer = "sqlserver"
// DBTypeRedis const for driver redis
DBTypeRedis = "redis"
// Jrpc const for json-rpc
Jrpc = "json-rpc"
// JrpcCodeFailure const for json-rpc failure
JrpcCodeFailure = -32901
// JrpcCodeOngoing const for json-rpc ongoing
JrpcCodeOngoing = -32902
// MsgDoBranch0 const for DoAndSubmit barrier branch
MsgDoBranch0 = "00"
// MsgDoBarrier1 const for DoAndSubmit barrier barrierID
MsgDoBarrier1 = "01"
// MsgDoOp const for DoAndSubmit barrier op
MsgDoOp = "msg"
//MsgTopicPrefix const for Add topic msg
MsgTopicPrefix = "topic://"
// XaBarrier1 const for xa barrier id
XaBarrier1 = "01"
// ProtocolGRPC const for protocol grpc
ProtocolGRPC = "grpc"
// ProtocolHTTP const for protocol http
ProtocolHTTP = "http"
)
================================================
FILE: client/dtmcli/dtmimp/db_special.go
================================================
/*
* 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 dtmimp
import (
"fmt"
"strings"
)
// DBSpecial db specific operations
type DBSpecial interface {
GetPlaceHoldSQL(sql string) string
GetInsertIgnoreTemplate(tableAndValues string, pgConstraint string) string
GetXaSQL(command string, xid string) string
}
var dbSpecials = map[string]DBSpecial{}
var currentDBType = DBTypeMysql
type mysqlDBSpecial struct{}
func (*mysqlDBSpecial) GetPlaceHoldSQL(sql string) string {
return sql
}
func (*mysqlDBSpecial) GetXaSQL(command string, xid string) string {
if command == "abort" {
command = "rollback"
}
return fmt.Sprintf("xa %s '%s'", command, xid)
}
func (*mysqlDBSpecial) GetInsertIgnoreTemplate(tableAndValues string, pgConstraint string) string {
return fmt.Sprintf("insert ignore into %s", tableAndValues)
}
func init() {
dbSpecials[DBTypeMysql] = &mysqlDBSpecial{}
}
type postgresDBSpecial struct{}
func (*postgresDBSpecial) GetXaSQL(command string, xid string) string {
return map[string]string{
"end": "",
"start": "begin",
"abort": "rollback",
"prepare": fmt.Sprintf("prepare transaction '%s'", xid),
"commit": fmt.Sprintf("commit prepared '%s'", xid),
"rollback": fmt.Sprintf("rollback prepared '%s'", xid),
}[command]
}
func (*postgresDBSpecial) GetPlaceHoldSQL(sql string) string {
pos := 1
parts := []string{}
b := 0
for i := 0; i < len(sql); i++ {
if sql[i] == '?' {
parts = append(parts, sql[b:i])
b = i + 1
parts = append(parts, fmt.Sprintf("$%d", pos))
pos++
}
}
parts = append(parts, sql[b:])
return strings.Join(parts, "")
}
func (*postgresDBSpecial) GetInsertIgnoreTemplate(tableAndValues string, pgConstraint string) string {
return fmt.Sprintf("insert into %s on conflict ON CONSTRAINT %s do nothing", tableAndValues, pgConstraint)
}
func init() {
dbSpecials[DBTypePostgres] = &postgresDBSpecial{}
}
// GetDBSpecial get DBSpecial for currentDBType
func GetDBSpecial(dbType string) DBSpecial {
if dbType == "" {
dbType = currentDBType
}
return dbSpecials[dbType]
}
// SetCurrentDBType set currentDBType
func SetCurrentDBType(dbType string) {
spec := dbSpecials[dbType]
PanicIf(spec == nil, fmt.Errorf("unknown db type '%s'", dbType))
currentDBType = dbType
}
// GetCurrentDBType get currentDBType
func GetCurrentDBType() string {
return currentDBType
}
================================================
FILE: client/dtmcli/dtmimp/db_special_test.go
================================================
/*
* 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 dtmimp
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestDBSpecial(t *testing.T) {
old := currentDBType
assert.Error(t, CatchP(func() {
SetCurrentDBType("no-driver")
}))
SetCurrentDBType(DBTypeMysql)
sp := GetDBSpecial(DBTypeMysql)
assert.Equal(t, "? ?", sp.GetPlaceHoldSQL("? ?"))
assert.Equal(t, "xa start 'xa1'", sp.GetXaSQL("start", "xa1"))
assert.Equal(t, "insert ignore into a(f) values(?)", sp.GetInsertIgnoreTemplate("a(f) values(?)", "c"))
SetCurrentDBType(DBTypePostgres)
sp = GetDBSpecial(DBTypePostgres)
assert.Equal(t, "$1 $2", sp.GetPlaceHoldSQL("? ?"))
assert.Equal(t, "begin", sp.GetXaSQL("start", "xa1"))
assert.Equal(t, "insert into a(f) values(?) on conflict ON CONSTRAINT c do nothing", sp.GetInsertIgnoreTemplate("a(f) values(?)", "c"))
SetCurrentDBType(old)
}
================================================
FILE: client/dtmcli/dtmimp/trans_base.go
================================================
/*
* 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 dtmimp
import (
"context"
"errors"
"fmt"
"net/http"
"net/url"
"strings"
"time"
"github.com/go-resty/resty/v2"
)
// BranchIDGen used to generate a sub branch id
type BranchIDGen struct {
BranchID string
subBranchID int
}
// NewSubBranchID generate a sub branch id
func (g *BranchIDGen) NewSubBranchID() string {
if g.subBranchID >= 99 {
panic(fmt.Errorf("branch id is larger than 99"))
}
if len(g.BranchID) >= 20 {
panic(fmt.Errorf("total branch id is longer than 20"))
}
g.subBranchID = g.subBranchID + 1
return g.CurrentSubBranchID()
}
// CurrentSubBranchID return current branchID
func (g *BranchIDGen) CurrentSubBranchID() string {
return g.BranchID + fmt.Sprintf("%02d", g.subBranchID)
}
// TransOptions transaction options
type TransOptions struct {
WaitResult bool `json:"wait_result,omitempty" gorm:"-"`
TimeoutToFail int64 `json:"timeout_to_fail,omitempty" gorm:"-"` // for trans type: xa, tcc, unit: second
RequestTimeout int64 `json:"request_timeout,omitempty" gorm:"-"` // for global trans resets request timeout, unit: second
RetryInterval int64 `json:"retry_interval,omitempty" gorm:"-"` // for trans type: msg saga xa tcc, unit: second
BranchHeaders map[string]string `json:"branch_headers,omitempty" gorm:"-"` // custom branch headers, dtm server => service api
Concurrent bool `json:"concurrent" gorm:"-"` // for trans type: saga msg
RetryLimit int64 `json:"retry_limit,omitempty" gorm:"-"` // for trans type: saga
RetryCount int64 `json:"retry_count,omitempty" gorm:"-"` // for trans type: saga
}
// TransBase base for all trans
type TransBase struct {
Gid string `json:"gid"` // NOTE: unique in storage, can customize the generation rules instead of using server-side generation, it will help with the tracking
TransType string `json:"trans_type"`
Dtm string `json:"-"`
CustomData string `json:"custom_data,omitempty"` // nosql data persistence
TransOptions
Context context.Context `json:"-" gorm:"-"`
Steps []map[string]string `json:"steps,omitempty"` // use in MSG/SAGA
Payloads []string `json:"payloads,omitempty"` // used in MSG/SAGA
BinPayloads [][]byte `json:"-"`
BranchIDGen `json:"-"` // used in XA/TCC
Op string `json:"-"` // used in XA/TCC
QueryPrepared string `json:"query_prepared,omitempty"` // used in MSG
Protocol string `json:"protocol"`
RollbackReason string `json:"rollback_reason,omitempty" gorm:"-"`
}
// NewTransBase new a TransBase
func NewTransBase(gid string, transType string, dtm string, branchID string) *TransBase {
return &TransBase{
Gid: gid,
TransType: transType,
BranchIDGen: BranchIDGen{BranchID: branchID},
Dtm: dtm,
Context: context.Background(),
}
}
// WithGlobalTransRequestTimeout defines global trans request timeout
func (t *TransBase) WithGlobalTransRequestTimeout(timeout int64) {
t.RequestTimeout = timeout
}
// WithRetryLimit defines global trans retry limit
func (t *TransBase) WithRetryLimit(retryLimit int64) {
t.RetryLimit = retryLimit
}
// TransBaseFromQuery construct transaction info from request
func TransBaseFromQuery(qs url.Values) *TransBase {
return NewTransBase(EscapeGet(qs, "gid"), EscapeGet(qs, "trans_type"), EscapeGet(qs, "dtm"), EscapeGet(qs, "branch_id"))
}
// TransCallDtmExt TransBase call dtm
func TransCallDtmExt(tb *TransBase, body interface{}, operation string) (*resty.Response, error) {
if tb.Protocol == Jrpc {
return transCallDtmJrpc(tb, body, operation)
}
rc := GetRestyClient2(time.Duration(tb.RequestTimeout) * time.Second)
resp, err := rc.R().
SetBody(body).Post(fmt.Sprintf("%s/%s", tb.Dtm, operation))
if err != nil {
return nil, err
}
if resp.StatusCode() != http.StatusOK || strings.Contains(resp.String(), ResultFailure) {
return nil, errors.New(resp.String())
}
return resp, nil
}
// TransCallDtm is the short call for TransCallDtmExt
func TransCallDtm(tb *TransBase, operation string) error {
_, err := TransCallDtmExt(tb, tb, operation)
return err
}
// TransRegisterBranch TransBase register a branch to dtm
func TransRegisterBranch(tb *TransBase, added map[string]string, operation string) error {
m := map[string]string{
"gid": tb.Gid,
"trans_type": tb.TransType,
}
for k, v := range added {
m[k] = v
}
_, err := TransCallDtmExt(tb, m, operation)
return err
}
// TransRequestBranch TransBase request branch result
func TransRequestBranch(t *TransBase, method string, body interface{}, branchID string, op string, url string) (*resty.Response, error) {
if url == "" {
return nil, nil
}
query := map[string]string{
"dtm": t.Dtm,
"gid": t.Gid,
"branch_id": branchID,
"trans_type": t.TransType,
"op": op,
}
if t.TransType == "xa" { // xa trans will add notify_url
query["phase2_url"] = url
}
resp, err := GetRestyClient2(0).R().
SetBody(body).
SetQueryParams(query).
SetHeaders(t.BranchHeaders).
Execute(method, url)
return resp, err
}
func transCallDtmJrpc(tb *TransBase, body interface{}, operation string) (*resty.Response, error) {
rc := GetRestyClient2(time.Duration(tb.RequestTimeout) * time.Second)
var result map[string]interface{}
resp, err := rc.R().
SetBody(map[string]interface{}{
"jsonrpc": "2.0",
"id": "no-use",
"method": operation,
"params": body,
}).
SetResult(&result).
Post(tb.Dtm)
if err != nil {
return nil, err
}
if resp.StatusCode() != http.StatusOK || result["error"] != nil {
return nil, errors.New(resp.String())
}
return resp, nil
}
================================================
FILE: client/dtmcli/dtmimp/trans_xa_base.go
================================================
/*
* 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 dtmimp
import (
"database/sql"
"strings"
)
// XaHandlePhase2 Handle the callback of commit/rollback
func XaHandlePhase2(gid string, dbConf DBConf, branchID string, op string) error {
db, err := PooledDB(dbConf)
if err != nil {
return err
}
xaID := gid + "-" + branchID
_, err = DBExec(dbConf.Driver, db, GetDBSpecial(dbConf.Driver).GetXaSQL(op, xaID))
if err != nil &&
(strings.Contains(err.Error(), "XAER_NOTA") || strings.Contains(err.Error(), "does not exist")) { // Repeat commit/rollback with the same id, report this error, ignore
err = nil
}
if op == OpRollback && err == nil {
// rollback insert a row after prepare. no-error means prepare has finished.
_, err = InsertBarrier(db, "xa", gid, branchID, OpAction, XaBarrier1, op, dbConf.Driver, "")
}
return err
}
// XaHandleLocalTrans public handler of LocalTransaction via http/grpc
func XaHandleLocalTrans(xa *TransBase, dbConf DBConf, cb func(*sql.DB) error) (rerr error) {
xaBranch := xa.Gid + "-" + xa.BranchID
db, rerr := XaDB(dbConf)
if rerr != nil {
return
}
defer XaClose(db)
defer DeferDo(&rerr, func() error {
_, err := DBExec(dbConf.Driver, db, GetDBSpecial(dbConf.Driver).GetXaSQL("prepare", xaBranch))
return err
}, func() error {
_, err := DBExec(dbConf.Driver, db, GetDBSpecial(dbConf.Driver).GetXaSQL("abort", xaBranch))
return err
})
_, rerr = DBExec(dbConf.Driver, db, GetDBSpecial(dbConf.Driver).GetXaSQL("start", xaBranch))
if rerr != nil {
return
}
defer func() {
_, _ = DBExec(dbConf.Driver, db, GetDBSpecial(dbConf.Driver).GetXaSQL("end", xaBranch))
}()
// prepare and rollback both insert a row
_, rerr = InsertBarrier(db, xa.TransType, xa.Gid, xa.BranchID, OpAction, XaBarrier1, OpAction, dbConf.Driver, "")
if rerr == nil {
rerr = cb(db)
}
return
}
// XaHandleGlobalTrans http/grpc GlobalTransaction shared func
func XaHandleGlobalTrans(xa *TransBase, callDtm func(string) error, callBusi func() error) (rerr error) {
rerr = callDtm("prepare")
if rerr != nil {
return
}
defer DeferDo(&rerr, func() error {
return callDtm("submit")
}, func() error {
return callDtm("abort")
})
rerr = callBusi()
return
}
================================================
FILE: client/dtmcli/dtmimp/types.go
================================================
/*
* 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 dtmimp
import "database/sql"
// DB interface of dtmcli db
type DB interface {
Exec(query string, args ...interface{}) (sql.Result, error)
QueryRow(query string, args ...interface{}) *sql.Row
}
// DBConf defines db config
type DBConf struct {
Driver string `yaml:"Driver"`
Host string `yaml:"Host"`
Port int64 `yaml:"Port"`
User string `yaml:"User"`
Password string `yaml:"Password"`
Db string `yaml:"Db"`
Schema string `yaml:"Schema"`
}
================================================
FILE: client/dtmcli/dtmimp/types_test.go
================================================
/*
* 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 dtmimp
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestTypes(t *testing.T) {
err := CatchP(func() {
idGen := BranchIDGen{BranchID: "12345678901234567890123"}
idGen.NewSubBranchID()
})
assert.Error(t, err)
err = CatchP(func() {
idGen := BranchIDGen{subBranchID: 99}
idGen.NewSubBranchID()
})
assert.Error(t, err)
}
================================================
FILE: client/dtmcli/dtmimp/utils.go
================================================
/*
* 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 dtmimp
import (
"database/sql"
"encoding/json"
"errors"
"fmt"
"net/url"
"os"
"runtime"
"strconv"
"strings"
"sync"
"time"
"github.com/dtm-labs/logger"
"github.com/go-resty/resty/v2"
)
// Logf an alias of Infof
// Deprecated: use logger.Errorf
var Logf = logger.Infof
// LogRedf an alias of Errorf
// Deprecated: use logger.Errorf
var LogRedf = logger.Errorf
// FatalIfError fatal if error is not nil
// Deprecated: use logger.FatalIfError
var FatalIfError = logger.FatalIfError
// LogIfFatalf fatal if cond is true
// Deprecated: use logger.FatalfIf
var LogIfFatalf = logger.FatalfIf
// AsError wrap a panic value as an error
func AsError(x interface{}) error {
logger.Errorf("panic wrapped to error: '%v'", x)
if e, ok := x.(error); ok {
return e
}
return fmt.Errorf("%v", x)
}
// P2E panic to error
func P2E(perr *error) {
if x := recover(); x != nil {
*perr = AsError(x)
}
}
// E2P error to panic
func E2P(err error) {
if err != nil {
panic(err)
}
}
// CatchP catch panic to error
func CatchP(f func()) (rerr error) {
defer P2E(&rerr)
f()
return nil
}
// PanicIf name is clear
func PanicIf(cond bool, err error) {
if cond {
panic(err)
}
}
// MustAtoi is string to int
func MustAtoi(s string) int {
r, err := strconv.Atoi(s)
if err != nil {
E2P(errors.New("convert to int error: " + s))
}
return r
}
// OrString return the first not empty string
func OrString(ss ...string) string {
for _, s := range ss {
if s != "" {
return s
}
}
return ""
}
// If ternary operator
func If(condition bool, trueObj interface{}, falseObj interface{}) interface{} {
if condition {
return trueObj
}
return falseObj
}
// MustMarshal checked version for marshal
func MustMarshal(v interface{}) []byte {
b, err := json.Marshal(v)
E2P(err)
return b
}
// MustMarshalString string version of MustMarshal
func MustMarshalString(v interface{}) string {
return string(MustMarshal(v))
}
// MustUnmarshal checked version for unmarshal
func MustUnmarshal(b []byte, obj interface{}) {
err := json.Unmarshal(b, obj)
E2P(err)
}
// MustUnmarshalString string version of MustUnmarshal
func MustUnmarshalString(s string, obj interface{}) {
MustUnmarshal([]byte(s), obj)
}
// MustRemarshal marshal and unmarshal, and check error
func MustRemarshal(from interface{}, to interface{}) {
b, err := json.Marshal(from)
E2P(err)
err = json.Unmarshal(b, to)
E2P(err)
}
// GetFuncName get current call func name
func GetFuncName() string {
pc, _, _, _ := runtime.Caller(1)
nm := runtime.FuncForPC(pc).Name()
return nm[strings.LastIndex(nm, ".")+1:]
}
// MayReplaceLocalhost when run in docker compose, change localhost to host.docker.internal for accessing host network
func MayReplaceLocalhost(host string) string {
if os.Getenv("IS_DOCKER") != "" {
return strings.Replace(strings.Replace(host,
"localhost", "host.docker.internal", 1),
"127.0.0.1", "host.docker.internal", 1)
}
return host
}
var sqlDbs = &mapCache{cache: map[string]*sql.DB{}}
type mapCache struct {
mutex sync.Mutex
cache map[string]*sql.DB
}
func (m *mapCache) LoadOrStore(conf DBConf, factory func(conf DBConf) (*sql.DB, error)) (*sql.DB, error) {
m.mutex.Lock()
defer m.mutex.Unlock()
dsn := GetDsn(conf)
if db, ok := m.cache[dsn]; ok {
return db, nil
}
db, err := factory(conf)
if err != nil {
return nil, err
}
m.cache[dsn] = db
return db, nil
}
// PooledDB get pooled sql.DB
func PooledDB(conf DBConf) (*sql.DB, error) {
return sqlDbs.LoadOrStore(conf, StandaloneDB)
}
// StandaloneDB get a standalone db instance
func StandaloneDB(conf DBConf) (*sql.DB, error) {
dsn := GetDsn(conf)
logger.Infof("opening standalone %s: %s", conf.Driver, strings.Replace(dsn, conf.Password, "****", 1))
return sql.Open(conf.Driver, dsn)
}
// XaDB return a standalone db instance for xa
func XaDB(conf DBConf) (*sql.DB, error) {
dsn := GetDsn(conf)
if conf.Driver == DBTypeMysql {
dsn += "&autocommit=0"
}
logger.Infof("opening xa standalone %s: %s", conf.Driver, strings.Replace(dsn, conf.Password, "****", 1))
return sql.Open(conf.Driver, dsn)
}
// XaClose will log and close the db
func XaClose(db *sql.DB) {
logger.Infof("closing xa db")
_ = db.Close()
}
// DBExec use raw db to exec
func DBExec(dbType string, db DB, sql string, values ...interface{}) (affected int64, rerr error) {
if sql == "" {
return 0, nil
}
began := time.Now()
if len(values) > 0 {
sql = GetDBSpecial(dbType).GetPlaceHoldSQL(sql)
}
r, rerr := db.Exec(sql, values...)
used := time.Since(began) / time.Millisecond
if rerr == nil {
affected, rerr = r.RowsAffected()
logger.Debugf("used: %d ms affected: %d for %s %v", used, affected, sql, values)
} else {
logger.Errorf("used: %d ms exec error: %v for %s %v", used, rerr, sql, values)
}
return
}
// GetDsn get dsn from map config
func GetDsn(conf DBConf) string {
host := MayReplaceLocalhost(conf.Host)
driver := conf.Driver
dsn := map[string]string{
"mysql": fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=true&loc=Local&interpolateParams=true",
conf.User, conf.Password, host, conf.Port, conf.Db),
"postgres": fmt.Sprintf("host=%s user=%s password=%s dbname='%s' search_path=%s port=%d sslmode=disable",
host, conf.User, conf.Password, conf.Db, conf.Schema, conf.Port),
// sqlserver://sa:mypass@localhost:1234?database=master&connection+timeout=30
"sqlserver": getSQLServerConnectionString(&conf, &host),
}[driver]
PanicIf(dsn == "", fmt.Errorf("unknow driver: %s", driver))
return dsn
}
func getSQLServerConnectionString(conf *DBConf, host *string) string {
query := url.Values{}
query.Add("database", conf.Db)
u := &url.URL{
Scheme: "sqlserver",
User: url.UserPassword(conf.User, conf.Password),
Host: fmt.Sprintf("%s:%d", *host, conf.Port),
// Path: instance, // if connecting to an instance instead of a port
RawQuery: query.Encode(),
}
return u.String()
}
// RespAsErrorByJSONRPC translate json rpc resty response to error
func RespAsErrorByJSONRPC(resp *resty.Response) error {
str := resp.String()
var result map[string]interface{}
MustUnmarshalString(str, &result)
if result["error"] != nil {
rerr := result["error"].(map[string]interface{})
if rerr["code"] == JrpcCodeFailure {
return fmt.Errorf("%s. %w", str, ErrFailure)
} else if rerr["code"] == JrpcCodeOngoing {
return ErrOngoing
}
return errors.New(resp.String())
}
return nil
}
// DeferDo a common defer do used in dtmcli/dtmgrpc
func DeferDo(rerr *error, success func() error, fail func() error) {
if x := recover(); x != nil {
*rerr = AsError(x)
_ = fail()
panic(x)
} else if *rerr != nil {
_ = fail()
} else {
*rerr = success()
}
}
// Escape solve CodeQL reported problem
func Escape(input string) string {
v := strings.Replace(input, "\n", "", -1)
v = strings.Replace(v, "\r", "", -1)
v = strings.Replace(v, ";", "", -1)
// v = strings.Replace(v, "'", "", -1)
return v
}
// EscapeGet escape get
func EscapeGet(qs url.Values, key string) string {
return Escape(qs.Get(key))
}
// InsertBarrier insert a record to barrier
func InsertBarrier(tx DB, transType string, gid string, branchID string, op string, barrierID string, reason string, dbType string, barrierTableName string) (int64, error) {
if op == "" {
return 0, nil
}
if dbType == "" {
dbType = currentDBType
}
if barrierTableName == "" {
barrierTableName = BarrierTableName
}
sql := GetDBSpecial(dbType).GetInsertIgnoreTemplate(barrierTableName+"(trans_type, gid, branch_id, op, barrier_id, reason) values(?,?,?,?,?,?)", "uniq_barrier")
return DBExec(dbType, tx, sql, transType, gid, branchID, op, barrierID, reason)
}
================================================
FILE: client/dtmcli/dtmimp/utils_test.go
================================================
/*
* 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 dtmimp
import (
"errors"
"os"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestEP(t *testing.T) {
skipped := true
err := func() (rerr error) {
defer P2E(&rerr)
E2P(errors.New("err1"))
skipped = false
return nil
}()
assert.Equal(t, true, skipped)
assert.Equal(t, "err1", err.Error())
err = CatchP(func() {
PanicIf(true, errors.New("err2"))
})
assert.Equal(t, "err2", err.Error())
err = func() (rerr error) {
defer P2E(&rerr)
panic("raw_string")
}()
assert.Equal(t, "raw_string", err.Error())
}
func TestTernary(t *testing.T) {
assert.Equal(t, "1", OrString("", "", "1"))
assert.Equal(t, "", OrString("", "", ""))
assert.Equal(t, "1", If(true, "1", "2"))
assert.Equal(t, "2", If(false, "1", "2"))
}
func TestMarshal(t *testing.T) {
a := 0
type e struct {
A int
}
e1 := e{A: 10}
m := map[string]int{}
assert.Equal(t, "1", MustMarshalString(1))
assert.Equal(t, []byte("1"), MustMarshal(1))
MustUnmarshal([]byte("2"), &a)
assert.Equal(t, 2, a)
MustUnmarshalString("3", &a)
assert.Equal(t, 3, a)
MustRemarshal(&e1, &m)
assert.Equal(t, 10, m["A"])
}
func TestSome(t *testing.T) {
n := MustAtoi("123")
assert.Equal(t, 123, n)
err := CatchP(func() {
MustAtoi("abc")
})
assert.Error(t, err)
func1 := GetFuncName()
assert.Equal(t, true, strings.HasSuffix(func1, "TestSome"))
os.Setenv("IS_DOCKER", "1")
s := MayReplaceLocalhost("http://localhost")
assert.Equal(t, "http://host.docker.internal", s)
os.Setenv("IS_DOCKER", "")
s2 := MayReplaceLocalhost("http://localhost")
assert.Equal(t, "http://localhost", s2)
}
================================================
FILE: client/dtmcli/dtmimp/vars.go
================================================
/*
* 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 dtmimp
import (
"errors"
"sync"
"time"
"github.com/dtm-labs/dtmdriver"
"github.com/dtm-labs/logger"
"github.com/go-resty/resty/v2"
)
// ErrFailure error of FAILURE
var ErrFailure = errors.New("FAILURE")
// ErrOngoing error of ONGOING
var ErrOngoing = errors.New("ONGOING")
// ErrDuplicated error of DUPLICATED for only msg
// if QueryPrepared executed before call. then DoAndSubmit return this error
var ErrDuplicated = errors.New("DUPLICATED")
// MapSuccess HTTP result of SUCCESS
var MapSuccess = map[string]interface{}{"dtm_result": ResultSuccess}
// MapFailure HTTP result of FAILURE
var MapFailure = map[string]interface{}{"dtm_result": ResultFailure}
// BarrierTableName the table name of barrier table
var BarrierTableName = "dtm_barrier.barrier"
var restyClients sync.Map
// GetRestyClient2 will return a resty client with timeout set
func GetRestyClient2(timeout time.Duration) *resty.Client {
cli, ok := restyClients.Load(timeout)
if !ok {
client := resty.New()
if timeout != 0 {
client.SetTimeout(timeout)
}
AddRestyMiddlewares(client)
restyClients.Store(timeout, client)
cli = client
}
return cli.(*resty.Client)
}
// AddRestyMiddlewares will add the middlewares used by dtm
func AddRestyMiddlewares(client *resty.Client) {
client.OnBeforeRequest(func(c *resty.Client, r *resty.Request) error {
old := r.URL
r.URL = MayReplaceLocalhost(r.URL)
ms := dtmdriver.Middlewares.HTTP
var err error
for i := 0; i < len(ms) && err == nil; i++ {
err = ms[i](c, r)
}
logger.Debugf("requesting: %s %s %s resolved: %s err: %v", r.Method, old, MustMarshalString(r.Body), r.URL, err)
return err
})
client.OnAfterResponse(func(c *resty.Client, resp *resty.Response) error {
r := resp.Request
logger.Debugf("requested: %d %s %s %s", resp.StatusCode(), r.Method, r.URL, resp.String())
return nil
})
}
================================================
FILE: client/dtmcli/logger/logger.go
================================================
package logger
import (
"github.com/dtm-labs/logger"
)
var (
// WithLogger replaces default logger
WithLogger = logger.WithLogger
// InitLog is an initialization for a logger
// level can be: debug info warn error
InitLog = logger.InitLog
// InitLog2 specify advanced log config
InitLog2 = logger.InitLog2
// Debugf log to level debug
Debugf = logger.Debugf
// Infof log to level info
Infof = logger.Infof
// Warnf log to level warn
Warnf = logger.Warnf
// Errorf log to level error
Errorf = logger.Errorf
// FatalfIf log to level error
FatalfIf = logger.FatalfIf
// FatalIfError if err is not nil, then log to level fatal and call os.Exit
FatalIfError = logger.FatalIfError
)
================================================
FILE: client/dtmcli/trans_msg.go
================================================
/*
* 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 dtmcli
import (
"database/sql"
"errors"
"fmt"
"github.com/dtm-labs/dtm/client/dtmcli/dtmimp"
)
// Msg reliable msg type
type Msg struct {
dtmimp.TransBase
delay uint64 // delay call branch, unit second
}
// NewMsg create new msg
func NewMsg(server string, gid string) *Msg {
return &Msg{TransBase: *dtmimp.NewTransBase(gid, "msg", server, "")}
}
// Add add a new step
func (s *Msg) Add(action string, postData interface{}) *Msg {
s.Steps = append(s.Steps, map[string]string{"action": action})
s.Payloads = append(s.Payloads, dtmimp.MustMarshalString(postData))
return s
}
// AddTopic add a new topic step
func (s *Msg) AddTopic(topic string, postData interface{}) *Msg {
return s.Add(fmt.Sprintf("%s%s", dtmimp.MsgTopicPrefix, topic), postData)
}
// SetDelay delay call branch, unit second
func (s *Msg) SetDelay(delay uint64) *Msg {
s.delay = delay
return s
}
// Prepare prepare the msg, msg will later be submitted
func (s *Msg) Prepare(queryPrepared string) error {
s.QueryPrepared = dtmimp.OrString(queryPrepared, s.QueryPrepared)
return dtmimp.TransCallDtm(&s.TransBase, "prepare")
}
// Submit submit the msg
func (s *Msg) Submit() error {
s.BuildCustomOptions()
return dtmimp.TransCallDtm(&s.TransBase, "submit")
}
// DoAndSubmitDB short method for Do on db type. please see DoAndSubmit
func (s *Msg) DoAndSubmitDB(queryPrepared string, db *sql.DB, busiCall BarrierBusiFunc) error {
return s.DoAndSubmit(queryPrepared, func(bb *BranchBarrier) error {
return bb.CallWithDB(db, busiCall)
})
}
// DoAndSubmit one method for the entire prepare->busi->submit
// the error returned by busiCall will be returned
// if busiCall return ErrFailure, then abort is called directly
// if busiCall return not nil error other than ErrFailure, then DoAndSubmit will call queryPrepared to get the result
func (s *Msg) DoAndSubmit(queryPrepared string, busiCall func(bb *BranchBarrier) error) error {
bb, err := BarrierFrom(s.TransType, s.Gid, dtmimp.MsgDoBranch0, dtmimp.MsgDoOp) // a special barrier for msg QueryPrepared
if err == nil {
err = s.Prepare(queryPrepared)
}
if err == nil {
errb := busiCall(bb)
if errb != nil && !errors.Is(errb, ErrFailure) {
// if busicall return an error other than failure, we will query the result
_, err = requestBranch(&s.TransBase, "GET", nil, bb.BranchID, bb.Op, queryPrepared)
}
if errors.Is(errb, ErrFailure) || errors.Is(err, ErrFailure) {
_ = dtmimp.TransCallDtm(&s.TransBase, "abort")
} else if err == nil {
err = s.Submit()
}
if errb != nil {
return errb
}
}
return err
}
// BuildCustomOptions add custom options to the request context
func (s *Msg) BuildCustomOptions() {
if s.delay > 0 {
s.CustomData = dtmimp.MustMarshalString(map[string]interface{}{"delay": s.delay})
}
}
================================================
FILE: client/dtmcli/trans_saga.go
================================================
/*
* 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 dtmcli
import (
"context"
"github.com/dtm-labs/dtm/client/dtmcli/dtmimp"
)
// Saga struct of saga
type Saga struct {
dtmimp.TransBase
orders map[int][]int
}
// NewSaga create a saga
func NewSaga(server string, gid string) *Saga {
return &Saga{TransBase: *dtmimp.NewTransBase(gid, "saga", server, ""), orders: map[int][]int{}}
}
// NewSagaWithContext create a saga with context
func NewSagaWithContext(ctx context.Context, server string, gid string) *Saga {
saga := NewSaga(server, gid)
saga.TransBase.Context = ctx
return saga
}
// Add add a saga step
func (s *Saga) Add(action string, compensate string, postData interface{}) *Saga {
s.Steps = append(s.Steps, map[string]string{"action": action, "compensate": compensate})
s.Payloads = append(s.Payloads, dtmimp.MustMarshalString(postData))
return s
}
// AddBranchOrder specify that branch should be after preBranches. branch should is larger than all the element in preBranches
func (s *Saga) AddBranchOrder(branch int, preBranches []int) *Saga {
s.orders[branch] = preBranches
return s
}
// SetConcurrent enable the concurrent exec of sub trans
func (s *Saga) SetConcurrent() *Saga {
s.Concurrent = true
return s
}
// Submit submit the saga trans
func (s *Saga) Submit() error {
s.BuildCustomOptions()
return dtmimp.TransCallDtm(&s.TransBase, "submit")
}
// BuildCustomOptions add custom options to the request context
func (s *Saga) BuildCustomOptions() {
if s.Concurrent {
s.CustomData = dtmimp.MustMarshalString(map[string]interface{}{"orders": s.orders, "concurrent": s.Concurrent})
}
}
================================================
FILE: client/dtmcli/trans_tcc.go
================================================
/*
* 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 dtmcli
import (
"fmt"
"net/url"
"github.com/dtm-labs/dtm/client/dtmcli/dtmimp"
"github.com/go-resty/resty/v2"
)
// Tcc struct of tcc
type Tcc struct {
dtmimp.TransBase
}
// TccGlobalFunc type of global tcc call
type TccGlobalFunc func(tcc *Tcc) (*resty.Response, error)
// TccGlobalTransaction begin a tcc global transaction
// dtm dtm server address
// gid global transaction ID
// tccFunc define the detail tcc busi
func TccGlobalTransaction(dtm string, gid string, tccFunc TccGlobalFunc) (rerr error) {
return TccGlobalTransaction2(dtm, gid, func(t *Tcc) {}, tccFunc)
}
// TccGlobalTransaction2 new version of TccGlobalTransaction, add custom param
func TccGlobalTransaction2(dtm string, gid string, custom func(*Tcc), tccFunc TccGlobalFunc) (rerr error) {
tcc := &Tcc{TransBase: *dtmimp.NewTransBase(gid, "tcc", dtm, "")}
custom(tcc)
rerr = dtmimp.TransCallDtm(&tcc.TransBase, "prepare")
if rerr != nil {
return rerr
}
defer dtmimp.DeferDo(&rerr, func() error {
return dtmimp.TransCallDtm(&tcc.TransBase, "submit")
}, func() error {
if rerr != nil {
tcc.RollbackReason = rerr.Error()
}
return dtmimp.TransCallDtm(&tcc.TransBase, "abort")
})
_, rerr = tccFunc(tcc)
return
}
// TccFromQuery tcc from request info
func TccFromQuery(qs url.Values) (*Tcc, error) {
tcc := &Tcc{TransBase: *dtmimp.TransBaseFromQuery(qs)}
if tcc.Dtm == "" || tcc.Gid == "" {
return nil, fmt.Errorf("bad tcc info. dtm: %s, gid: %s parentID: %s", tcc.Dtm, tcc.Gid, tcc.BranchID)
}
return tcc, nil
}
// CallBranch call a tcc branch
func (t *Tcc) CallBranch(body interface{}, tryURL string, confirmURL string, cancelURL string) (*resty.Response, error) {
branchID := t.NewSubBranchID()
err := dtmimp.TransRegisterBranch(&t.TransBase, map[string]string{
"data": dtmimp.MustMarshalString(body),
"branch_id": branchID,
dtmimp.OpConfirm: confirmURL,
dtmimp.OpCancel: cancelURL,
}, "registerBranch")
if err != nil {
return nil, err
}
return requestBranch(&t.TransBase, "POST", body, branchID, dtmimp.OpTry, tryURL)
}
================================================
FILE: client/dtmcli/types.go
================================================
/*
* 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 dtmcli
import (
"time"
"github.com/dtm-labs/dtm/client/dtmcli/dtmimp"
"github.com/go-resty/resty/v2"
)
// DB interface
type DB = dtmimp.DB
// TransOptions transaction option
type TransOptions = dtmimp.TransOptions
// DBConf declares db configuration
type DBConf = dtmimp.DBConf
// SetCurrentDBType set currentDBType
func SetCurrentDBType(dbType string) {
dtmimp.SetCurrentDBType(dbType)
}
// GetCurrentDBType get currentDBType
func GetCurrentDBType() string {
return dtmimp.GetCurrentDBType()
}
// SetBarrierTableName sets barrier table name
func SetBarrierTableName(tablename string) {
dtmimp.BarrierTableName = tablename
}
// GetRestyClient get the resty.Client for http request
func GetRestyClient() *resty.Client {
return dtmimp.GetRestyClient2(0)
}
// GetRestyClient2 get the resty.Client with the specified timeout set
func GetRestyClient2(timeout time.Duration) *resty.Client {
return dtmimp.GetRestyClient2(timeout)
}
================================================
FILE: client/dtmcli/types_test.go
================================================
/*
* 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 dtmcli
import (
"net/url"
"testing"
"github.com/dtm-labs/dtm/client/dtmcli/dtmimp"
"github.com/stretchr/testify/assert"
)
func TestTypes(t *testing.T) {
err := dtmimp.CatchP(func() {
MustGenGid("http://localhost:36789/api/no")
})
assert.Error(t, err)
assert.Error(t, err)
_, err = BarrierFromQuery(url.Values{})
assert.Error(t, err)
}
func TestXaSqlTimeout(t *testing.T) {
SetBarrierTableName(dtmimp.BarrierTableName) // just cover this func
}
================================================
FILE: client/dtmcli/utils.go
================================================
package dtmcli
import (
"errors"
"fmt"
"net/http"
"strings"
"github.com/dtm-labs/dtm/client/dtmcli/dtmimp"
"github.com/go-resty/resty/v2"
)
// MustGenGid generate a new gid
func MustGenGid(server string) string {
res := map[string]string{}
resp, err := GetRestyClient().R().SetResult(&res).Get(server + "/newGid")
if err != nil || res["gid"] == "" {
panic(fmt.Errorf("newGid error: %v, resp: %s", err, resp))
}
return res["gid"]
}
// ErrorMessage2Error return an error fmt.Errorf("%s %w", errMsg, err) but trim out duplicate wrap
// eg. ErrorMessage2Error("an error. FAILURE", ErrFailure) return an error with message: "an error. FAILURE",
// no additional " FAILURE" added
func ErrorMessage2Error(errMsg string, err error) error {
errMsg = strings.TrimSuffix(errMsg, " "+err.Error())
return fmt.Errorf("%s %w", errMsg, err)
}
// HTTPResp2DtmError translate a resty response to error
// compatible with version < v1.10
func HTTPResp2DtmError(resp *resty.Response) error {
code := resp.StatusCode()
str := resp.String()
if code == http.StatusTooEarly || strings.Contains(str, ResultOngoing) {
return ErrorMessage2Error(str, ErrOngoing)
} else if code == http.StatusConflict || strings.Contains(str, ResultFailure) {
return ErrorMessage2Error(str, ErrFailure)
} else if code != http.StatusOK {
return errors.New(str)
}
return nil
}
// Result2HttpJSON return the http code and json result
// if result is error, the return proper code, else return StatusOK
func Result2HttpJSON(result interface{}) (code int, res interface{}) {
err, _ := result.(error)
if err == nil {
code = http.StatusOK
res = result
} else {
res = map[string]string{
"error": err.Error(),
}
if errors.Is(err, ErrFailure) {
code = http.StatusConflict
} else if errors.Is(err, ErrOngoing) {
code = http.StatusTooEarly
} else if err != nil {
code = http.StatusInternalServerError
}
}
return
}
func requestBranch(t *dtmimp.TransBase, method string, body interface{}, branchID string, op string, url string) (*resty.Response, error) {
resp, err := dtmimp.TransRequestBranch(t, method, body, branchID, op, url)
if err == nil {
err = HTTPResp2DtmError(resp)
}
return resp, err
}
================================================
FILE: client/dtmcli/xa.go
================================================
/*
* 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 dtmcli
import (
"database/sql"
"fmt"
"net/url"
"github.com/dtm-labs/dtm/client/dtmcli/dtmimp"
"github.com/go-resty/resty/v2"
)
// XaGlobalFunc type of xa global function
type XaGlobalFunc func(xa *Xa) (*resty.Response, error)
// XaLocalFunc type of xa local function
type XaLocalFunc func(db *sql.DB, xa *Xa) error
// Xa xa transaction
type Xa struct {
dtmimp.TransBase
Phase2URL string
}
// XaFromQuery construct xa info from request
func XaFromQuery(qs url.Values) (*Xa, error) {
xa := &Xa{TransBase: *dtmimp.TransBaseFromQuery(qs)}
xa.Op = dtmimp.EscapeGet(qs, "op")
xa.Phase2URL = dtmimp.EscapeGet(qs, "phase2_url")
if xa.Gid == "" || xa.BranchID == "" || xa.Op == "" {
return nil, fmt.Errorf("bad xa info: gid: %s branchid: %s op: %s phase2_url: %s", xa.Gid, xa.BranchID, xa.Op, xa.Phase2URL)
}
return xa, nil
}
// XaLocalTransaction start a xa local transaction
func XaLocalTransaction(qs url.Values, dbConf DBConf, xaFunc XaLocalFunc) error {
xa, err := XaFromQuery(qs)
if err != nil {
return err
}
if xa.Op == dtmimp.OpCommit || xa.Op == dtmimp.OpRollback {
return dtmimp.XaHandlePhase2(xa.Gid, dbConf, xa.BranchID, xa.Op)
}
return dtmimp.XaHandleLocalTrans(&xa.TransBase, dbConf, func(db *sql.DB) error {
err := xaFunc(db, xa)
if err != nil {
return err
}
return dtmimp.TransRegisterBranch(&xa.TransBase, map[string]string{
"url": xa.Phase2URL,
"branch_id": xa.BranchID,
}, "registerBranch")
})
}
// XaGlobalTransaction start a xa global transaction
func XaGlobalTransaction(server string, gid string, xaFunc XaGlobalFunc) error {
return XaGlobalTransaction2(server, gid, func(x *Xa) {}, xaFunc)
}
// XaGlobalTransaction2 start a xa global transaction with xa custom function
func XaGlobalTransaction2(server string, gid string, custom func(*Xa), xaFunc XaGlobalFunc) (rerr error) {
xa := &Xa{TransBase: *dtmimp.NewTransBase(gid, "xa", server, "")}
custom(xa)
return dtmimp.XaHandleGlobalTrans(&xa.TransBase, func(action string) error {
return dtmimp.TransCallDtm(&xa.TransBase, action)
}, func() error {
_, rerr := xaFunc(xa)
return rerr
})
}
// CallBranch call a xa branch
func (x *Xa) CallBranch(body interface{}, url string) (*resty.Response, error) {
branchID := x.NewSubBranchID()
return requestBranch(&x.TransBase, "POST", body, branchID, dtmimp.OpAction, url)
}
================================================
FILE: client/dtmgrpc/barrier.go
================================================
/*
* 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 dtmgrpc
import (
"context"
"github.com/dtm-labs/dtm/client/dtmcli"
"github.com/dtm-labs/dtm/client/dtmgrpc/dtmgimp"
)
// BarrierFromGrpc generate a Barrier from grpc context
func BarrierFromGrpc(ctx context.Context) (*dtmcli.BranchBarrier, error) {
tb := dtmgimp.TransBaseFromGrpc(ctx)
return dtmcli.BarrierFrom(tb.TransType, tb.Gid, tb.BranchID, tb.Op)
}
================================================
FILE: client/dtmgrpc/dtmgimp/README-cn.md
================================================
## 注意
此包带imp后缀,主要被dtm内部使用,相关接口可能会发生变更,请勿使用这里的接口
================================================
FILE: client/dtmgrpc/dtmgimp/README.md
================================================
## Notice
Please donot use this package, and this package should only be used in dtm internally. The interfaces are not stable, and package name has postfix "imp"
================================================
FILE: client/dtmgrpc/dtmgimp/grpc_clients.go
================================================
/*
* 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 dtmgimp
import (
"fmt"
"os"
"sync"
"github.com/dtm-labs/dtm/client/dtmcli/dtmimp"
"github.com/dtm-labs/dtm/client/dtmgrpc/dtmgpb"
"github.com/dtm-labs/dtmdriver"
"github.com/dtm-labs/logger"
grpc "google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
type rawCodec struct{}
func (cb rawCodec) Marshal(v interface{}) ([]byte, error) {
return v.([]byte), nil
}
func (cb rawCodec) Unmarshal(data []byte, v interface{}) error {
ba, ok := v.(*[]byte)
dtmimp.PanicIf(!ok, fmt.Errorf("please pass in *[]byte"))
*ba = append(*ba, data...)
return nil
}
func (cb rawCodec) Name() string { return "dtm_raw" }
var normalClients, rawClients sync.Map
// ClientInterceptors declares grpc.UnaryClientInterceptors slice
var ClientInterceptors = []grpc.UnaryClientInterceptor{}
// GrpcServiceConfigGetter is a function to get gRPC service config, can be set by server config
var GrpcServiceConfigGetter func() string
// MustGetDtmClient 1
func MustGetDtmClient(grpcServer string) dtmgpb.DtmClient {
return dtmgpb.NewDtmClient(MustGetGrpcConn(grpcServer, false))
}
// GetGrpcConn 1
func GetGrpcConn(grpcServer string, isRaw bool) (conn *grpc.ClientConn, rerr error) {
clients := &normalClients
if isRaw {
clients = &rawClients
}
grpcServer = dtmimp.MayReplaceLocalhost(grpcServer)
v, ok := clients.Load(grpcServer)
if !ok {
opts := grpc.WithDefaultCallOptions()
if isRaw {
opts = grpc.WithDefaultCallOptions(grpc.ForceCodec(rawCodec{}))
}
logger.Debugf("grpc client connecting %s", grpcServer)
interceptors := append(ClientInterceptors, GrpcClientLog)
interceptors = append(interceptors, dtmdriver.Middlewares.Grpc...)
inOpt := grpc.WithChainUnaryInterceptor(interceptors...)
grpcServiceConfig, hasConfig := getGrpcServiceConfig()
dialOpts := []grpc.DialOption{inOpt, grpc.WithTransportCredentials(insecure.NewCredentials()), opts}
if hasConfig {
dialOpts = append(dialOpts, grpc.WithDefaultServiceConfig(grpcServiceConfig))
}
conn, rerr := grpc.Dial(grpcServer, dialOpts...)
if rerr == nil {
clients.Store(grpcServer, conn)
v = conn
logger.Debugf("grpc client inited for %s", grpcServer)
}
}
return v.(*grpc.ClientConn), rerr
}
// MustGetGrpcConn 1
func MustGetGrpcConn(grpcServer string, isRaw bool) *grpc.ClientConn {
conn, err := GetGrpcConn(grpcServer, isRaw)
dtmimp.E2P(err)
return conn
}
// getGrpcServiceConfig returns the gRPC service config from config getter or environment variable, and a bool indicating if config is set
func getGrpcServiceConfig() (string, bool) {
// First try to get from config getter (set by server)
if GrpcServiceConfigGetter != nil {
if config := GrpcServiceConfigGetter(); config != "" {
return config, true
}
}
// Fallback to environment variable
config := os.Getenv("GRPC_SERVICE_CONFIG")
if config != "" {
return config, true
}
// No config set
return "", false
}
================================================
FILE: client/dtmgrpc/dtmgimp/types.go
================================================
/*
* 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 dtmgimp
import (
"context"
"fmt"
"time"
"github.com/dtm-labs/dtm/client/dtmcli/dtmimp"
"github.com/dtm-labs/dtmdriver"
"github.com/dtm-labs/logger"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
)
// GrpcServerLog middleware to print server-side grpc log
func GrpcServerLog(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
began := time.Now()
logger.Debugf("grpc server handling: %s %s", info.FullMethod, dtmimp.MustMarshalString(req))
LogDtmCtx(ctx)
m, err := handler(ctx, req)
res := fmt.Sprintf("%2dms %v %s %s %s",
time.Since(began).Milliseconds(), err, info.FullMethod, dtmimp.MustMarshalString(m), dtmimp.MustMarshalString(req))
st, _ := status.FromError(err)
if err == nil || st != nil && st.Code() == codes.FailedPrecondition {
logger.Infof("%s", res)
} else {
logger.Errorf("%s", res)
}
return m, err
}
// GrpcClientLog middleware to print client-side grpc log
func GrpcClientLog(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
logger.Debugf("grpc client calling: %s%s %v", cc.Target(), method, dtmimp.MustMarshalString(req))
LogDtmCtx(ctx)
err := invoker(ctx, method, req, reply, cc, opts...)
res := fmt.Sprintf("grpc client called: %s%s %s result: %s err: %v",
cc.Target(), method, dtmimp.MustMarshalString(req), dtmimp.MustMarshalString(reply), err)
st, _ := status.FromError(err)
if err == nil || st != nil && st.Code() == codes.FailedPrecondition {
logger.Infof("%s", res)
} else {
logger.Errorf("%s", res)
}
return err
}
// InvokeBranch invoke a url for trans
func InvokeBranch(t *dtmimp.TransBase, isRaw bool, msg proto.Message, url string, reply interface{}, branchID string, op string, opts ...grpc.CallOption) error {
server, method, err := dtmdriver.GetDriver().ParseServerMethod(url)
if err != nil {
return err
}
ctx := TransInfo2Ctx(t.Context, t.Gid, t.TransType, branchID, op, t.Dtm)
ctx = metadata.AppendToOutgoingContext(ctx, Map2Kvs(t.BranchHeaders)...)
if t.TransType == "xa" { // xa branch need additional phase2_url
ctx = metadata.AppendToOutgoingContext(ctx, Map2Kvs(map[string]string{dtmpre + "phase2_url": url})...)
}
return MustGetGrpcConn(server, isRaw).Invoke(ctx, method, msg, reply, opts...)
}
================================================
FILE: client/dtmgrpc/dtmgimp/utils.go
================================================
/*
* 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 dtmgimp
import (
"context"
"github.com/dtm-labs/dtm/client/dtmcli/dtmimp"
"github.com/dtm-labs/dtm/client/dtmgrpc/dtmgpb"
"github.com/dtm-labs/logger"
"google.golang.org/grpc/metadata"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/emptypb"
)
// MustProtoMarshal must version of proto.Marshal
func MustProtoMarshal(msg proto.Message) []byte {
b, err := proto.Marshal(msg)
dtmimp.PanicIf(err != nil, err)
return b
}
// MustProtoUnmarshal must version of proto.Unmarshal
func MustProtoUnmarshal(data []byte, msg proto.Message) {
err := proto.Unmarshal(data, msg)
dtmimp.PanicIf(err != nil, err)
}
// GetDtmRequest return a DtmRequest from TransBase
func GetDtmRequest(s *dtmimp.TransBase) *dtmgpb.DtmRequest {
return &dtmgpb.DtmRequest{
Gid: s.Gid,
TransType: s.TransType,
TransOptions: &dtmgpb.DtmTransOptions{
WaitResult: s.WaitResult,
TimeoutToFail: s.TimeoutToFail,
RetryInterval: s.RetryInterval,
BranchHeaders: s.BranchHeaders,
RequestTimeout: s.RequestTimeout,
RetryLimit: s.RetryLimit,
},
QueryPrepared: s.QueryPrepared,
CustomedData: s.CustomData,
BinPayloads: s.BinPayloads,
Steps: dtmimp.MustMarshalString(s.Steps),
RollbackReason: s.RollbackReason,
}
}
// DtmGrpcCall make a convenient call to dtm
func DtmGrpcCall(s *dtmimp.TransBase, operation string) error {
reply := emptypb.Empty{}
return MustGetGrpcConn(s.Dtm, false).Invoke(s.Context, "/dtmgimp.Dtm/"+operation, GetDtmRequest(s), &reply)
}
const dtmpre string = "dtm-"
// TransInfo2Ctx add trans info to grpc context
func TransInfo2Ctx(ctx context.Context, gid, transType, branchID, op, dtm string) context.Context {
nctx := ctx
if ctx == nil {
nctx = context.Background()
}
return metadata.AppendToOutgoingContext(
nctx,
dtmpre+"gid", gid,
dtmpre+"trans_type", transType,
dtmpre+"branch_id", branchID,
dtmpre+"op", op,
dtmpre+"dtm", dtm,
)
}
// Map2Kvs map to metadata kv
func Map2Kvs(m map[string]string) []string {
kvs := make([]string, 0, len(m)*2)
for k, v := range m {
kvs = append(kvs, k, v)
}
return kvs
}
// LogDtmCtx logout dtm info in context metadata
func LogDtmCtx(ctx context.Context) {
tb := TransBaseFromGrpc(ctx)
if tb.Gid != "" {
logger.Debugf("gid: %s trans_type: %s branch_id: %s op: %s dtm: %s", tb.Gid, tb.TransType, tb.BranchID, tb.Op, tb.Dtm)
}
}
func dtmGet(md metadata.MD, key string) string {
return mdGet(md, dtmpre+key)
}
func mdGet(md metadata.MD, key string) string {
v := md.Get(key)
if len(v) == 0 {
return ""
}
return v[0]
}
// TransBaseFromGrpc get trans base info from a context metadata
func TransBaseFromGrpc(ctx context.Context) *dtmimp.TransBase {
md, _ := metadata.FromIncomingContext(ctx)
tb := dtmimp.NewTransBase(dtmGet(md, "gid"), dtmGet(md, "trans_type"), dtmGet(md, "dtm"), dtmGet(md, "branch_id"))
tb.Op = dtmGet(md, "op")
return tb
}
// GetMetaFromContext get header from context
func GetMetaFromContext(ctx context.Context, name string) string {
md, _ := metadata.FromIncomingContext(ctx)
return mdGet(md, name)
}
// GetDtmMetaFromContext get dtm header from context
func GetDtmMetaFromContext(ctx context.Context, name string) string {
md, _ := metadata.FromIncomingContext(ctx)
return dtmGet(md, name)
}
type requestTimeoutKey struct{}
// RequestTimeoutFromContext returns requestTime of transOption option
func RequestTimeoutFromContext(ctx context.Context) int64 {
if v, ok := ctx.Value(requestTimeoutKey{}).(int64); ok {
return v
}
return 0
}
// RequestTimeoutNewContext sets requestTimeout of transOption option to context
func RequestTimeoutNewContext(ctx context.Context, requestTimeout int64) context.Context {
return context.WithValue(ctx, requestTimeoutKey{}, requestTimeout)
}
================================================
FILE: client/dtmgrpc/dtmgpb/dtmgimp.pb.go
================================================
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc v3.21.12
// source: 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"`
// repeated string PassthroughHeaders = 4; // depreceated
BranchHeaders map[string]string `protobuf:"bytes,5,rep,name=BranchHeaders,proto3" json:"BranchHeaders,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
RequestTimeout int64 `protobuf:"varint,6,opt,name=RequestTimeout,proto3" json:"RequestTimeout,omitempty"`
RetryLimit int64 `protobuf:"varint,7,opt,name=RetryLimit,proto3" json:"RetryLimit,omitempty"`
}
func (x *DtmTransOptions) Reset() {
*x = DtmTransOptions{}
if protoimpl.UnsafeEnabled {
mi := &file_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_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_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) GetBranchHeaders() map[string]string {
if x != nil {
return x.BranchHeaders
}
return nil
}
func (x *DtmTransOptions) GetRequestTimeout() int64 {
if x != nil {
return x.RequestTimeout
}
return 0
}
func (x *DtmTransOptions) GetRetryLimit() int64 {
if x != nil {
return x.RetryLimit
}
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/Workflow 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"`
ReqExtra map[string]string `protobuf:"bytes,8,rep,name=ReqExtra,proto3" json:"ReqExtra,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
RollbackReason string `protobuf:"bytes,9,opt,name=RollbackReason,proto3" json:"RollbackReason,omitempty"`
}
func (x *DtmRequest) Reset() {
*x = DtmRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_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_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_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 ""
}
func (x *DtmRequest) GetReqExtra() map[string]string {
if x != nil {
return x.ReqExtra
}
return nil
}
func (x *DtmRequest) GetRollbackReason() string {
if x != nil {
return x.RollbackReason
}
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_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_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_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_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_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_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
}
type DtmProgressesReply struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Transaction *DtmTransaction `protobuf:"bytes,1,opt,name=Transaction,json=transaction,proto3" json:"Transaction,omitempty"`
Progresses []*DtmProgress `protobuf:"bytes,2,rep,name=Progresses,json=progresses,proto3" json:"Progresses,omitempty"`
}
func (x *DtmProgressesReply) Reset() {
*x = DtmProgressesReply{}
if protoimpl.UnsafeEnabled {
mi := &file_dtmgimp_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DtmProgressesReply) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DtmProgressesReply) ProtoMessage() {}
func (x *DtmProgressesReply) ProtoReflect() protoreflect.Message {
mi := &file_dtmgimp_proto_msgTypes[4]
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 DtmProgressesReply.ProtoReflect.Descriptor instead.
func (*DtmProgressesReply) Descriptor() ([]byte, []int) {
return file_dtmgimp_proto_rawDescGZIP(), []int{4}
}
func (x *DtmProgressesReply) GetTransaction() *DtmTransaction {
if x != nil {
return x.Transaction
}
return nil
}
func (x *DtmProgressesReply) GetProgresses() []*DtmProgress {
if x != nil {
return x.Progresses
}
return nil
}
type DtmTransaction struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Gid string `protobuf:"bytes,1,opt,name=Gid,json=gid,proto3" json:"Gid,omitempty"`
Status string `protobuf:"bytes,2,opt,name=Status,json=status,proto3" json:"Status,omitempty"`
RollbackReason string `protobuf:"bytes,3,opt,name=RollbackReason,json=rollback_reason,proto3" json:"RollbackReason,omitempty"`
Result string `protobuf:"bytes,4,opt,name=Result,json=result,proto3" json:"Result,omitempty"`
}
func (x *DtmTransaction) Reset() {
*x = DtmTransaction{}
if protoimpl.UnsafeEnabled {
mi := &file_dtmgimp_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DtmTransaction) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DtmTransaction) ProtoMessage() {}
func (x *DtmTransaction) ProtoReflect() protoreflect.Message {
mi := &file_dtmgimp_proto_msgTypes[5]
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 DtmTransaction.ProtoReflect.Descriptor instead.
func (*DtmTransaction) Descriptor() ([]byte, []int) {
return file_dtmgimp_proto_rawDescGZIP(), []int{5}
}
func (x *DtmTransaction) GetGid() string {
if x != nil {
return x.Gid
}
return ""
}
func (x *DtmTransaction) GetStatus() string {
if x != nil {
return x.Status
}
return ""
}
func (x *DtmTransaction) GetRollbackReason() string {
if x != nil {
return x.RollbackReason
}
return ""
}
func (x *DtmTransaction) GetResult() string {
if x != nil {
return x.Result
}
return ""
}
type DtmProgress struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Status string `protobuf:"bytes,1,opt,name=Status,json=status,proto3" json:"Status,omitempty"`
BinData []byte `protobuf:"bytes,2,opt,name=BinData,json=bin_data,proto3" json:"BinData,omitempty"`
BranchID string `protobuf:"bytes,3,opt,name=BranchID,json=branch_id,proto3" json:"BranchID,omitempty"`
Op string `protobuf:"bytes,4,opt,name=Op,json=op,proto3" json:"Op,omitempty"`
}
func (x *DtmProgress) Reset() {
*x = DtmProgress{}
if protoimpl.UnsafeEnabled {
mi := &file_dtmgimp_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DtmProgress) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DtmProgress) ProtoMessage() {}
func (x *DtmProgress) ProtoReflect() protoreflect.Message {
mi := &file_dtmgimp_proto_msgTypes[6]
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 DtmProgress.ProtoReflect.Descriptor instead.
func (*DtmProgress) Descriptor() ([]byte, []int) {
return file_dtmgimp_proto_rawDescGZIP(), []int{6}
}
func (x *DtmProgress) GetStatus() string {
if x != nil {
return x.Status
}
return ""
}
func (x *DtmProgress) GetBinData() []byte {
if x != nil {
return x.BinData
}
return nil
}
func (x *DtmProgress) GetBranchID() string {
if x != nil {
return x.BranchID
}
return ""
}
func (x *DtmProgress) GetOp() string {
if x != nil {
return x.Op
}
return ""
}
type DtmTopicRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Topic string `protobuf:"bytes,1,opt,name=Topic,proto3" json:"Topic,omitempty"`
URL string `protobuf:"bytes,2,opt,name=URL,proto3" json:"URL,omitempty"`
Remark string `protobuf:"bytes,3,opt,name=Remark,proto3" json:"Remark,omitempty"`
}
func (x *DtmTopicRequest) Reset() {
*x = DtmTopicRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_dtmgimp_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DtmTopicRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DtmTopicRequest) ProtoMessage() {}
func (x *DtmTopicRequest) ProtoReflect() protoreflect.Message {
mi := &file_dtmgimp_proto_msgTypes[7]
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 DtmTopicRequest.ProtoReflect.Descriptor instead.
func (*DtmTopicRequest) Descriptor() ([]byte, []int) {
return file_dtmgimp_proto_rawDescGZIP(), []int{7}
}
func (x *DtmTopicRequest) GetTopic() string {
if x != nil {
return x.Topic
}
return ""
}
func (x *DtmTopicRequest) GetURL() string {
if x != nil {
return x.URL
}
return ""
}
func (x *DtmTopicRequest) GetRemark() string {
if x != nil {
return x.Remark
}
return ""
}
var File_dtmgimp_proto protoreflect.FileDescriptor
var file_dtmgimp_proto_rawDesc = []byte{
0x0a, 0x0d, 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, 0xda, 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, 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, 0x12, 0x26, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03,
0x52, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
0x12, 0x1e, 0x0a, 0x0a, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x07,
0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4c, 0x69, 0x6d, 0x69, 0x74,
0x1a, 0x40, 0x0a, 0x12, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72,
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
0x38, 0x01, 0x22, 0xa0, 0x03, 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, 0x12, 0x3d, 0x0a, 0x08, 0x52, 0x65, 0x71, 0x45, 0x78, 0x74, 0x72, 0x61, 0x18, 0x08, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74,
0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x45, 0x78, 0x74, 0x72,
0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x52, 0x65, 0x71, 0x45, 0x78, 0x74, 0x72, 0x61,
0x12, 0x26, 0x0a, 0x0e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x61, 0x73,
0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61,
0x63, 0x6b, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x1a, 0x3b, 0x0a, 0x0d, 0x52, 0x65, 0x71, 0x45,
0x78, 0x74, 0x72, 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, 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, 0x22, 0x85, 0x01, 0x0a, 0x12,
0x44, 0x74, 0x6d, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x70,
0x6c, 0x79, 0x12, 0x39, 0x0a, 0x0b, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d,
0x70, 0x2e, 0x44, 0x74, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a,
0x0a, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x14, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x50,
0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73,
0x73, 0x65, 0x73, 0x22, 0x7b, 0x0a, 0x0e, 0x44, 0x74, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x47, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x03, 0x67, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75,
0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12,
0x27, 0x0a, 0x0e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x61, 0x73, 0x6f,
0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63,
0x6b, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75,
0x6c, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74,
0x22, 0x6d, 0x0a, 0x0b, 0x44, 0x74, 0x6d, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12,
0x16, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x0a, 0x07, 0x42, 0x69, 0x6e, 0x44, 0x61,
0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x62, 0x69, 0x6e, 0x5f, 0x64, 0x61,
0x74, 0x61, 0x12, 0x1b, 0x0a, 0x08, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x49, 0x44, 0x18, 0x03,
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x69, 0x64, 0x12,
0x0e, 0x0a, 0x02, 0x4f, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x6f, 0x70, 0x22,
0x51, 0x0a, 0x0f, 0x44, 0x74, 0x6d, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x05, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x52, 0x4c, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x52, 0x4c, 0x12, 0x16, 0x0a, 0x06, 0x52, 0x65,
0x6d, 0x61, 0x72, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x52, 0x65, 0x6d, 0x61,
0x72, 0x6b, 0x32, 0xbf, 0x04, 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, 0x12, 0x45, 0x0a, 0x0f, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72,
0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x13, 0x2e, 0x64, 0x74, 0x6d, 0x67,
0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b,
0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x50, 0x72, 0x6f, 0x67,
0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3f, 0x0a,
0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x18, 0x2e, 0x64, 0x74, 0x6d,
0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x54, 0x6f, 0x70, 0x69, 0x63, 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, 0x41,
0x0a, 0x0b, 0x55, 0x6e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x18, 0x2e,
0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x54, 0x6f, 0x70, 0x69, 0x63,
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, 0x41, 0x0a, 0x0b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x6f, 0x70, 0x69, 0x63,
0x12, 0x18, 0x2e, 0x64, 0x74, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x44, 0x74, 0x6d, 0x54, 0x6f,
0x70, 0x69, 0x63, 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_dtmgimp_proto_rawDescOnce sync.Once
file_dtmgimp_proto_rawDescData = file_dtmgimp_proto_rawDesc
)
func file_dtmgimp_proto_rawDescGZIP() []byte {
file_dtmgimp_proto_rawDescOnce.Do(func() {
file_dtmgimp_proto_rawDescData = protoimpl.X.CompressGZIP(file_dtmgimp_proto_rawDescData)
})
return file_dtmgimp_proto_rawDescData
}
var file_dtmgimp_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_dtmgimp_proto_goTypes = []interface{}{
(*DtmTransOptions)(nil), // 0: dtmgimp.DtmTransOptions
(*DtmRequest)(nil), // 1: dtmgimp.DtmRequest
(*DtmGidReply)(nil), // 2: dtmgimp.DtmGidReply
(*DtmBranchRequest)(nil), // 3: dtmgimp.DtmBranchRequest
(*DtmProgressesReply)(nil), // 4: dtmgimp.DtmProgressesReply
(*DtmTransaction)(nil), // 5: dtmgimp.DtmTransaction
(*DtmProgress)(nil), // 6: dtmgimp.DtmProgress
(*DtmTopicRequest)(nil), // 7: dtmgimp.DtmTopicRequest
nil, // 8: dtmgimp.DtmTransOptions.BranchHeadersEntry
nil, // 9: dtmgimp.DtmRequest.ReqExtraEntry
nil, // 10: dtmgimp.DtmBranchRequest.DataEntry
(*emptypb.Empty)(nil), // 11: google.protobuf.Empty
}
var file_dtmgimp_proto_depIdxs = []int32{
8, // 0: dtmgimp.DtmTransOptions.BranchHeaders:type_name -> dtmgimp.DtmTransOptions.BranchHeadersEntry
0, // 1: dtmgimp.DtmRequest.TransOptions:type_name -> dtmgimp.DtmTransOptions
9, // 2: dtmgimp.DtmRequest.ReqExtra:type_name -> dtmgimp.DtmRequest.ReqExtraEntry
10, // 3: dtmgimp.DtmBranchRequest.Data:type_name -> dtmgimp.DtmBranchRequest.DataEntry
5, // 4: dtmgimp.DtmProgressesReply.Transaction:type_name -> dtmgimp.DtmTransaction
6, // 5: dtmgimp.DtmProgressesReply.Progresses:type_name -> dtmgimp.DtmProgress
11, // 6: dtmgimp.Dtm.NewGid:input_type -> google.protobuf.Empty
1, // 7: dtmgimp.Dtm.Submit:input_type -> dtmgimp.DtmRequest
1, // 8: dtmgimp.Dtm.Prepare:input_type -> dtmgimp.DtmRequest
1, // 9: dtmgimp.Dtm.Abort:input_type -> dtmgimp.DtmRequest
3, // 10: dtmgimp.Dtm.RegisterBranch:input_type -> dtmgimp.DtmBranchRequest
1, // 11: dtmgimp.Dtm.PrepareWorkflow:input_type -> dtmgimp.DtmRequest
7, // 12: dtmgimp.Dtm.Subscribe:input_type -> dtmgimp.DtmTopicRequest
7, // 13: dtmgimp.Dtm.Unsubscribe:input_type -> dtmgimp.DtmTopicRequest
7, // 14: dtmgimp.Dtm.DeleteTopic:input_type -> dtmgimp.DtmTopicRequest
2, // 15: dtmgimp.Dtm.NewGid:output_type -> dtmgimp.DtmGidReply
11, // 16: dtmgimp.Dtm.Submit:output_type -> google.protobuf.Empty
11, // 17: dtmgimp.Dtm.Prepare:output_type -> google.protobuf.Empty
11, // 18: dtmgimp.Dtm.Abort:output_type -> google.protobuf.Empty
11, // 19: dtmgimp.Dtm.RegisterBranch:output_type -> google.protobuf.Empty
4, // 20: dtmgimp.Dtm.PrepareWorkflow:output_type -> dtmgimp.DtmProgressesReply
11, // 21: dtmgimp.Dtm.Subscribe:output_type -> google.protobuf.Empty
11, // 22: dtmgimp.Dtm.Unsubscribe:output_type -> google.protobuf.Empty
11, // 23: dtmgimp.Dtm.DeleteTopic:output_type -> google.protobuf.Empty
15, // [15:24] is the sub-list for method output_type
6, // [6:15] is the sub-list for method input_type
6, // [6:6] is the sub-list for extension type_name
6, // [6:6] is the sub-list for extension extendee
0, // [0:6] is the sub-list for field type_name
}
func init() { file_dtmgimp_proto_init() }
func file_dtmgimp_proto_init() {
if File_dtmgimp_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_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_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_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_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
}
}
file_dtmgimp_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DtmProgressesReply); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_dtmgimp_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DtmTransaction); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_dtmgimp_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DtmProgress); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_dtmgimp_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DtmTopicRequest); 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_dtmgimp_proto_rawDesc,
NumEnums: 0,
NumMessages: 11,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_dtmgimp_proto_goTypes,
DependencyIndexes: file_dtmgimp_proto_depIdxs,
MessageInfos: file_dtmgimp_proto_msgTypes,
}.Build()
File_dtmgimp_proto = out.File
file_dtmgimp_proto_rawDesc = nil
file_dtmgimp_proto_goTypes = nil
file_dtmgimp_proto_depIdxs = nil
}
================================================
FILE: client/dtmgrpc/dtmgpb/dtmgimp.proto
================================================
syntax = "proto3";
option go_package = "./dtmgpb";
import "google/protobuf/empty.proto";
package dtmgimp;
// The dtm service definition.
service Dtm {
rpc NewGid(google.protobuf.Empty) returns (DtmGidReply) {}
rpc Submit(DtmRequest) returns (google.protobuf.Empty) {}
rpc Prepare(DtmRequest) returns (google.protobuf.Empty) {}
rpc Abort(DtmRequest) returns (google.protobuf.Empty) {}
rpc RegisterBranch(DtmBranchRequest) returns (google.protobuf.Empty) {}
rpc PrepareWorkflow(DtmRequest) returns (DtmProgressesReply) {}
rpc Subscribe(DtmTopicRequest) returns (google.protobuf.Empty){}
rpc Unsubscribe(DtmTopicRequest) returns (google.protobuf.Empty){}
rpc DeleteTopic(DtmTopicRequest) returns (google.protobuf.Empty){}
}
message DtmTransOptions {
bool WaitResult = 1;
int64 TimeoutToFail = 2;
int64 RetryInterval = 3;
// repeated string PassthroughHeaders = 4; // depreceated
map<string, string> BranchHeaders = 5;
int64 RequestTimeout = 6;
int64 RetryLimit = 7;
}
// DtmRequest request sent to dtm server
message DtmRequest {
string Gid = 1;
string TransType = 2;
DtmTransOptions TransOptions = 3;
string CustomedData = 4;
repeated bytes BinPayloads = 5; // for Msg/Saga/Workflow branch payloads
string QueryPrepared = 6; // for Msg
string Steps = 7;
map<string, string> ReqExtra = 8;
string RollbackReason = 9;
}
message DtmGidReply {
string Gid = 1;
}
message DtmBranchRequest {
string Gid = 1;
string TransType = 2;
string BranchID = 3;
string Op = 4;
map<string, string> Data = 5;
bytes BusiPayload = 6;
}
message DtmProgressesReply {
DtmTransaction Transaction = 1 [json_name="transaction"];
repeated DtmProgress Progresses = 2 [json_name="progresses"];
}
message DtmTransaction {
string Gid = 1 [json_name="gid"];
string Status = 2 [json_name="status"];
string RollbackReason = 3 [json_name="rollback_reason"];
string Result = 4 [json_name="result"];
}
message DtmProgress {
string Status = 1 [json_name="status"];
bytes BinData = 2 [json_name="bin_data"];
string BranchID = 3 [json_name="branch_id"];
string Op = 4 [json_name="op"];
}
message DtmTopicRequest {
string Topic = 1;
string URL = 2;
string Remark = 3;
}
================================================
FILE: client/dtmgrpc/dtmgpb/dtmgimp_grpc.pb.go
================================================
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.2.0
// - protoc v3.21.12
// source: dtmgimp.proto
package dtmgpb
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
emptypb "google.golang.org/protobuf/types/known/emptypb"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// DtmClient is the client API for Dtm service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type DtmClient interface {
NewGid(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*DtmGidReply, error)
Submit(ctx context.Context, in *DtmRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
Prepare(ctx context.Context, in *DtmRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
Abort(ctx context.Context, in *DtmRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
RegisterBranch(ctx context.Context, in *DtmBranchRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
PrepareWorkflow(ctx context.Context, in *DtmRequest, opts ...grpc.CallOption) (*DtmProgressesReply, error)
Su
gitextract_qlsxhq70/
├── .github/
│ └── workflows/
│ ├── codeql-analysis.yml
│ ├── docker.yml
│ ├── release.yml
│ └── tests.yml
├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── admin/
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── README.md
│ ├── index.html
│ ├── package.json
│ ├── postcss.config.js
│ ├── src/
│ │ ├── App.vue
│ │ ├── api/
│ │ │ └── api_dtm.ts
│ │ ├── assets/
│ │ │ └── css/
│ │ │ └── index.css
│ │ ├── components/
│ │ │ ├── Screenfull/
│ │ │ │ └── index.vue
│ │ │ └── SvgIcon/
│ │ │ └── index.vue
│ │ ├── components.d.ts
│ │ ├── icons/
│ │ │ └── readme.md
│ │ ├── layout/
│ │ │ ├── aside.vue
│ │ │ ├── components/
│ │ │ │ ├── content.vue
│ │ │ │ ├── header.vue
│ │ │ │ └── sidebar.vue
│ │ │ └── index.vue
│ │ ├── main.ts
│ │ ├── permission.ts
│ │ ├── router/
│ │ │ ├── asyncRouter.ts
│ │ │ └── index.ts
│ │ ├── store/
│ │ │ ├── index.ts
│ │ │ └── modules/
│ │ │ └── layout.ts
│ │ ├── type/
│ │ │ ├── index.d.ts
│ │ │ ├── shim.vue.d.ts
│ │ │ └── store/
│ │ │ └── layout.ts
│ │ ├── utils/
│ │ │ ├── request.ts
│ │ │ └── util.ts
│ │ └── views/
│ │ └── Dashboard/
│ │ ├── GlobalTransactions/
│ │ │ ├── AllTransactions.vue
│ │ │ ├── DialogTransactionDetail.vue
│ │ │ └── UnfinishedTransactions.vue
│ │ ├── KVPairs/
│ │ │ ├── Topics.vue
│ │ │ └── _Components/
│ │ │ ├── DialogTopicDetail.vue
│ │ │ └── DialogTopicSubscribe.vue
│ │ └── Nodes/
│ │ └── LivingNodes.vue
│ ├── tailwind.config.js
│ ├── tsconfig.json
│ └── vite.config.ts
├── charts/
│ ├── .helmignore
│ ├── Chart.yaml
│ ├── README.md
│ ├── templates/
│ │ ├── NOTES.txt
│ │ ├── _helpers.tpl
│ │ ├── configmap.yaml
│ │ ├── deployment.yaml
│ │ ├── hpa.yaml
│ │ ├── ingress.yaml
│ │ ├── service.yaml
│ │ └── tests/
│ │ └── test-connection.yaml
│ └── values.yaml
├── client/
│ ├── README.md
│ ├── dtmcli/
│ │ ├── barrier.go
│ │ ├── barrier_mongo.go
│ │ ├── barrier_redis.go
│ │ ├── consts.go
│ │ ├── cover_test.go
│ │ ├── dtmimp/
│ │ │ ├── README-cn.md
│ │ │ ├── README.md
│ │ │ ├── consts.go
│ │ │ ├── db_special.go
│ │ │ ├── db_special_test.go
│ │ │ ├── trans_base.go
│ │ │ ├── trans_xa_base.go
│ │ │ ├── types.go
│ │ │ ├── types_test.go
│ │ │ ├── utils.go
│ │ │ ├── utils_test.go
│ │ │ └── vars.go
│ │ ├── logger/
│ │ │ └── logger.go
│ │ ├── trans_msg.go
│ │ ├── trans_saga.go
│ │ ├── trans_tcc.go
│ │ ├── types.go
│ │ ├── types_test.go
│ │ ├── utils.go
│ │ └── xa.go
│ ├── dtmgrpc/
│ │ ├── barrier.go
│ │ ├── dtmgimp/
│ │ │ ├── README-cn.md
│ │ │ ├── README.md
│ │ │ ├── grpc_clients.go
│ │ │ ├── types.go
│ │ │ └── utils.go
│ │ ├── dtmgpb/
│ │ │ ├── dtmgimp.pb.go
│ │ │ ├── dtmgimp.proto
│ │ │ └── dtmgimp_grpc.pb.go
│ │ ├── msg.go
│ │ ├── options.go
│ │ ├── options_test.go
│ │ ├── saga.go
│ │ ├── tcc.go
│ │ ├── type.go
│ │ ├── type_test.go
│ │ └── xa.go
│ └── workflow/
│ ├── dummyReadCloser.go
│ ├── factory.go
│ ├── imp.go
│ ├── rpc.go
│ ├── server.go
│ ├── utils.go
│ ├── wfpb/
│ │ ├── wf.pb.go
│ │ ├── wf.proto
│ │ └── wf_grpc.pb.go
│ ├── workflow.go
│ └── workflow_test.go
├── conf.sample.yml
├── dtmsvr/
│ ├── api.go
│ ├── api_grpc.go
│ ├── api_http.go
│ ├── api_json_rpc.go
│ ├── config/
│ │ ├── config.go
│ │ ├── config_test.go
│ │ └── config_utils.go
│ ├── cron.go
│ ├── entry/
│ │ └── main.go
│ ├── metrics.go
│ ├── microservices/
│ │ └── drivers.go
│ ├── storage/
│ │ ├── boltdb/
│ │ │ ├── boltdb.go
│ │ │ └── boltdb_test.go
│ │ ├── redis/
│ │ │ └── redis.go
│ │ ├── registry/
│ │ │ ├── factory.go
│ │ │ └── registry.go
│ │ ├── sql/
│ │ │ └── sql.go
│ │ ├── store.go
│ │ └── trans.go
│ ├── svr.go
│ ├── topics.go
│ ├── trans_class.go
│ ├── trans_process.go
│ ├── trans_status.go
│ ├── trans_type_msg.go
│ ├── trans_type_saga.go
│ ├── trans_type_tcc.go
│ ├── trans_type_workflow.go
│ ├── trans_type_xa.go
│ ├── utils.go
│ └── utils_test.go
├── dtmutil/
│ ├── consts.go
│ ├── db.go
│ ├── utils.go
│ └── utils_test.go
├── go.mod
├── go.sum
├── helper/
│ ├── .goreleaser.yml
│ ├── Dockerfile-release
│ ├── README-cn.md
│ ├── README-en.md
│ ├── bench/
│ │ ├── Makefile
│ │ ├── main.go
│ │ ├── prepare.sh
│ │ ├── setup-redis6.sh
│ │ ├── setup.sh
│ │ ├── svr/
│ │ │ └── http.go
│ │ ├── test-boltdb.sh
│ │ ├── test-flash-sales.sh
│ │ ├── test-mysql.sh
│ │ └── test-redis.sh
│ ├── compose.store.yml
│ ├── golint.sh
│ ├── sync-client.sh
│ └── test-cover.sh
├── main.go
├── qs/
│ └── main.go
├── revive.toml
├── sqls/
│ ├── busi.mongo.js
│ ├── busi.mysql.sql
│ ├── busi.postgres.sql
│ ├── dtmcli.barrier.mongo.js
│ ├── dtmcli.barrier.mysql.sql
│ ├── dtmcli.barrier.postgres.sql
│ ├── dtmsvr.storage.mysql.sql
│ ├── dtmsvr.storage.postgres.sql
│ ├── dtmsvr.storage.sqlserver.sql
│ └── dtmsvr.storage.tdsql.sql
└── test/
├── api_test.go
├── base_test.go
├── busi/
│ ├── barrier.go
│ ├── base_grpc.go
│ ├── base_http.go
│ ├── base_jrpc.go
│ ├── base_types.go
│ ├── busi.pb.go
│ ├── busi.proto
│ ├── busi_grpc.pb.go
│ ├── data.go
│ ├── quick_start.go
│ ├── startup.go
│ └── utils.go
├── common_test.go
├── dtmsvr_test.go
├── main_test.go
├── msg_barrier_mongo_test.go
├── msg_barrier_redis_test.go
├── msg_barrier_test.go
├── msg_delay_test.go
├── msg_grpc_barrier_redis_test.go
├── msg_grpc_barrier_test.go
├── msg_grpc_test.go
├── msg_jrpc_test.go
├── msg_options_test.go
├── msg_test.go
├── msg_webhook_test.go
├── saga_barrier_mongo_test.go
├── saga_barrier_redis_test.go
├── saga_barrier_test.go
├── saga_compatible_test.go
├── saga_concurrent_test.go
├── saga_grpc_barrier_test.go
├── saga_grpc_test.go
├── saga_options_test.go
├── saga_test.go
├── store_test.go
├── tcc_barrier_test.go
├── tcc_cover_test.go
├── tcc_grpc_cover_test.go
├── tcc_grpc_test.go
├── tcc_jrpc_test.go
├── tcc_old_test.go
├── tcc_test.go
├── topic_test.go
├── types.go
├── workflow_base_test.go
├── workflow_grpc_test.go
├── workflow_http_ret_test.go
├── workflow_http_test.go
├── workflow_interceptor_test.go
├── workflow_ongoing_test.go
├── workflow_xa_test.go
├── xa_cover_test.go
├── xa_grpc_test.go
└── xa_test.go
SYMBOL INDEX (1235 symbols across 155 files)
FILE: admin/src/api/api_dtm.ts
type IListAllTransactionsReq (line 4) | interface IListAllTransactionsReq {
type IListAllKVReq (line 10) | interface IListAllKVReq {
function listAllTransactions (line 16) | function listAllTransactions<T>(
function forceStopTransaction (line 26) | function forceStopTransaction(gid: string): Promise<AxiosResponse> {
function queryKVPair (line 34) | function queryKVPair<T>(payload: {
function listKVPairs (line 45) | function listKVPairs<T>(
function deleteTopic (line 55) | function deleteTopic<T>(topicName: string): Promise<AxiosResponse<T>> {
function subscribe (line 62) | function subscribe<T>(payload: {
function unsubscribe (line 74) | function unsubscribe(payload: {
function getTransaction (line 85) | function getTransaction<T>(payload: {
function resetNextCronTime (line 95) | function resetNextCronTime(gid: string): Promise<AxiosResponse> {
function getDtmVersion (line 103) | function getDtmVersion(): Promise<AxiosResponse<any>> {
FILE: admin/src/components.d.ts
type GlobalComponents (line 9) | interface GlobalComponents {
FILE: admin/src/main.ts
function showAlert (line 27) | function showAlert(msg: string) {
FILE: admin/src/store/modules/layout.ts
method getMenubar (line 19) | getMenubar(): IMenubar {
method getStatus (line 22) | getStatus(): IStatus {
method setRoutes (line 27) | setRoutes(data: Array<IMenubarList>): void {
method setGlobalError (line 30) | setGlobalError(err: string) {
method concatAllowRoutes (line 33) | concatAllowRoutes(): void {
method loadDtmVersion (line 36) | async loadDtmVersion(): Promise<void> {
FILE: admin/src/type/index.d.ts
type IObject (line 3) | interface IObject<T> {
type ImportMetaEnv (line 6) | interface ImportMetaEnv {
type ITable (line 12) | interface ITable<T = any> {
type Window (line 17) | interface Window {
FILE: admin/src/type/store/layout.ts
type IMenubar (line 1) | interface IMenubar {
type ILayout (line 5) | interface ILayout {
type IStatus (line 12) | interface IStatus {
type IMenubarList (line 16) | interface IMenubarList {
FILE: admin/vite.config.ts
method renderBuiltUrl (line 37) | renderBuiltUrl(
FILE: client/dtmcli/barrier.go
type BarrierBusiFunc (line 19) | type BarrierBusiFunc
type BranchBarrier (line 22) | type BranchBarrier struct
method String (line 32) | func (bb *BranchBarrier) String() string {
method newBarrierID (line 36) | func (bb *BranchBarrier) newBarrierID() string {
method Call (line 63) | func (bb *BranchBarrier) Call(tx *sql.Tx, busiCall BarrierBusiFunc) (r...
method CallWithDB (line 99) | func (bb *BranchBarrier) CallWithDB(db *sql.DB, busiCall BarrierBusiFu...
method QueryPrepared (line 108) | func (bb *BranchBarrier) QueryPrepared(db *sql.DB) error {
function BarrierFromQuery (line 42) | func BarrierFromQuery(qs url.Values) (*BranchBarrier, error) {
function BarrierFrom (line 47) | func BarrierFrom(transType, gid, branchID, op string) (*BranchBarrier, e...
FILE: client/dtmcli/barrier_mongo.go
method MongoCall (line 15) | func (bb *BranchBarrier) MongoCall(mc *mongo.Client, busiCall func(mongo...
method MongoQueryPrepared (line 56) | func (bb *BranchBarrier) MongoQueryPrepared(mc *mongo.Client) error {
function mongoInsertBarrier (line 79) | func mongoInsertBarrier(sc context.Context, mc *mongo.Client, transType ...
FILE: client/dtmcli/barrier_redis.go
method RedisCheckAdjustAmount (line 13) | func (bb *BranchBarrier) RedisCheckAdjustAmount(rd redis.Cmdable, key st...
method RedisQueryPrepared (line 58) | func (bb *BranchBarrier) RedisQueryPrepared(rd redis.Cmdable, barrierExp...
FILE: client/dtmcli/consts.go
constant StatusPrepared (line 16) | StatusPrepared = "prepared"
constant StatusSubmitted (line 18) | StatusSubmitted = "submitted"
constant StatusSucceed (line 20) | StatusSucceed = "succeed"
constant StatusFailed (line 23) | StatusFailed = "failed"
constant StatusAborting (line 25) | StatusAborting = "aborting"
constant ResultSuccess (line 28) | ResultSuccess = dtmimp.ResultSuccess
constant ResultFailure (line 30) | ResultFailure = dtmimp.ResultFailure
constant ResultOngoing (line 32) | ResultOngoing = dtmimp.ResultOngoing
constant DBTypeMysql (line 35) | DBTypeMysql = dtmimp.DBTypeMysql
constant DBTypePostgres (line 37) | DBTypePostgres = dtmimp.DBTypePostgres
constant DBTypeSQLServer (line 39) | DBTypeSQLServer = dtmimp.DBTypeSQLServer
FILE: client/dtmcli/cover_test.go
function TestQuery (line 16) | func TestQuery(t *testing.T) {
FILE: client/dtmcli/dtmimp/consts.go
constant ResultFailure (line 12) | ResultFailure = "FAILURE"
constant ResultSuccess (line 15) | ResultSuccess = "SUCCESS"
constant ResultOngoing (line 18) | ResultOngoing = "ONGOING"
constant OpTry (line 21) | OpTry = "try"
constant OpConfirm (line 23) | OpConfirm = "confirm"
constant OpCancel (line 25) | OpCancel = "cancel"
constant OpAction (line 27) | OpAction = "action"
constant OpCompensate (line 29) | OpCompensate = "compensate"
constant OpCommit (line 31) | OpCommit = "commit"
constant OpRollback (line 33) | OpRollback = "rollback"
constant DBTypeMysql (line 36) | DBTypeMysql = "mysql"
constant DBTypePostgres (line 38) | DBTypePostgres = "postgres"
constant DBTypeSQLServer (line 40) | DBTypeSQLServer = "sqlserver"
constant DBTypeRedis (line 42) | DBTypeRedis = "redis"
constant Jrpc (line 44) | Jrpc = "json-rpc"
constant JrpcCodeFailure (line 46) | JrpcCodeFailure = -32901
constant JrpcCodeOngoing (line 49) | JrpcCodeOngoing = -32902
constant MsgDoBranch0 (line 52) | MsgDoBranch0 = "00"
constant MsgDoBarrier1 (line 54) | MsgDoBarrier1 = "01"
constant MsgDoOp (line 56) | MsgDoOp = "msg"
constant MsgTopicPrefix (line 58) | MsgTopicPrefix = "topic://"
constant XaBarrier1 (line 61) | XaBarrier1 = "01"
constant ProtocolGRPC (line 64) | ProtocolGRPC = "grpc"
constant ProtocolHTTP (line 66) | ProtocolHTTP = "http"
FILE: client/dtmcli/dtmimp/db_special.go
type DBSpecial (line 15) | type DBSpecial interface
type mysqlDBSpecial (line 24) | type mysqlDBSpecial struct
method GetPlaceHoldSQL (line 26) | func (*mysqlDBSpecial) GetPlaceHoldSQL(sql string) string {
method GetXaSQL (line 30) | func (*mysqlDBSpecial) GetXaSQL(command string, xid string) string {
method GetInsertIgnoreTemplate (line 37) | func (*mysqlDBSpecial) GetInsertIgnoreTemplate(tableAndValues string, ...
function init (line 41) | func init() {
type postgresDBSpecial (line 45) | type postgresDBSpecial struct
method GetXaSQL (line 47) | func (*postgresDBSpecial) GetXaSQL(command string, xid string) string {
method GetPlaceHoldSQL (line 58) | func (*postgresDBSpecial) GetPlaceHoldSQL(sql string) string {
method GetInsertIgnoreTemplate (line 74) | func (*postgresDBSpecial) GetInsertIgnoreTemplate(tableAndValues strin...
function init (line 77) | func init() {
function GetDBSpecial (line 82) | func GetDBSpecial(dbType string) DBSpecial {
function SetCurrentDBType (line 90) | func SetCurrentDBType(dbType string) {
function GetCurrentDBType (line 97) | func GetCurrentDBType() string {
FILE: client/dtmcli/dtmimp/db_special_test.go
function TestDBSpecial (line 15) | func TestDBSpecial(t *testing.T) {
FILE: client/dtmcli/dtmimp/trans_base.go
type BranchIDGen (line 22) | type BranchIDGen struct
method NewSubBranchID (line 28) | func (g *BranchIDGen) NewSubBranchID() string {
method CurrentSubBranchID (line 40) | func (g *BranchIDGen) CurrentSubBranchID() string {
type TransOptions (line 45) | type TransOptions struct
type TransBase (line 57) | type TransBase struct
method WithGlobalTransRequestTimeout (line 88) | func (t *TransBase) WithGlobalTransRequestTimeout(timeout int64) {
method WithRetryLimit (line 93) | func (t *TransBase) WithRetryLimit(retryLimit int64) {
function NewTransBase (line 77) | func NewTransBase(gid string, transType string, dtm string, branchID str...
function TransBaseFromQuery (line 98) | func TransBaseFromQuery(qs url.Values) *TransBase {
function TransCallDtmExt (line 103) | func TransCallDtmExt(tb *TransBase, body interface{}, operation string) ...
function TransCallDtm (line 120) | func TransCallDtm(tb *TransBase, operation string) error {
function TransRegisterBranch (line 126) | func TransRegisterBranch(tb *TransBase, added map[string]string, operati...
function TransRequestBranch (line 139) | func TransRequestBranch(t *TransBase, method string, body interface{}, b...
function transCallDtmJrpc (line 161) | func transCallDtmJrpc(tb *TransBase, body interface{}, operation string)...
FILE: client/dtmcli/dtmimp/trans_xa_base.go
function XaHandlePhase2 (line 15) | func XaHandlePhase2(gid string, dbConf DBConf, branchID string, op strin...
function XaHandleLocalTrans (line 34) | func XaHandleLocalTrans(xa *TransBase, dbConf DBConf, cb func(*sql.DB) e...
function XaHandleGlobalTrans (line 64) | func XaHandleGlobalTrans(xa *TransBase, callDtm func(string) error, call...
FILE: client/dtmcli/dtmimp/types.go
type DB (line 12) | type DB interface
type DBConf (line 18) | type DBConf struct
FILE: client/dtmcli/dtmimp/types_test.go
function TestTypes (line 15) | func TestTypes(t *testing.T) {
FILE: client/dtmcli/dtmimp/utils.go
function AsError (line 43) | func AsError(x interface{}) error {
function P2E (line 52) | func P2E(perr *error) {
function E2P (line 59) | func E2P(err error) {
function CatchP (line 66) | func CatchP(f func()) (rerr error) {
function PanicIf (line 73) | func PanicIf(cond bool, err error) {
function MustAtoi (line 80) | func MustAtoi(s string) int {
function OrString (line 89) | func OrString(ss ...string) string {
function If (line 99) | func If(condition bool, trueObj interface{}, falseObj interface{}) inter...
function MustMarshal (line 107) | func MustMarshal(v interface{}) []byte {
function MustMarshalString (line 114) | func MustMarshalString(v interface{}) string {
function MustUnmarshal (line 119) | func MustUnmarshal(b []byte, obj interface{}) {
function MustUnmarshalString (line 125) | func MustUnmarshalString(s string, obj interface{}) {
function MustRemarshal (line 130) | func MustRemarshal(from interface{}, to interface{}) {
function GetFuncName (line 138) | func GetFuncName() string {
function MayReplaceLocalhost (line 145) | func MayReplaceLocalhost(host string) string {
type mapCache (line 156) | type mapCache struct
method LoadOrStore (line 161) | func (m *mapCache) LoadOrStore(conf DBConf, factory func(conf DBConf) ...
function PooledDB (line 177) | func PooledDB(conf DBConf) (*sql.DB, error) {
function StandaloneDB (line 182) | func StandaloneDB(conf DBConf) (*sql.DB, error) {
function XaDB (line 189) | func XaDB(conf DBConf) (*sql.DB, error) {
function XaClose (line 199) | func XaClose(db *sql.DB) {
function DBExec (line 205) | func DBExec(dbType string, db DB, sql string, values ...interface{}) (af...
function GetDsn (line 225) | func GetDsn(conf DBConf) string {
function getSQLServerConnectionString (line 240) | func getSQLServerConnectionString(conf *DBConf, host *string) string {
function RespAsErrorByJSONRPC (line 254) | func RespAsErrorByJSONRPC(resp *resty.Response) error {
function DeferDo (line 271) | func DeferDo(rerr *error, success func() error, fail func() error) {
function Escape (line 284) | func Escape(input string) string {
function EscapeGet (line 293) | func EscapeGet(qs url.Values, key string) string {
function InsertBarrier (line 298) | func InsertBarrier(tx DB, transType string, gid string, branchID string,...
FILE: client/dtmcli/dtmimp/utils_test.go
function TestEP (line 18) | func TestEP(t *testing.T) {
function TestTernary (line 39) | func TestTernary(t *testing.T) {
function TestMarshal (line 46) | func TestMarshal(t *testing.T) {
function TestSome (line 63) | func TestSome(t *testing.T) {
FILE: client/dtmcli/dtmimp/vars.go
function GetRestyClient2 (line 41) | func GetRestyClient2(timeout time.Duration) *resty.Client {
function AddRestyMiddlewares (line 56) | func AddRestyMiddlewares(client *resty.Client) {
FILE: client/dtmcli/trans_msg.go
type Msg (line 18) | type Msg struct
method Add (line 29) | func (s *Msg) Add(action string, postData interface{}) *Msg {
method AddTopic (line 36) | func (s *Msg) AddTopic(topic string, postData interface{}) *Msg {
method SetDelay (line 41) | func (s *Msg) SetDelay(delay uint64) *Msg {
method Prepare (line 47) | func (s *Msg) Prepare(queryPrepared string) error {
method Submit (line 53) | func (s *Msg) Submit() error {
method DoAndSubmitDB (line 59) | func (s *Msg) DoAndSubmitDB(queryPrepared string, db *sql.DB, busiCall...
method DoAndSubmit (line 69) | func (s *Msg) DoAndSubmit(queryPrepared string, busiCall func(bb *Bran...
method BuildCustomOptions (line 93) | func (s *Msg) BuildCustomOptions() {
function NewMsg (line 24) | func NewMsg(server string, gid string) *Msg {
FILE: client/dtmcli/trans_saga.go
type Saga (line 16) | type Saga struct
method Add (line 34) | func (s *Saga) Add(action string, compensate string, postData interfac...
method AddBranchOrder (line 41) | func (s *Saga) AddBranchOrder(branch int, preBranches []int) *Saga {
method SetConcurrent (line 47) | func (s *Saga) SetConcurrent() *Saga {
method Submit (line 53) | func (s *Saga) Submit() error {
method BuildCustomOptions (line 59) | func (s *Saga) BuildCustomOptions() {
function NewSaga (line 22) | func NewSaga(server string, gid string) *Saga {
function NewSagaWithContext (line 27) | func NewSagaWithContext(ctx context.Context, server string, gid string) ...
FILE: client/dtmcli/trans_tcc.go
type Tcc (line 18) | type Tcc struct
method CallBranch (line 63) | func (t *Tcc) CallBranch(body interface{}, tryURL string, confirmURL s...
type TccGlobalFunc (line 23) | type TccGlobalFunc
function TccGlobalTransaction (line 29) | func TccGlobalTransaction(dtm string, gid string, tccFunc TccGlobalFunc)...
function TccGlobalTransaction2 (line 34) | func TccGlobalTransaction2(dtm string, gid string, custom func(*Tcc), tc...
function TccFromQuery (line 54) | func TccFromQuery(qs url.Values) (*Tcc, error) {
FILE: client/dtmcli/types.go
function SetCurrentDBType (line 26) | func SetCurrentDBType(dbType string) {
function GetCurrentDBType (line 31) | func GetCurrentDBType() string {
function SetBarrierTableName (line 36) | func SetBarrierTableName(tablename string) {
function GetRestyClient (line 41) | func GetRestyClient() *resty.Client {
function GetRestyClient2 (line 46) | func GetRestyClient2(timeout time.Duration) *resty.Client {
FILE: client/dtmcli/types_test.go
function TestTypes (line 17) | func TestTypes(t *testing.T) {
function TestXaSqlTimeout (line 28) | func TestXaSqlTimeout(t *testing.T) {
FILE: client/dtmcli/utils.go
function MustGenGid (line 14) | func MustGenGid(server string) string {
function ErrorMessage2Error (line 26) | func ErrorMessage2Error(errMsg string, err error) error {
function HTTPResp2DtmError (line 33) | func HTTPResp2DtmError(resp *resty.Response) error {
function Result2HttpJSON (line 48) | func Result2HttpJSON(result interface{}) (code int, res interface{}) {
function requestBranch (line 68) | func requestBranch(t *dtmimp.TransBase, method string, body interface{},...
FILE: client/dtmcli/xa.go
type XaGlobalFunc (line 19) | type XaGlobalFunc
type XaLocalFunc (line 22) | type XaLocalFunc
type Xa (line 25) | type Xa struct
method CallBranch (line 80) | func (x *Xa) CallBranch(body interface{}, url string) (*resty.Response...
function XaFromQuery (line 31) | func XaFromQuery(qs url.Values) (*Xa, error) {
function XaLocalTransaction (line 42) | func XaLocalTransaction(qs url.Values, dbConf DBConf, xaFunc XaLocalFunc...
function XaGlobalTransaction (line 63) | func XaGlobalTransaction(server string, gid string, xaFunc XaGlobalFunc)...
function XaGlobalTransaction2 (line 68) | func XaGlobalTransaction2(server string, gid string, custom func(*Xa), x...
FILE: client/dtmgrpc/barrier.go
function BarrierFromGrpc (line 17) | func BarrierFromGrpc(ctx context.Context) (*dtmcli.BranchBarrier, error) {
FILE: client/dtmgrpc/dtmgimp/grpc_clients.go
type rawCodec (line 22) | type rawCodec struct
method Marshal (line 24) | func (cb rawCodec) Marshal(v interface{}) ([]byte, error) {
method Unmarshal (line 28) | func (cb rawCodec) Unmarshal(data []byte, v interface{}) error {
method Name (line 36) | func (cb rawCodec) Name() string { return "dtm_raw" }
function MustGetDtmClient (line 47) | func MustGetDtmClient(grpcServer string) dtmgpb.DtmClient {
function GetGrpcConn (line 52) | func GetGrpcConn(grpcServer string, isRaw bool) (conn *grpc.ClientConn, ...
function MustGetGrpcConn (line 84) | func MustGetGrpcConn(grpcServer string, isRaw bool) *grpc.ClientConn {
function getGrpcServiceConfig (line 91) | func getGrpcServiceConfig() (string, bool) {
FILE: client/dtmgrpc/dtmgimp/types.go
function GrpcServerLog (line 25) | func GrpcServerLog(ctx context.Context, req interface{}, info *grpc.Unar...
function GrpcClientLog (line 42) | func GrpcClientLog(ctx context.Context, method string, req, reply interf...
function InvokeBranch (line 58) | func InvokeBranch(t *dtmimp.TransBase, isRaw bool, msg proto.Message, ur...
FILE: client/dtmgrpc/dtmgimp/utils.go
function MustProtoMarshal (line 21) | func MustProtoMarshal(msg proto.Message) []byte {
function MustProtoUnmarshal (line 28) | func MustProtoUnmarshal(data []byte, msg proto.Message) {
function GetDtmRequest (line 34) | func GetDtmRequest(s *dtmimp.TransBase) *dtmgpb.DtmRequest {
function DtmGrpcCall (line 55) | func DtmGrpcCall(s *dtmimp.TransBase, operation string) error {
constant dtmpre (line 60) | dtmpre string = "dtm-"
function TransInfo2Ctx (line 63) | func TransInfo2Ctx(ctx context.Context, gid, transType, branchID, op, dt...
function Map2Kvs (line 79) | func Map2Kvs(m map[string]string) []string {
function LogDtmCtx (line 88) | func LogDtmCtx(ctx context.Context) {
function dtmGet (line 95) | func dtmGet(md metadata.MD, key string) string {
function mdGet (line 99) | func mdGet(md metadata.MD, key string) string {
function TransBaseFromGrpc (line 108) | func TransBaseFromGrpc(ctx context.Context) *dtmimp.TransBase {
function GetMetaFromContext (line 116) | func GetMetaFromContext(ctx context.Context, name string) string {
function GetDtmMetaFromContext (line 122) | func GetDtmMetaFromContext(ctx context.Context, name string) string {
type requestTimeoutKey (line 127) | type requestTimeoutKey struct
function RequestTimeoutFromContext (line 130) | func RequestTimeoutFromContext(ctx context.Context) int64 {
function RequestTimeoutNewContext (line 139) | func RequestTimeoutNewContext(ctx context.Context, requestTimeout int64)...
FILE: client/dtmgrpc/dtmgpb/dtmgimp.pb.go
constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
type DtmTransOptions (line 24) | type DtmTransOptions struct
method Reset (line 38) | func (x *DtmTransOptions) Reset() {
method String (line 47) | func (x *DtmTransOptions) String() string {
method ProtoMessage (line 51) | func (*DtmTransOptions) ProtoMessage() {}
method ProtoReflect (line 53) | func (x *DtmTransOptions) ProtoReflect() protoreflect.Message {
method Descriptor (line 66) | func (*DtmTransOptions) Descriptor() ([]byte, []int) {
method GetWaitResult (line 70) | func (x *DtmTransOptions) GetWaitResult() bool {
method GetTimeoutToFail (line 77) | func (x *DtmTransOptions) GetTimeoutToFail() int64 {
method GetRetryInterval (line 84) | func (x *DtmTransOptions) GetRetryInterval() int64 {
method GetBranchHeaders (line 91) | func (x *DtmTransOptions) GetBranchHeaders() map[string]string {
method GetRequestTimeout (line 98) | func (x *DtmTransOptions) GetRequestTimeout() int64 {
method GetRetryLimit (line 105) | func (x *DtmTransOptions) GetRetryLimit() int64 {
type DtmRequest (line 113) | type DtmRequest struct
method Reset (line 129) | func (x *DtmRequest) Reset() {
method String (line 138) | func (x *DtmRequest) String() string {
method ProtoMessage (line 142) | func (*DtmRequest) ProtoMessage() {}
method ProtoReflect (line 144) | func (x *DtmRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 157) | func (*DtmRequest) Descriptor() ([]byte, []int) {
method GetGid (line 161) | func (x *DtmRequest) GetGid() string {
method GetTransType (line 168) | func (x *DtmRequest) GetTransType() string {
method GetTransOptions (line 175) | func (x *DtmRequest) GetTransOptions() *DtmTransOptions {
method GetCustomedData (line 182) | func (x *DtmRequest) GetCustomedData() string {
method GetBinPayloads (line 189) | func (x *DtmRequest) GetBinPayloads() [][]byte {
method GetQueryPrepared (line 196) | func (x *DtmRequest) GetQueryPrepared() string {
method GetSteps (line 203) | func (x *DtmRequest) GetSteps() string {
method GetReqExtra (line 210) | func (x *DtmRequest) GetReqExtra() map[string]string {
method GetRollbackReason (line 217) | func (x *DtmRequest) GetRollbackReason() string {
type DtmGidReply (line 224) | type DtmGidReply struct
method Reset (line 232) | func (x *DtmGidReply) Reset() {
method String (line 241) | func (x *DtmGidReply) String() string {
method ProtoMessage (line 245) | func (*DtmGidReply) ProtoMessage() {}
method ProtoReflect (line 247) | func (x *DtmGidReply) ProtoReflect() protoreflect.Message {
method Descriptor (line 260) | func (*DtmGidReply) Descriptor() ([]byte, []int) {
method GetGid (line 264) | func (x *DtmGidReply) GetGid() string {
type DtmBranchRequest (line 271) | type DtmBranchRequest struct
method Reset (line 284) | func (x *DtmBranchRequest) Reset() {
method String (line 293) | func (x *DtmBranchRequest) String() string {
method ProtoMessage (line 297) | func (*DtmBranchRequest) ProtoMessage() {}
method ProtoReflect (line 299) | func (x *DtmBranchRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 312) | func (*DtmBranchRequest) Descriptor() ([]byte, []int) {
method GetGid (line 316) | func (x *DtmBranchRequest) GetGid() string {
method GetTransType (line 323) | func (x *DtmBranchRequest) GetTransType() string {
method GetBranchID (line 330) | func (x *DtmBranchRequest) GetBranchID() string {
method GetOp (line 337) | func (x *DtmBranchRequest) GetOp() string {
method GetData (line 344) | func (x *DtmBranchRequest) GetData() map[string]string {
method GetBusiPayload (line 351) | func (x *DtmBranchRequest) GetBusiPayload() []byte {
type DtmProgressesReply (line 358) | type DtmProgressesReply struct
method Reset (line 367) | func (x *DtmProgressesReply) Reset() {
method String (line 376) | func (x *DtmProgressesReply) String() string {
method ProtoMessage (line 380) | func (*DtmProgressesReply) ProtoMessage() {}
method ProtoReflect (line 382) | func (x *DtmProgressesReply) ProtoReflect() protoreflect.Message {
method Descriptor (line 395) | func (*DtmProgressesReply) Descriptor() ([]byte, []int) {
method GetTransaction (line 399) | func (x *DtmProgressesReply) GetTransaction() *DtmTransaction {
method GetProgresses (line 406) | func (x *DtmProgressesReply) GetProgresses() []*DtmProgress {
type DtmTransaction (line 413) | type DtmTransaction struct
method Reset (line 424) | func (x *DtmTransaction) Reset() {
method String (line 433) | func (x *DtmTransaction) String() string {
method ProtoMessage (line 437) | func (*DtmTransaction) ProtoMessage() {}
method ProtoReflect (line 439) | func (x *DtmTransaction) ProtoReflect() protoreflect.Message {
method Descriptor (line 452) | func (*DtmTransaction) Descriptor() ([]byte, []int) {
method GetGid (line 456) | func (x *DtmTransaction) GetGid() string {
method GetStatus (line 463) | func (x *DtmTransaction) GetStatus() string {
method GetRollbackReason (line 470) | func (x *DtmTransaction) GetRollbackReason() string {
method GetResult (line 477) | func (x *DtmTransaction) GetResult() string {
type DtmProgress (line 484) | type DtmProgress struct
method Reset (line 495) | func (x *DtmProgress) Reset() {
method String (line 504) | func (x *DtmProgress) String() string {
method ProtoMessage (line 508) | func (*DtmProgress) ProtoMessage() {}
method ProtoReflect (line 510) | func (x *DtmProgress) ProtoReflect() protoreflect.Message {
method Descriptor (line 523) | func (*DtmProgress) Descriptor() ([]byte, []int) {
method GetStatus (line 527) | func (x *DtmProgress) GetStatus() string {
method GetBinData (line 534) | func (x *DtmProgress) GetBinData() []byte {
method GetBranchID (line 541) | func (x *DtmProgress) GetBranchID() string {
method GetOp (line 548) | func (x *DtmProgress) GetOp() string {
type DtmTopicRequest (line 555) | type DtmTopicRequest struct
method Reset (line 565) | func (x *DtmTopicRequest) Reset() {
method String (line 574) | func (x *DtmTopicRequest) String() string {
method ProtoMessage (line 578) | func (*DtmTopicRequest) ProtoMessage() {}
method ProtoReflect (line 580) | func (x *DtmTopicRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 593) | func (*DtmTopicRequest) Descriptor() ([]byte, []int) {
method GetTopic (line 597) | func (x *DtmTopicRequest) GetTopic() string {
method GetURL (line 604) | func (x *DtmTopicRequest) GetURL() string {
method GetRemark (line 611) | func (x *DtmTopicRequest) GetRemark() string {
function file_dtmgimp_proto_rawDescGZIP (line 764) | func file_dtmgimp_proto_rawDescGZIP() []byte {
function init (line 818) | func init() { file_dtmgimp_proto_init() }
function file_dtmgimp_proto_init (line 819) | func file_dtmgimp_proto_init() {
FILE: client/dtmgrpc/dtmgpb/dtmgimp_grpc.pb.go
constant _ (line 20) | _ = grpc.SupportPackageIsVersion7
type DtmClient (line 25) | type DtmClient interface
type dtmClient (line 37) | type dtmClient struct
method NewGid (line 45) | func (c *dtmClient) NewGid(ctx context.Context, in *emptypb.Empty, opt...
method Submit (line 54) | func (c *dtmClient) Submit(ctx context.Context, in *DtmRequest, opts ....
method Prepare (line 63) | func (c *dtmClient) Prepare(ctx context.Context, in *DtmRequest, opts ...
method Abort (line 72) | func (c *dtmClient) Abort(ctx context.Context, in *DtmRequest, opts .....
method RegisterBranch (line 81) | func (c *dtmClient) RegisterBranch(ctx context.Context, in *DtmBranchR...
method PrepareWorkflow (line 90) | func (c *dtmClient) PrepareWorkflow(ctx context.Context, in *DtmReques...
method Subscribe (line 99) | func (c *dtmClient) Subscribe(ctx context.Context, in *DtmTopicRequest...
method Unsubscribe (line 108) | func (c *dtmClient) Unsubscribe(ctx context.Context, in *DtmTopicReque...
method DeleteTopic (line 117) | func (c *dtmClient) DeleteTopic(ctx context.Context, in *DtmTopicReque...
function NewDtmClient (line 41) | func NewDtmClient(cc grpc.ClientConnInterface) DtmClient {
type DtmServer (line 129) | type DtmServer interface
type UnimplementedDtmServer (line 143) | type UnimplementedDtmServer struct
method NewGid (line 146) | func (UnimplementedDtmServer) NewGid(context.Context, *emptypb.Empty) ...
method Submit (line 149) | func (UnimplementedDtmServer) Submit(context.Context, *DtmRequest) (*e...
method Prepare (line 152) | func (UnimplementedDtmServer) Prepare(context.Context, *DtmRequest) (*...
method Abort (line 155) | func (UnimplementedDtmServer) Abort(context.Context, *DtmRequest) (*em...
method RegisterBranch (line 158) | func (UnimplementedDtmServer) RegisterBranch(context.Context, *DtmBran...
method PrepareWorkflow (line 161) | func (UnimplementedDtmServer) PrepareWorkflow(context.Context, *DtmReq...
method Subscribe (line 164) | func (UnimplementedDtmServer) Subscribe(context.Context, *DtmTopicRequ...
method Unsubscribe (line 167) | func (UnimplementedDtmServer) Unsubscribe(context.Context, *DtmTopicRe...
method DeleteTopic (line 170) | func (UnimplementedDtmServer) DeleteTopic(context.Context, *DtmTopicRe...
method mustEmbedUnimplementedDtmServer (line 173) | func (UnimplementedDtmServer) mustEmbedUnimplementedDtmServer() {}
type UnsafeDtmServer (line 178) | type UnsafeDtmServer interface
function RegisterDtmServer (line 182) | func RegisterDtmServer(s grpc.ServiceRegistrar, srv DtmServer) {
function _Dtm_NewGid_Handler (line 186) | func _Dtm_NewGid_Handler(srv interface{}, ctx context.Context, dec func(...
function _Dtm_Submit_Handler (line 204) | func _Dtm_Submit_Handler(srv interface{}, ctx context.Context, dec func(...
function _Dtm_Prepare_Handler (line 222) | func _Dtm_Prepare_Handler(srv interface{}, ctx context.Context, dec func...
function _Dtm_Abort_Handler (line 240) | func _Dtm_Abort_Handler(srv interface{}, ctx context.Context, dec func(i...
function _Dtm_RegisterBranch_Handler (line 258) | func _Dtm_RegisterBranch_Handler(srv interface{}, ctx context.Context, d...
function _Dtm_PrepareWorkflow_Handler (line 276) | func _Dtm_PrepareWorkflow_Handler(srv interface{}, ctx context.Context, ...
function _Dtm_Subscribe_Handler (line 294) | func _Dtm_Subscribe_Handler(srv interface{}, ctx context.Context, dec fu...
function _Dtm_Unsubscribe_Handler (line 312) | func _Dtm_Unsubscribe_Handler(srv interface{}, ctx context.Context, dec ...
function _Dtm_DeleteTopic_Handler (line 330) | func _Dtm_DeleteTopic_Handler(srv interface{}, ctx context.Context, dec ...
FILE: client/dtmgrpc/msg.go
type MsgGrpc (line 22) | type MsgGrpc struct
method Add (line 38) | func (s *MsgGrpc) Add(action string, msg proto.Message) *MsgGrpc {
method AddTopic (line 45) | func (s *MsgGrpc) AddTopic(topic string, msg proto.Message) *MsgGrpc {
method SetDelay (line 50) | func (s *MsgGrpc) SetDelay(delay uint64) *MsgGrpc {
method Prepare (line 56) | func (s *MsgGrpc) Prepare(queryPrepared string) error {
method Submit (line 62) | func (s *MsgGrpc) Submit() error {
method DoAndSubmitDB (line 68) | func (s *MsgGrpc) DoAndSubmitDB(queryPrepared string, db *sql.DB, busi...
method DoAndSubmit (line 78) | func (s *MsgGrpc) DoAndSubmit(queryPrepared string, busiCall func(bb *...
function NewMsgGrpc (line 27) | func NewMsgGrpc(server string, gid string, opts ...TransBaseOption) *Msg...
FILE: client/dtmgrpc/options.go
type TransBaseOption (line 8) | type TransBaseOption
function WithBranchHeaders (line 11) | func WithBranchHeaders(headers map[string]string) TransBaseOption {
FILE: client/dtmgrpc/options_test.go
function TestNewMsgGrpc (line 12) | func TestNewMsgGrpc(t *testing.T) {
function TestNewSagaGrpc (line 60) | func TestNewSagaGrpc(t *testing.T) {
function TestNewSagaGrpcWithContext (line 108) | func TestNewSagaGrpcWithContext(t *testing.T) {
FILE: client/dtmgrpc/saga.go
type SagaGrpc (line 18) | type SagaGrpc struct
method Add (line 45) | func (s *SagaGrpc) Add(action string, compensate string, payload proto...
method AddBranchOrder (line 52) | func (s *SagaGrpc) AddBranchOrder(branch int, preBranches []int) *Saga...
method EnableConcurrent (line 58) | func (s *SagaGrpc) EnableConcurrent() *SagaGrpc {
method Submit (line 64) | func (s *SagaGrpc) Submit() error {
function NewSagaGrpc (line 23) | func NewSagaGrpc(server string, gid string, opts ...TransBaseOption) *Sa...
function NewSagaGrpcWithContext (line 34) | func NewSagaGrpcWithContext(ctx context.Context, server string, gid stri...
FILE: client/dtmgrpc/tcc.go
type TccGrpc (line 21) | type TccGrpc struct
method CallBranch (line 65) | func (t *TccGrpc) CallBranch(busiMsg proto.Message, tryURL string, con...
type TccGlobalFunc (line 26) | type TccGlobalFunc
function TccGlobalTransaction (line 32) | func TccGlobalTransaction(dtm string, gid string, tccFunc TccGlobalFunc)...
function TccGlobalTransaction2 (line 37) | func TccGlobalTransaction2(dtm string, gid string, custom func(*TccGrpc)...
function TccFromGrpc (line 54) | func TccFromGrpc(ctx context.Context) (*TccGrpc, error) {
FILE: client/dtmgrpc/type.go
function DtmError2GrpcError (line 24) | func DtmError2GrpcError(res interface{}) error {
function GrpcError2DtmError (line 35) | func GrpcError2DtmError(err error) error {
function MustGenGid (line 50) | func MustGenGid(grpcServer string) string {
function UseDriver (line 58) | func UseDriver(driverName string) error {
function AddUnaryInterceptor (line 63) | func AddUnaryInterceptor(interceptor grpc.UnaryClientInterceptor) {
FILE: client/dtmgrpc/type_test.go
function TestType (line 16) | func TestType(t *testing.T) {
FILE: client/dtmgrpc/xa.go
type XaGrpcGlobalFunc (line 24) | type XaGrpcGlobalFunc
type XaGrpcLocalFunc (line 27) | type XaGrpcLocalFunc
type XaGrpc (line 30) | type XaGrpc struct
method CallBranch (line 97) | func (x *XaGrpc) CallBranch(msg proto.Message, url string, reply inter...
function XaGrpcFromRequest (line 36) | func XaGrpcFromRequest(ctx context.Context) (*XaGrpc, error) {
function XaLocalTransaction (line 48) | func XaLocalTransaction(ctx context.Context, dbConf dtmcli.DBConf, xaFun...
function XaGlobalTransaction (line 73) | func XaGlobalTransaction(server string, gid string, xaFunc XaGrpcGlobalF...
function XaGlobalTransaction2 (line 78) | func XaGlobalTransaction2(server string, gid string, custom func(*XaGrpc...
FILE: client/workflow/dummyReadCloser.go
function NewRespBodyFromBytes (line 10) | func NewRespBodyFromBytes(body []byte) io.ReadCloser {
type dummyReadCloser (line 14) | type dummyReadCloser struct
method Read (line 18) | func (d *dummyReadCloser) Read(p []byte) (n int, err error) {
method Close (line 22) | func (d *dummyReadCloser) Close() error {
FILE: client/workflow/factory.go
type workflowFactory (line 10) | type workflowFactory struct
method execute (line 23) | func (w *workflowFactory) execute(ctx context.Context, name string, gi...
method register (line 35) | func (w *workflowFactory) register(name string, handler WfFunc2, custo...
FILE: client/workflow/imp.go
type workflowImp (line 16) | type workflowImp struct
type workflowPhase2Item (line 29) | type workflowPhase2Item struct
method initProgress (line 34) | func (wf *Workflow) initProgress(progresses []*dtmgpb.DtmProgress) {
type wfMeta (line 48) | type wfMeta struct
method newWorkflow (line 50) | func (w *workflowFactory) newWorkflow(ctx context.Context, name string, ...
method initRestyClient (line 81) | func (wf *Workflow) initRestyClient() {
method process (line 97) | func (wf *Workflow) process(handler WfFunc2, data []byte) (res []byte, e...
method saveResult (line 126) | func (wf *Workflow) saveResult(branchID string, op string, sr *stepResul...
method processPhase2 (line 136) | func (wf *Workflow) processPhase2(err error) error {
method callPhase2 (line 155) | func (wf *Workflow) callPhase2(branchID string, fn WfPhase2Func) error {
method recordedDo (line 166) | func (wf *Workflow) recordedDo(fn func(bb *dtmcli.BranchBarrier) *stepRe...
method recordedDoInner (line 178) | func (wf *Workflow) recordedDoInner(fn func(bb *dtmcli.BranchBarrier) *s...
method getStepResult (line 203) | func (wf *Workflow) getStepResult() *stepResult {
FILE: client/workflow/rpc.go
method getProgress (line 16) | func (wf *Workflow) getProgress() (*dtmgpb.DtmProgressesReply, error) {
method submit (line 35) | func (wf *Workflow) submit(result []byte, err error) error {
method registerBranch (line 61) | func (wf *Workflow) registerBranch(res []byte, branchID string, op strin...
FILE: client/workflow/server.go
type workflowServer (line 15) | type workflowServer struct
method Execute (line 19) | func (s *workflowServer) Execute(ctx context.Context, wd *wfpb.Workflo...
FILE: client/workflow/utils.go
function wfErrorToStatus (line 18) | func wfErrorToStatus(err error) string {
type stepResult (line 27) | type stepResult struct
type roundTripper (line 35) | type roundTripper struct
method RoundTrip (line 52) | func (r *roundTripper) RoundTrip(req *http.Request) (*http.Response, e...
function newJSONResponse (line 40) | func newJSONResponse(status int, result []byte) *http.Response {
function newRoundTripper (line 67) | func newRoundTripper(old http.RoundTripper, wf *Workflow) http.RoundTrip...
function HTTPResp2DtmError (line 72) | func HTTPResp2DtmError(resp *http.Response) ([]byte, error) {
function GrpcError2DtmError (line 87) | func GrpcError2DtmError(err error) error {
method stepResultFromLocal (line 97) | func (wf *Workflow) stepResultFromLocal(data []byte, err error) *stepRes...
method stepResultToLocal (line 105) | func (wf *Workflow) stepResultToLocal(sr *stepResult) ([]byte, error) {
method stepResultFromGrpc (line 109) | func (wf *Workflow) stepResultFromGrpc(reply interface{}, err error) *st...
method stepResultToGrpc (line 120) | func (wf *Workflow) stepResultToGrpc(s *stepResult, reply interface{}) e...
method stepResultFromHTTP (line 127) | func (wf *Workflow) stepResultFromHTTP(resp *http.Response, err error) *...
method stepResultToHTTP (line 136) | func (wf *Workflow) stepResultToHTTP(s *stepResult) (*http.Response, err...
FILE: client/workflow/wfpb/wf.pb.go
constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
type WorkflowData (line 24) | type WorkflowData struct
method Reset (line 32) | func (x *WorkflowData) Reset() {
method String (line 41) | func (x *WorkflowData) String() string {
method ProtoMessage (line 45) | func (*WorkflowData) ProtoMessage() {}
method ProtoReflect (line 47) | func (x *WorkflowData) ProtoReflect() protoreflect.Message {
method Descriptor (line 60) | func (*WorkflowData) Descriptor() ([]byte, []int) {
method GetData (line 64) | func (x *WorkflowData) GetData() []byte {
function file_workflow_wfpb_wf_proto_rawDescGZIP (line 93) | func file_workflow_wfpb_wf_proto_rawDescGZIP() []byte {
function init (line 115) | func init() { file_workflow_wfpb_wf_proto_init() }
function file_workflow_wfpb_wf_proto_init (line 116) | func file_workflow_wfpb_wf_proto_init() {
FILE: client/workflow/wfpb/wf_grpc.pb.go
constant _ (line 20) | _ = grpc.SupportPackageIsVersion7
type WorkflowClient (line 25) | type WorkflowClient interface
type workflowClient (line 29) | type workflowClient struct
method Execute (line 37) | func (c *workflowClient) Execute(ctx context.Context, in *WorkflowData...
function NewWorkflowClient (line 33) | func NewWorkflowClient(cc grpc.ClientConnInterface) WorkflowClient {
type WorkflowServer (line 49) | type WorkflowServer interface
type UnimplementedWorkflowServer (line 55) | type UnimplementedWorkflowServer struct
method Execute (line 58) | func (UnimplementedWorkflowServer) Execute(context.Context, *WorkflowD...
method mustEmbedUnimplementedWorkflowServer (line 61) | func (UnimplementedWorkflowServer) mustEmbedUnimplementedWorkflowServe...
type UnsafeWorkflowServer (line 66) | type UnsafeWorkflowServer interface
function RegisterWorkflowServer (line 70) | func RegisterWorkflowServer(s grpc.ServiceRegistrar, srv WorkflowServer) {
function _Workflow_Execute_Handler (line 74) | func _Workflow_Execute_Handler(srv interface{}, ctx context.Context, dec...
FILE: client/workflow/workflow.go
function InitHTTP (line 22) | func InitHTTP(httpDtm string, callback string) {
function InitGrpc (line 32) | func InitGrpc(grpcDtm string, clientHost string, grpcServer *grpc.Server) {
function SetProtocolForTest (line 40) | func SetProtocolForTest(protocol string) {
function Register (line 45) | func Register(name string, handler WfFunc, custom ...func(wf *Workflow))...
function Register2 (line 52) | func Register2(name string, handler WfFunc2, custom ...func(wf *Workflow...
function ExecuteCtx (line 59) | func ExecuteCtx(ctx context.Context, name string, gid string, data []byt...
function Execute (line 65) | func Execute(name string, gid string, data []byte) error {
function Execute2 (line 72) | func Execute2(name string, gid string, data []byte) ([]byte, error) {
function ExecuteByQS (line 78) | func ExecuteByQS(qs url.Values, body []byte) error {
type Options (line 86) | type Options struct
type Workflow (line 101) | type Workflow struct
method NewRequest (line 125) | func (wf *Workflow) NewRequest() *resty.Request {
method NewBranch (line 130) | func (wf *Workflow) NewBranch() *Workflow {
method NewBranchCtx (line 141) | func (wf *Workflow) NewBranchCtx() context.Context {
method OnRollback (line 148) | func (wf *Workflow) OnRollback(compensate WfPhase2Func) *Workflow {
method OnCommit (line 162) | func (wf *Workflow) OnCommit(fn WfPhase2Func) *Workflow {
method OnFinish (line 175) | func (wf *Workflow) OnFinish(fn func(bb *dtmcli.BranchBarrier, isRollb...
method Do (line 184) | func (wf *Workflow) Do(fn func(bb *dtmcli.BranchBarrier) ([]byte, erro...
method DoXa (line 194) | func (wf *Workflow) DoXa(dbConf dtmcli.DBConf, fn func(db *sql.DB) ([]...
type wfItem (line 109) | type wfItem struct
type WfFunc (line 115) | type WfFunc
type WfFunc2 (line 118) | type WfFunc2
type WfPhase2Func (line 122) | type WfPhase2Func
function Interceptor (line 236) | func Interceptor(ctx context.Context, method string, req, reply interfac...
FILE: client/workflow/workflow_test.go
function TestAbnormal (line 11) | func TestAbnormal(t *testing.T) {
FILE: dtmsvr/api.go
function svcSubmit (line 22) | func svcSubmit(t *TransGlobal) interface{} {
function svcPrepare (line 45) | func svcPrepare(t *TransGlobal) interface{} {
function svcPrepareWorkflow (line 58) | func svcPrepareWorkflow(t *TransGlobal) (*storage.TransGlobalStore, []Tr...
function svcAbort (line 68) | func svcAbort(t *TransGlobal) interface{} {
function svcForceStop (line 82) | func svcForceStop(t *TransGlobal) interface{} {
function svcResetNextCronTime (line 91) | func svcResetNextCronTime(t *TransGlobal) error {
function svcRegisterBranch (line 96) | func svcRegisterBranch(transType string, branch *TransBranch, data map[s...
FILE: dtmsvr/api_grpc.go
type dtmServer (line 19) | type dtmServer struct
method NewGid (line 23) | func (s *dtmServer) NewGid(ctx context.Context, in *emptypb.Empty) (*p...
method Submit (line 27) | func (s *dtmServer) Submit(ctx context.Context, in *pb.DtmRequest) (*e...
method Prepare (line 32) | func (s *dtmServer) Prepare(ctx context.Context, in *pb.DtmRequest) (*...
method Abort (line 37) | func (s *dtmServer) Abort(ctx context.Context, in *pb.DtmRequest) (*em...
method RegisterBranch (line 42) | func (s *dtmServer) RegisterBranch(ctx context.Context, in *pb.DtmBran...
method PrepareWorkflow (line 52) | func (s *dtmServer) PrepareWorkflow(ctx context.Context, in *pb.DtmReq...
method Subscribe (line 73) | func (s *dtmServer) Subscribe(ctx context.Context, in *pb.DtmTopicRequ...
method Unsubscribe (line 77) | func (s *dtmServer) Unsubscribe(ctx context.Context, in *pb.DtmTopicRe...
method DeleteTopic (line 81) | func (s *dtmServer) DeleteTopic(ctx context.Context, in *pb.DtmTopicRe...
FILE: dtmsvr/api_http.go
function addRoute (line 22) | func addRoute(engine *gin.Engine) {
function newGid (line 53) | func newGid(c *gin.Context) interface{} {
function prepare (line 57) | func prepare(c *gin.Context) interface{} {
function submit (line 61) | func submit(c *gin.Context) interface{} {
function abort (line 65) | func abort(c *gin.Context) interface{} {
function forceStop (line 69) | func forceStop(c *gin.Context) interface{} {
function resetNextCronTime (line 73) | func resetNextCronTime(c *gin.Context) interface{} {
function registerBranch (line 77) | func registerBranch(c *gin.Context) interface{} {
function query (line 90) | func query(c *gin.Context) interface{} {
function prepareWorkflow (line 100) | func prepareWorkflow(c *gin.Context) interface{} {
function all (line 108) | func all(c *gin.Context) interface{} {
function stringTotime (line 131) | func stringTotime(timeStr string) time.Time {
function resetCronTime (line 139) | func resetCronTime(c *gin.Context) interface{} {
function scanKV (line 151) | func scanKV(c *gin.Context) interface{} {
function queryKV (line 159) | func queryKV(c *gin.Context) interface{} {
function subscribe (line 167) | func subscribe(c *gin.Context) interface{} {
function unsubscribe (line 175) | func unsubscribe(c *gin.Context) interface{} {
function deleteTopic (line 182) | func deleteTopic(c *gin.Context) interface{} {
FILE: dtmsvr/api_json_rpc.go
type jrpcReq (line 15) | type jrpcReq struct
function addJrpcRouter (line 22) | func addJrpcRouter(engine *gin.Engine) {
function TransFromJrpcParams (line 103) | func TransFromJrpcParams(params interface{}) *TransGlobal {
function jrpcNewGid (line 110) | func jrpcNewGid(interface{}) interface{} {
function jrpcPrepare (line 114) | func jrpcPrepare(params interface{}) interface{} {
function jrpcSubmit (line 118) | func jrpcSubmit(params interface{}) interface{} {
function jrpcAbort (line 122) | func jrpcAbort(params interface{}) interface{} {
function jrpcRegisterBranch (line 126) | func jrpcRegisterBranch(params interface{}) interface{} {
FILE: dtmsvr/config/config.go
constant DtmMetricsPort (line 15) | DtmMetricsPort = 8889
constant Mysql (line 17) | Mysql = "mysql"
constant Redis (line 19) | Redis = "redis"
constant BoltDb (line 21) | BoltDb = "boltdb"
constant Postgres (line 23) | Postgres = "postgres"
constant SQLServer (line 25) | SQLServer = "sqlserver"
type MicroService (line 29) | type MicroService struct
type HTTPMicroService (line 36) | type HTTPMicroService struct
type Log (line 46) | type Log struct
type Store (line 53) | type Store struct
method IsDB (line 70) | func (s *Store) IsDB() bool {
method GetDBConf (line 75) | func (s *Store) GetDBConf() dtmcli.DBConf {
type Type (line 88) | type Type struct
function MustLoadConfig (line 115) | func MustLoadConfig(confFile string) {
FILE: dtmsvr/config/config_test.go
function TestLoadFromEnv (line 11) | func TestLoadFromEnv(t *testing.T) {
function TestLoadConfig (line 20) | func TestLoadConfig(t *testing.T) {
function TestCheckConfig (line 26) | func TestCheckConfig(t *testing.T) {
function TestConfig (line 71) | func TestConfig(t *testing.T) {
function testConfigStringField (line 78) | func testConfigStringField(fd *string, val string, t *testing.T) {
function testConfigIntField (line 86) | func testConfigIntField(fd *int64, val int64, t *testing.T) {
FILE: dtmsvr/config/config_utils.go
function loadFromEnv (line 14) | func loadFromEnv(prefix string, conf interface{}) {
function loadFromEnvInner (line 21) | func loadFromEnvInner(prefix string, conf reflect.Value, defaultValue st...
function toUnderscoreUpper (line 50) | func toUnderscoreUpper(key string) string {
function checkConfig (line 61) | func checkConfig(conf *Type) error {
FILE: dtmsvr/cron.go
function CronTransOnce (line 28) | func CronTransOnce() (gid string) {
function CronExpiredTrans (line 43) | func CronExpiredTrans(num int) {
function CronUpdateTopicsMap (line 53) | func CronUpdateTopicsMap() {
function CronUpdateTopicsMapOnce (line 61) | func CronUpdateTopicsMapOnce() {
function lockOneTrans (line 66) | func lockOneTrans(expireIn time.Duration) *TransGlobal {
function handlePanic (line 75) | func handlePanic(perr *error) {
function sleepCronTime (line 84) | func sleepCronTime() {
FILE: dtmsvr/entry/main.go
function usage (line 19) | func usage() {
function Main (line 33) | func Main(version *string) (*gin.Engine, *config.Type) {
FILE: dtmsvr/metrics.go
function setServerInfoMetrics (line 58) | func setServerInfoMetrics() {
function httpMetrics (line 62) | func httpMetrics(app *gin.Engine) *gin.Engine {
function grpcMetrics (line 80) | func grpcMetrics(ctx context.Context, req interface{}, info *grpc.UnaryS...
function transactionMetrics (line 95) | func transactionMetrics(global *TransGlobal, status bool) {
function branchMetrics (line 104) | func branchMetrics(global *TransGlobal, branch *TransBranch, status bool) {
function extractFromPath (line 112) | func extractFromPath(val string) string {
FILE: dtmsvr/storage/boltdb/boltdb.go
type Store (line 23) | type Store struct
method Ping (line 278) | func (s *Store) Ping() error {
method PopulateData (line 283) | func (s *Store) PopulateData(skipDrop bool) {
method FindTransGlobalStore (line 306) | func (s *Store) FindTransGlobalStore(gid string) (trans *storage.Trans...
method ScanTransGlobalStores (line 316) | func (s *Store) ScanTransGlobalStores(position *string, limit int64, c...
method FindBranches (line 349) | func (s *Store) FindBranches(gid string) []storage.TransBranchStore {
method UpdateBranches (line 360) | func (s *Store) UpdateBranches(branches []storage.TransBranchStore, up...
method LockGlobalSaveBranches (line 365) | func (s *Store) LockGlobalSaveBranches(gid string, status string, bran...
method MaySaveNewTrans (line 380) | func (s *Store) MaySaveNewTrans(global *storage.TransGlobalStore, bran...
method ChangeGlobalStatus (line 394) | func (s *Store) ChangeGlobalStatus(global *storage.TransGlobalStore, n...
method TouchCronTime (line 412) | func (s *Store) TouchCronTime(global *storage.TransGlobalStore, nextCr...
method LockOneGlobalTrans (line 431) | func (s *Store) LockOneGlobalTrans(expireIn time.Duration) *storage.Tr...
method ResetCronTime (line 460) | func (s *Store) ResetCronTime(after time.Duration, limit int64) (succe...
method ResetTransGlobalCronTime (line 488) | func (s *Store) ResetTransGlobalCronTime(g *storage.TransGlobalStore) ...
method ScanKV (line 505) | func (s *Store) ScanKV(cat string, position *string, limit int64) []st...
method FindKV (line 535) | func (s *Store) FindKV(cat, key string) []storage.KVStore {
method UpdateKV (line 565) | func (s *Store) UpdateKV(kv *storage.KVStore) error {
method DeleteKV (line 582) | func (s *Store) DeleteKV(cat, key string) error {
method CreateKV (line 594) | func (s *Store) CreateKV(cat, key, value string) error {
function NewStore (line 32) | func NewStore(dataExpire int64, retryInterval int64) *Store {
function initializeBuckets (line 58) | func initializeBuckets(db *bolt.DB) error {
function cleanupExpiredData (line 74) | func cleanupExpiredData(expire time.Duration, db *bolt.DB) error {
function cleanupGlobalWithGids (line 108) | func cleanupGlobalWithGids(t *bolt.Tx, gids map[string]struct{}) {
function cleanupBranchWithGids (line 121) | func cleanupBranchWithGids(t *bolt.Tx, gids map[string]struct{}) {
function cleanupIndexWithGids (line 150) | func cleanupIndexWithGids(t *bolt.Tx, gids map[string]struct{}) {
function tGetGlobal (line 187) | func tGetGlobal(t *bolt.Tx, gid string) *storage.TransGlobalStore {
function tGetBranches (line 197) | func tGetBranches(t *bolt.Tx, gid string) []storage.TransBranchStore {
function tPutGlobal (line 210) | func tPutGlobal(t *bolt.Tx, global *storage.TransGlobalStore) {
function tPutBranches (line 216) | func tPutBranches(t *bolt.Tx, branches []storage.TransBranchStore, start...
function tPutBranches2 (line 221) | func tPutBranches2(t *bolt.Tx, branches []storage.TransBranchStore, star...
function tDelIndex (line 241) | func tDelIndex(t *bolt.Tx, unix int64, gid string) {
function tPutIndex (line 247) | func tPutIndex(t *bolt.Tx, unix int64, gid string) {
function tGetKV (line 253) | func tGetKV(t *bolt.Tx, cat, key string) *storage.KVStore {
function tPutKV (line 264) | func tPutKV(t *bolt.Tx, kv *storage.KVStore) {
function tDelKV (line 271) | func tDelKV(t *bolt.Tx, cat, key string) {
FILE: dtmsvr/storage/boltdb/boltdb_test.go
function TestInitializeBuckets (line 21) | func TestInitializeBuckets(t *testing.T) {
function TestCleanupExpiredData (line 44) | func TestCleanupExpiredData(t *testing.T) {
function TestCleanupGlobalWithGids (line 116) | func TestCleanupGlobalWithGids(t *testing.T) {
function TestCleanupBranchWithGids (line 178) | func TestCleanupBranchWithGids(t *testing.T) {
function TestCleanupIndexWithGids (line 259) | func TestCleanupIndexWithGids(t *testing.T) {
FILE: dtmsvr/storage/redis/redis.go
type Store (line 33) | type Store struct
method Ping (line 37) | func (s *Store) Ping() error {
method PopulateData (line 43) | func (s *Store) PopulateData(skipDrop bool) {
method FindTransGlobalStore (line 52) | func (s *Store) FindTransGlobalStore(gid string) *storage.TransGlobalS...
method ScanTransGlobalStores (line 65) | func (s *Store) ScanTransGlobalStores(position *string, limit int64, c...
method FindBranches (line 114) | func (s *Store) FindBranches(gid string) []storage.TransBranchStore {
method UpdateBranches (line 126) | func (s *Store) UpdateBranches(branches []storage.TransBranchStore, up...
method MaySaveNewTrans (line 184) | func (s *Store) MaySaveNewTrans(global *storage.TransGlobalStore, bran...
method LockGlobalSaveBranches (line 212) | func (s *Store) LockGlobalSaveBranches(gid string, status string, bran...
method ChangeGlobalStatus (line 248) | func (s *Store) ChangeGlobalStatus(global *storage.TransGlobalStore, n...
method LockOneGlobalTrans (line 277) | func (s *Store) LockOneGlobalTrans(expireIn time.Duration) *storage.Tr...
method ResetCronTime (line 309) | func (s *Store) ResetCronTime(after time.Duration, limit int64) (succe...
method ResetTransGlobalCronTime (line 338) | func (s *Store) ResetTransGlobalCronTime(global *storage.TransGlobalSt...
method TouchCronTime (line 348) | func (s *Store) TouchCronTime(global *storage.TransGlobalStore, nextCr...
method ScanKV (line 370) | func (s *Store) ScanKV(cat string, position *string, limit int64) []st...
method FindKV (line 414) | func (s *Store) FindKV(cat, key string) []storage.KVStore {
method UpdateKV (line 447) | func (s *Store) UpdateKV(kv *storage.KVStore) error {
method DeleteKV (line 474) | func (s *Store) DeleteKV(cat, key string) error {
method CreateKV (line 483) | func (s *Store) CreateKV(cat, key, value string) error {
type argList (line 130) | type argList struct
method AppendGid (line 140) | func (a *argList) AppendGid(gid string) *argList {
method AppendRaw (line 148) | func (a *argList) AppendRaw(v interface{}) *argList {
method AppendObject (line 153) | func (a *argList) AppendObject(v interface{}) *argList {
method AppendBranches (line 157) | func (a *argList) AppendBranches(branches []storage.TransBranchStore) ...
function newArgList (line 135) | func newArgList() *argList {
function handleRedisResult (line 164) | func handleRedisResult(ret interface{}, err error) (string, error) {
function callLua (line 177) | func callLua(a *argList, lua string) (string, error) {
function redisGet (line 514) | func redisGet() redis.Cmdable {
FILE: dtmsvr/storage/registry/factory.go
type SingletonFactory (line 10) | type SingletonFactory struct
method GetStorage (line 19) | func (f *SingletonFactory) GetStorage() storage.Store {
FILE: dtmsvr/storage/registry/registry.go
type StorageFactory (line 18) | type StorageFactory interface
function GetStore (line 46) | func GetStore() storage.Store {
function WaitStoreUp (line 51) | func WaitStoreUp() {
FILE: dtmsvr/storage/sql/sql.go
type Store (line 29) | type Store struct
method Ping (line 33) | func (s *Store) Ping() error {
method PopulateData (line 41) | func (s *Store) PopulateData(skipDrop bool) {
method FindTransGlobalStore (line 47) | func (s *Store) FindTransGlobalStore(gid string) *storage.TransGlobalS...
method ScanTransGlobalStores (line 58) | func (s *Store) ScanTransGlobalStores(position *string, limit int64, c...
method FindBranches (line 89) | func (s *Store) FindBranches(gid string) []storage.TransBranchStore {
method UpdateBranches (line 96) | func (s *Store) UpdateBranches(branches []storage.TransBranchStore, up...
method LockGlobalSaveBranches (line 105) | func (s *Store) LockGlobalSaveBranches(gid string, status string, bran...
method MaySaveNewTrans (line 128) | func (s *Store) MaySaveNewTrans(global *storage.TransGlobalStore, bran...
method ChangeGlobalStatus (line 147) | func (s *Store) ChangeGlobalStatus(global *storage.TransGlobalStore, n...
method TouchCronTime (line 157) | func (s *Store) TouchCronTime(global *storage.TransGlobalStore, nextCr...
method LockOneGlobalTrans (line 166) | func (s *Store) LockOneGlobalTrans(expireIn time.Duration) *storage.Tr...
method ResetCronTime (line 203) | func (s *Store) ResetCronTime(after time.Duration, limit int64) (succe...
method ResetTransGlobalCronTime (line 220) | func (s *Store) ResetTransGlobalCronTime(global *storage.TransGlobalSt...
method ScanKV (line 231) | func (s *Store) ScanKV(cat string, position *string, limit int64) []st...
method FindKV (line 247) | func (s *Store) FindKV(cat, key string) []storage.KVStore {
method UpdateKV (line 261) | func (s *Store) UpdateKV(kv *storage.KVStore) error {
method DeleteKV (line 275) | func (s *Store) DeleteKV(cat, key string) error {
method CreateKV (line 284) | func (s *Store) CreateKV(cat, key, value string) error {
function SetDBConn (line 306) | func SetDBConn(db *gorm.DB) {
function dbGet (line 313) | func dbGet() *dtmutil.DB {
function wrapError (line 317) | func wrapError(err error) error {
function getTimeStr (line 325) | func getTimeStr(afterSecond int64) string {
FILE: dtmsvr/storage/store.go
type Store (line 21) | type Store interface
type TransGlobalScanCondition (line 43) | type TransGlobalScanCondition struct
FILE: dtmsvr/storage/trans.go
type TransGlobalExt (line 18) | type TransGlobalExt struct
type TransGlobalStore (line 23) | type TransGlobalStore struct
method TableName (line 48) | func (g *TransGlobalStore) TableName() string {
method String (line 52) | func (g *TransGlobalStore) String() string {
method IsFinished (line 57) | func (g *TransGlobalStore) IsFinished() bool {
type TransBranchStore (line 62) | type TransBranchStore struct
method TableName (line 76) | func (b *TransBranchStore) TableName() string {
method String (line 80) | func (b *TransBranchStore) String() string {
type KVStore (line 85) | type KVStore struct
method TableName (line 94) | func (k *KVStore) TableName() string {
FILE: dtmsvr/svr.go
function StartSvr (line 31) | func StartSvr() *gin.Engine {
function PopulateDB (line 87) | func PopulateDB(skipDrop bool) {
function updateBranchAsync (line 95) | func updateBranchAsync() {
function grpcRecover (line 137) | func grpcRecover(ctx context.Context, req interface{}, info *grpc.UnaryS...
FILE: dtmsvr/topics.go
constant topicsCat (line 11) | topicsCat = "topics"
type Topic (line 17) | type Topic struct
type Subscriber (line 24) | type Subscriber struct
function topic2urls (line 29) | func topic2urls(topic string) []string {
function Subscribe (line 38) | func Subscribe(topic, url, remark string) error {
function Unsubscribe (line 68) | func Unsubscribe(topic, url string) error {
function updateTopicsMap (line 100) | func updateTopicsMap() {
FILE: dtmsvr/trans_class.go
type TransGlobal (line 16) | type TransGlobal struct
method setupPayloads (line 24) | func (t *TransGlobal) setupPayloads() {
method getProcessor (line 56) | func (t *TransGlobal) getProcessor() transProcessor {
type transProcessor (line 43) | type transProcessor interface
type processorCreator (line 48) | type processorCreator
function registorProcessorCreator (line 52) | func registorProcessorCreator(transType string, creator processorCreator) {
type cronType (line 60) | type cronType
constant cronBackoff (line 63) | cronBackoff cronType = iota
constant cronReset (line 64) | cronReset
constant cronKeep (line 65) | cronKeep
function TransFromContext (line 69) | func TransFromContext(c *gin.Context) *TransGlobal {
function TransFromDtmRequest (line 83) | func TransFromDtmRequest(ctx context.Context, c *dtmgpb.DtmRequest) *Tra...
FILE: dtmsvr/trans_process.go
method Process (line 22) | func (t *TransGlobal) Process(branches []TransBranch) error {
method process (line 28) | func (t *TransGlobal) process(branches []TransBranch) error {
method processInner (line 60) | func (t *TransGlobal) processInner(ctx context.Context, branches []Trans...
method saveNew (line 78) | func (t *TransGlobal) saveNew() ([]TransBranch, error) {
FILE: dtmsvr/trans_status.go
method touchCronTime (line 27) | func (t *TransGlobal) touchCronTime(ctype cronType, delay uint64) {
type changeStatusParams (line 42) | type changeStatusParams struct
type changeStatusOption (line 47) | type changeStatusOption
function withRollbackReason (line 49) | func withRollbackReason(rollbackReason string) changeStatusOption {
function withResult (line 55) | func withResult(result string) changeStatusOption {
method changeStatus (line 61) | func (t *TransGlobal) changeStatus(status string, opts ...changeStatusOp...
method resetNextCronTime (line 89) | func (t *TransGlobal) resetNextCronTime() error {
method changeBranchStatus (line 98) | func (t *TransGlobal) changeBranchStatus(b *TransBranch, status string, ...
method isTimeout (line 112) | func (t *TransGlobal) isTimeout() bool {
method needDelay (line 123) | func (t *TransGlobal) needDelay(delay uint64) bool {
method needProcess (line 127) | func (t *TransGlobal) needProcess() bool {
method getURLResult (line 131) | func (t *TransGlobal) getURLResult(ctx context.Context, uri string, bran...
method getHTTPResult (line 144) | func (t *TransGlobal) getHTTPResult(uri string, branchID, op string, bra...
method determineHTTPRequestMethod (line 163) | func (t *TransGlobal) determineHTTPRequestMethod(branchPayload []byte) s...
method getJSONRPCResult (line 167) | func (t *TransGlobal) getJSONRPCResult(uri string, branchID, op string, ...
method getGrpcResult (line 196) | func (t *TransGlobal) getGrpcResult(ctx context.Context, uri string, bra...
method getBranchResult (line 216) | func (t *TransGlobal) getBranchResult(ctx context.Context, branch *Trans...
method execBranch (line 229) | func (t *TransGlobal) execBranch(ctx context.Context, branch *TransBranc...
method getNextCronInterval (line 262) | func (t *TransGlobal) getNextCronInterval(ctype cronType) int64 {
FILE: dtmsvr/trans_type_msg.go
type transMsgProcessor (line 20) | type transMsgProcessor struct
method GenBranches (line 28) | func (t *transMsgProcessor) GenBranches() []TransBranch {
method ProcessOnce (line 72) | func (t *transMsgProcessor) ProcessOnce(ctx context.Context, branches ...
function init (line 24) | func init() {
type cMsgCustom (line 51) | type cMsgCustom struct
method mayQueryPrepared (line 55) | func (t *TransGlobal) mayQueryPrepared(ctx context.Context) {
FILE: dtmsvr/trans_type_saga.go
type transSagaProcessor (line 14) | type transSagaProcessor struct
method GenBranches (line 24) | func (t *transSagaProcessor) GenBranches() []TransBranch {
method ProcessOnce (line 56) | func (t *transSagaProcessor) ProcessOnce(ctx context.Context, branches...
function init (line 18) | func init() {
type cSagaCustom (line 42) | type cSagaCustom struct
type branchResult (line 48) | type branchResult struct
FILE: dtmsvr/trans_type_tcc.go
type transTccProcessor (line 12) | type transTccProcessor struct
method GenBranches (line 20) | func (t *transTccProcessor) GenBranches() []TransBranch {
method ProcessOnce (line 24) | func (t *transTccProcessor) ProcessOnce(ctx context.Context, branches ...
function init (line 16) | func init() {
FILE: dtmsvr/trans_type_workflow.go
type transWorkflowProcessor (line 12) | type transWorkflowProcessor struct
method GenBranches (line 20) | func (t *transWorkflowProcessor) GenBranches() []TransBranch {
method ProcessOnce (line 29) | func (t *transWorkflowProcessor) ProcessOnce(ctx context.Context, bran...
function init (line 16) | func init() {
type cWorkflowCustom (line 24) | type cWorkflowCustom struct
FILE: dtmsvr/trans_type_xa.go
type transXaProcessor (line 11) | type transXaProcessor struct
method GenBranches (line 19) | func (t *transXaProcessor) GenBranches() []TransBranch {
method ProcessOnce (line 23) | func (t *transXaProcessor) ProcessOnce(ctx context.Context, branches [...
function init (line 15) | func init() {
FILE: dtmsvr/utils.go
type branchStatus (line 21) | type branchStatus struct
function GetStore (line 34) | func GetStore() storage.Store {
function GenGid (line 42) | func GenGid() string {
function GetTransGlobal (line 47) | func GetTransGlobal(gid string) *TransGlobal {
type asyncCtx (line 55) | type asyncCtx struct
method Deadline (line 59) | func (a *asyncCtx) Deadline() (deadline time.Time, ok bool) {
method Done (line 63) | func (a *asyncCtx) Done() <-chan struct{} {
function NewAsyncContext (line 69) | func NewAsyncContext(ctx context.Context) context.Context {
FILE: dtmsvr/utils_test.go
function TestUtils (line 18) | func TestUtils(t *testing.T) {
function TestSetNextCron (line 23) | func TestSetNextCron(t *testing.T) {
function TestNewAsyncContext (line 36) | func TestNewAsyncContext(t *testing.T) {
function TestAsyncContext (line 48) | func TestAsyncContext(t *testing.T) {
type testContextType (line 67) | type testContextType
function TestAsyncContextRecursive (line 69) | func TestAsyncContextRecursive(t *testing.T) {
function TestCopyContextWithMetadata (line 94) | func TestCopyContextWithMetadata(t *testing.T) {
function BenchmarkCopyContext (line 110) | func BenchmarkCopyContext(b *testing.B) {
FILE: dtmutil/consts.go
constant DefaultHTTPServer (line 11) | DefaultHTTPServer = "http://localhost:36789/api/dtmsvr"
constant DefaultJrpcServer (line 13) | DefaultJrpcServer = "http://localhost:36789/api/json-rpc"
constant DefaultGrpcServer (line 15) | DefaultGrpcServer = "localhost:36790"
FILE: dtmutil/db.go
type ModelBase (line 23) | type ModelBase struct
function getGormDialetor (line 29) | func getGormDialetor(driver string, dsn string) gorm.Dialector {
type DB (line 43) | type DB struct
method Must (line 48) | func (m *DB) Must() *DB {
method ToSQLDB (line 54) | func (m *DB) ToSQLDB() *sql.DB {
type tracePlugin (line 60) | type tracePlugin struct
method Name (line 62) | func (op *tracePlugin) Name() string {
method Initialize (line 66) | func (op *tracePlugin) Initialize(db *gorm.DB) (err error) {
function DbGet (line 105) | func DbGet(conf dtmcli.DBConf, ops ...func(*gorm.DB)) *DB {
FILE: dtmutil/utils.go
function GetGinApp (line 29) | func GetGinApp() *gin.Engine {
function WrapHandler (line 51) | func WrapHandler(fn func(*gin.Context) interface{}) gin.HandlerFunc {
function WrapHandler2 (line 69) | func WrapHandler2(fn func(*gin.Context) interface{}) gin.HandlerFunc {
function MustGetwd (line 127) | func MustGetwd() string {
function GetSQLDir (line 134) | func GetSQLDir() string {
function RecoverPanic (line 143) | func RecoverPanic(err *error) {
function GetNextTime (line 153) | func GetNextTime(second int64) *time.Time {
function RunSQLScript (line 159) | func RunSQLScript(conf dtmcli.DBConf, script string, skipDrop bool) {
FILE: dtmutil/utils_test.go
function TestGin (line 22) | func TestGin(t *testing.T) {
function TestFuncs (line 41) | func TestFuncs(t *testing.T) {
function TestRecoverPanic (line 50) | func TestRecoverPanic(t *testing.T) {
FILE: helper/bench/main.go
function hintAndExit (line 23) | func hintAndExit() {
function main (line 30) | func main() {
FILE: helper/bench/svr/http.go
constant benchAPI (line 31) | benchAPI = "/api/busi_bench"
constant total (line 32) | total = 200000
function pdbGet (line 37) | func pdbGet() *sql.DB {
function txGet (line 43) | func txGet() *sql.Tx {
function reloadData (line 50) | func reloadData() {
function PrepareBenchDB (line 74) | func PrepareBenchDB() {
function StartSvr (line 98) | func StartSvr() {
function qsAdjustBalance (line 107) | func qsAdjustBalance(uid int, amount int, c *gin.Context) error { // nol...
function benchAddRoute (line 140) | func benchAddRoute(app *gin.Engine) {
FILE: main.go
function main (line 36) | func main() {
function getSub (line 52) | func getSub(f1 fs.FS, subs ...string) fs.FS {
function addAdmin (line 60) | func addAdmin(app *gin.Engine, conf *config.Type) {
function proxyAdmin (line 101) | func proxyAdmin(conf *config.Type) func(c *gin.Context) {
function bytesTryReplaceIndex (line 129) | func bytesTryReplaceIndex(source []byte, conf *config.Type) []byte {
type transport (line 135) | type transport struct
method RoundTrip (line 140) | func (t *transport) RoundTrip(req *http.Request) (resp *http.Response,...
FILE: qs/main.go
function main (line 13) | func main() {
FILE: sqls/busi.mysql.sql
type dtm_busi (line 5) | create table if not exists dtm_busi.user_account(
FILE: sqls/busi.postgres.sql
type dtm_busi (line 7) | create table if not exists dtm_busi.user_account(
type create_idx (line 16) | create index if not exists create_idx on dtm_busi.user_account(create_time)
type update_idx (line 18) | create index if not exists update_idx on dtm_busi.user_account(update_time)
FILE: sqls/dtmcli.barrier.mysql.sql
type dtm_barrier (line 5) | create table if not exists dtm_barrier.barrier(
FILE: sqls/dtmcli.barrier.postgres.sql
type dtm_barrier (line 4) | create table if not exists dtm_barrier.barrier(
FILE: sqls/dtmsvr.storage.mysql.sql
type dtm (line 5) | CREATE TABLE if not EXISTS dtm.trans_global (
type dtm (line 30) | CREATE TABLE IF NOT EXISTS dtm.trans_branch_op (
type dtm (line 47) | CREATE TABLE IF NOT EXISTS dtm.kv (
FILE: sqls/dtmsvr.storage.postgres.sql
type trans_global (line 4) | CREATE TABLE if not EXISTS trans_global (
type owner (line 26) | create index if not EXISTS owner on trans_global(owner)
type status_next_cron_time (line 27) | create index if not EXISTS status_next_cron_time on trans_global (status...
type trans_branch_op (line 31) | CREATE TABLE IF NOT EXISTS trans_branch_op (
type kv (line 50) | CREATE TABLE IF NOT EXISTS kv (
FILE: sqls/dtmsvr.storage.sqlserver.sql
type dtm (line 7) | CREATE TABLE dtm.dbo.trans_global (
type dtm (line 29) | CREATE INDEX[owner] ON [dtm].[dbo].[trans_global]([owner] ASC)
type dtm (line 33) | CREATE TABLE dtm.dbo.trans_branch_op (
type dtm (line 50) | CREATE TABLE dtm.dbo.kv (
FILE: sqls/dtmsvr.storage.tdsql.sql
type dtm (line 5) | CREATE TABLE if not EXISTS dtm.trans_global (
type dtm (line 30) | CREATE TABLE IF NOT EXISTS dtm.trans_branch_op (
type dtm (line 47) | CREATE TABLE IF NOT EXISTS dtm.kv (
FILE: test/api_test.go
function TestAPIVersion (line 24) | func TestAPIVersion(t *testing.T) {
function TestAPIQuery (line 30) | func TestAPIQuery(t *testing.T) {
function TestAPIAll (line 55) | func TestAPIAll(t *testing.T) {
function TestAPIScanKV (line 137) | func TestAPIScanKV(t *testing.T) {
function TestAPIQueryKV (line 176) | func TestAPIQueryKV(t *testing.T) {
function TestDtmMetrics (line 198) | func TestDtmMetrics(t *testing.T) {
function TestAPIResetCronTime (line 204) | func TestAPIResetCronTime(t *testing.T) {
function TestAPIForceStoppedNormal (line 224) | func TestAPIForceStoppedNormal(t *testing.T) {
function TestAPIForceStoppedAbnormal (line 239) | func TestAPIForceStoppedAbnormal(t *testing.T) {
function TestAPIResetNextCronTime (line 253) | func TestAPIResetNextCronTime(t *testing.T) {
FILE: test/base_test.go
type BarrierModel (line 23) | type BarrierModel struct
method TableName (line 29) | func (BarrierModel) TableName() string { return dtmimp.BarrierTableName }
function TestBaseSqlDB (line 31) | func TestBaseSqlDB(t *testing.T) {
function TestBaseHttp (line 63) | func TestBaseHttp(t *testing.T) {
FILE: test/busi/barrier.go
function init (line 20) | func init() {
function TccBarrierTransOutCancel (line 189) | func TccBarrierTransOutCancel(c *gin.Context) interface{} {
method TransInBSaga (line 205) | func (s *busiServer) TransInBSaga(ctx context.Context, in *ReqGrpc) (*em...
method TransOutBSaga (line 212) | func (s *busiServer) TransOutBSaga(ctx context.Context, in *ReqGrpc) (*e...
method TransInRevertBSaga (line 219) | func (s *busiServer) TransInRevertBSaga(ctx context.Context, in *ReqGrpc...
method TransOutRevertBSaga (line 226) | func (s *busiServer) TransOutRevertBSaga(ctx context.Context, in *ReqGrp...
method TransInRedis (line 233) | func (s *busiServer) TransInRedis(ctx context.Context, in *ReqGrpc) (*em...
method TransOutRedis (line 238) | func (s *busiServer) TransOutRedis(ctx context.Context, in *ReqGrpc) (*e...
method TransInRevertRedis (line 243) | func (s *busiServer) TransInRevertRedis(ctx context.Context, in *ReqGrpc...
method TransOutRevertRedis (line 248) | func (s *busiServer) TransOutRevertRedis(ctx context.Context, in *ReqGrp...
method QueryPreparedB (line 253) | func (s *busiServer) QueryPreparedB(ctx context.Context, in *ReqGrpc) (*...
method QueryPreparedRedis (line 259) | func (s *busiServer) QueryPreparedRedis(ctx context.Context, in *ReqGrpc...
FILE: test/busi/base_grpc.go
function retry (line 41) | func retry(ctx context.Context, method string, req, reply interface{}, c...
function GrpcStartup (line 53) | func GrpcStartup() *grpc.Server {
function RunGrpc (line 69) | func RunGrpc(server *grpc.Server) {
type busiServer (line 79) | type busiServer struct
method QueryPrepared (line 83) | func (s *busiServer) QueryPrepared(ctx context.Context, in *ReqGrpc) (...
method TransIn (line 90) | func (s *busiServer) TransIn(ctx context.Context, in *ReqGrpc) (*empty...
method TransOut (line 94) | func (s *busiServer) TransOut(ctx context.Context, in *ReqGrpc) (*empt...
method TransInRevert (line 98) | func (s *busiServer) TransInRevert(ctx context.Context, in *ReqGrpc) (...
method TransOutRevert (line 102) | func (s *busiServer) TransOutRevert(ctx context.Context, in *ReqGrpc) ...
method TransInConfirm (line 106) | func (s *busiServer) TransInConfirm(ctx context.Context, in *ReqGrpc) ...
method TransOutConfirm (line 110) | func (s *busiServer) TransOutConfirm(ctx context.Context, in *ReqGrpc)...
method TransInTcc (line 114) | func (s *busiServer) TransInTcc(ctx context.Context, in *ReqGrpc) (*em...
method TransOutTcc (line 118) | func (s *busiServer) TransOutTcc(ctx context.Context, in *ReqGrpc) (*e...
method TransInXa (line 122) | func (s *busiServer) TransInXa(ctx context.Context, in *ReqGrpc) (*emp...
method TransOutXa (line 128) | func (s *busiServer) TransOutXa(ctx context.Context, in *ReqGrpc) (*em...
method TransInTccNested (line 134) | func (s *busiServer) TransInTccNested(ctx context.Context, in *ReqGrpc...
method TransOutHeaderYes (line 143) | func (s *busiServer) TransOutHeaderYes(ctx context.Context, in *ReqGrp...
method TransOutHeaderNo (line 151) | func (s *busiServer) TransOutHeaderNo(ctx context.Context, in *ReqGrpc...
FILE: test/busi/base_http.go
constant BusiAPI (line 29) | BusiAPI = "/api/busi"
constant BusiPort (line 31) | BusiPort = 8081
constant BusiGrpcPort (line 33) | BusiGrpcPort = 58081
type setupFunc (line 36) | type setupFunc
type SleepCancelHandler (line 44) | type SleepCancelHandler
function SetSleepCancelHandler (line 49) | func SetSleepCancelHandler(handler SleepCancelHandler) {
function BaseAppStartup (line 57) | func BaseAppStartup() *gin.Engine {
function RunHTTP (line 80) | func RunHTTP(app *gin.Engine) {
function BaseAddRoute (line 87) | func BaseAddRoute(app *gin.Engine) {
FILE: test/busi/base_jrpc.go
function addJrpcRoute (line 15) | func addJrpcRoute(app *gin.Engine) {
FILE: test/busi/base_types.go
type UserAccount (line 32) | type UserAccount struct
method TableName (line 39) | func (*UserAccount) TableName() string {
function GetBalanceByUID (line 44) | func GetBalanceByUID(uid int, store string) int {
type ReqHTTP (line 64) | type ReqHTTP struct
method String (line 71) | func (t *ReqHTTP) String() string {
function GenReqHTTP (line 76) | func GenReqHTTP(amount int, outFailed bool, inFailed bool) *ReqHTTP {
function GenReqGrpc (line 85) | func GenReqGrpc(amount int, outFailed bool, inFailed bool) *ReqGrpc {
function reqFrom (line 93) | func reqFrom(c *gin.Context) *ReqHTTP {
function infoFromContext (line 105) | func infoFromContext(c *gin.Context) *dtmcli.BranchBarrier {
type AutoEmptyString (line 116) | type AutoEmptyString struct
method SetOnce (line 121) | func (s *AutoEmptyString) SetOnce(v string) {
method Fetch (line 126) | func (s *AutoEmptyString) Fetch() string {
type mainSwitchType (line 135) | type mainSwitchType struct
function GetRedisAccountKey (line 152) | func GetRedisAccountKey(uid int) string {
FILE: test/busi/busi.pb.go
constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
type ReqGrpc (line 25) | type ReqGrpc struct
method Reset (line 35) | func (x *ReqGrpc) Reset() {
method String (line 44) | func (x *ReqGrpc) String() string {
method ProtoMessage (line 48) | func (*ReqGrpc) ProtoMessage() {}
method ProtoReflect (line 50) | func (x *ReqGrpc) ProtoReflect() protoreflect.Message {
method Descriptor (line 63) | func (*ReqGrpc) Descriptor() ([]byte, []int) {
method GetAmount (line 67) | func (x *ReqGrpc) GetAmount() int64 {
method GetTransOutResult (line 74) | func (x *ReqGrpc) GetTransOutResult() string {
method GetTransInResult (line 81) | func (x *ReqGrpc) GetTransInResult() string {
type BusiReply (line 88) | type BusiReply struct
method Reset (line 96) | func (x *BusiReply) Reset() {
method String (line 105) | func (x *BusiReply) String() string {
method ProtoMessage (line 109) | func (*BusiReply) ProtoMessage() {}
method ProtoReflect (line 111) | func (x *BusiReply) ProtoReflect() protoreflect.Message {
method Descriptor (line 124) | func (*BusiReply) Descriptor() ([]byte, []int) {
method GetMessage (line 128) | func (x *BusiReply) GetMessage() string {
function file_test_busi_busi_proto_rawDescGZIP (line 252) | func file_test_busi_busi_proto_rawDescGZIP() []byte {
function init (line 323) | func init() { file_test_busi_busi_proto_init() }
function file_test_busi_busi_proto_init (line 324) | func file_test_busi_busi_proto_init() {
FILE: test/busi/busi_grpc.pb.go
constant _ (line 20) | _ = grpc.SupportPackageIsVersion7
type BusiClient (line 25) | type BusiClient interface
type busiClient (line 53) | type busiClient struct
method TransIn (line 61) | func (c *busiClient) TransIn(ctx context.Context, in *ReqGrpc, opts .....
method TransOut (line 70) | func (c *busiClient) TransOut(ctx context.Context, in *ReqGrpc, opts ....
method TransInRevert (line 79) | func (c *busiClient) TransInRevert(ctx context.Context, in *ReqGrpc, o...
method TransOutRevert (line 88) | func (c *busiClient) TransOutRevert(ctx context.Context, in *ReqGrpc, ...
method TransInConfirm (line 97) | func (c *busiClient) TransInConfirm(ctx context.Context, in *ReqGrpc, ...
method TransOutConfirm (line 106) | func (c *busiClient) TransOutConfirm(ctx context.Context, in *ReqGrpc,...
method XaNotify (line 115) | func (c *busiClient) XaNotify(ctx context.Context, in *emptypb.Empty, ...
method TransInXa (line 124) | func (c *busiClient) TransInXa(ctx context.Context, in *ReqGrpc, opts ...
method TransOutXa (line 133) | func (c *busiClient) TransOutXa(ctx context.Context, in *ReqGrpc, opts...
method TransInTcc (line 142) | func (c *busiClient) TransInTcc(ctx context.Context, in *ReqGrpc, opts...
method TransOutTcc (line 151) | func (c *busiClient) TransOutTcc(ctx context.Context, in *ReqGrpc, opt...
method TransInTccNested (line 160) | func (c *busiClient) TransInTccNested(ctx context.Context, in *ReqGrpc...
method TransInBSaga (line 169) | func (c *busiClient) TransInBSaga(ctx context.Context, in *ReqGrpc, op...
method TransOutBSaga (line 178) | func (c *busiClient) TransOutBSaga(ctx context.Context, in *ReqGrpc, o...
method TransInRevertBSaga (line 187) | func (c *busiClient) TransInRevertBSaga(ctx context.Context, in *ReqGr...
method TransOutRevertBSaga (line 196) | func (c *busiClient) TransOutRevertBSaga(ctx context.Context, in *ReqG...
method TransOutHeaderYes (line 205) | func (c *busiClient) TransOutHeaderYes(ctx context.Context, in *ReqGrp...
method TransOutHeaderNo (line 214) | func (c *busiClient) TransOutHeaderNo(ctx context.Context, in *ReqGrpc...
method TransInRedis (line 223) | func (c *busiClient) TransInRedis(ctx context.Context, in *ReqGrpc, op...
method TransOutRedis (line 232) | func (c *busiClient) TransOutRedis(ctx context.Context, in *ReqGrpc, o...
method TransInRevertRedis (line 241) | func (c *busiClient) TransInRevertRedis(ctx context.Context, in *ReqGr...
method TransOutRevertRedis (line 250) | func (c *busiClient) TransOutRevertRedis(ctx context.Context, in *ReqG...
method QueryPrepared (line 259) | func (c *busiClient) QueryPrepared(ctx context.Context, in *ReqGrpc, o...
method QueryPreparedB (line 268) | func (c *busiClient) QueryPreparedB(ctx context.Context, in *ReqGrpc, ...
method QueryPreparedRedis (line 277) | func (c *busiClient) QueryPreparedRedis(ctx context.Context, in *ReqGr...
function NewBusiClient (line 57) | func NewBusiClient(cc grpc.ClientConnInterface) BusiClient {
type BusiServer (line 289) | type BusiServer interface
type UnimplementedBusiServer (line 319) | type UnimplementedBusiServer struct
method TransIn (line 322) | func (UnimplementedBusiServer) TransIn(context.Context, *ReqGrpc) (*em...
method TransOut (line 325) | func (UnimplementedBusiServer) TransOut(context.Context, *ReqGrpc) (*e...
method TransInRevert (line 328) | func (UnimplementedBusiServer) TransInRevert(context.Context, *ReqGrpc...
method TransOutRevert (line 331) | func (UnimplementedBusiServer) TransOutRevert(context.Context, *ReqGrp...
method TransInConfirm (line 334) | func (UnimplementedBusiServer) TransInConfirm(context.Context, *ReqGrp...
method TransOutConfirm (line 337) | func (UnimplementedBusiServer) TransOutConfirm(context.Context, *ReqGr...
method XaNotify (line 340) | func (UnimplementedBusiServer) XaNotify(context.Context, *emptypb.Empt...
method TransInXa (line 343) | func (UnimplementedBusiServer) TransInXa(context.Context, *ReqGrpc) (*...
method TransOutXa (line 346) | func (UnimplementedBusiServer) TransOutXa(context.Context, *ReqGrpc) (...
method TransInTcc (line 349) | func (UnimplementedBusiServer) TransInTcc(context.Context, *ReqGrpc) (...
method TransOutTcc (line 352) | func (UnimplementedBusiServer) TransOutTcc(context.Context, *ReqGrpc) ...
method TransInTccNested (line 355) | func (UnimplementedBusiServer) TransInTccNested(context.Context, *ReqG...
method TransInBSaga (line 358) | func (UnimplementedBusiServer) TransInBSaga(context.Context, *ReqGrpc)...
method TransOutBSaga (line 361) | func (UnimplementedBusiServer) TransOutBSaga(context.Context, *ReqGrpc...
method TransInRevertBSaga (line 364) | func (UnimplementedBusiServer) TransInRevertBSaga(context.Context, *Re...
method TransOutRevertBSaga (line 367) | func (UnimplementedBusiServer) TransOutRevertBSaga(context.Context, *R...
method TransOutHeaderYes (line 370) | func (UnimplementedBusiServer) TransOutHeaderYes(context.Context, *Req...
method TransOutHeaderNo (line 373) | func (UnimplementedBusiServer) TransOutHeaderNo(context.Context, *ReqG...
method TransInRedis (line 376) | func (UnimplementedBusiServer) TransInRedis(context.Context, *ReqGrpc)...
method TransOutRedis (line 379) | func (UnimplementedBusiServer) TransOutRedis(context.Context, *ReqGrpc...
method TransInRevertRedis (line 382) | func (UnimplementedBusiServer) TransInRevertRedis(context.Context, *Re...
method TransOutRevertRedis (line 385) | func (UnimplementedBusiServer) TransOutRevertRedis(context.Context, *R...
method QueryPrepared (line 388) | func (UnimplementedBusiServer) QueryPrepared(context.Context, *ReqGrpc...
method QueryPreparedB (line 391) | func (UnimplementedBusiServer) QueryPreparedB(context.Context, *ReqGrp...
method QueryPreparedRedis (line 394) | func (UnimplementedBusiServer) QueryPreparedRedis(context.Context, *Re...
method mustEmbedUnimplementedBusiServer (line 397) | func (UnimplementedBusiServer) mustEmbedUnimplementedBusiServer() {}
type UnsafeBusiServer (line 402) | type UnsafeBusiServer interface
function RegisterBusiServer (line 406) | func RegisterBusiServer(s grpc.ServiceRegistrar, srv BusiServer) {
function _Busi_TransIn_Handler (line 410) | func _Busi_TransIn_Handler(srv interface{}, ctx context.Context, dec fun...
function _Busi_TransOut_Handler (line 428) | func _Busi_TransOut_Handler(srv interface{}, ctx context.Context, dec fu...
function _Busi_TransInRevert_Handler (line 446) | func _Busi_TransInRevert_Handler(srv interface{}, ctx context.Context, d...
function _Busi_TransOutRevert_Handler (line 464) | func _Busi_TransOutRevert_Handler(srv interface{}, ctx context.Context, ...
function _Busi_TransInConfirm_Handler (line 482) | func _Busi_TransInConfirm_Handler(srv interface{}, ctx context.Context, ...
function _Busi_TransOutConfirm_Handler (line 500) | func _Busi_TransOutConfirm_Handler(srv interface{}, ctx context.Context,...
function _Busi_XaNotify_Handler (line 518) | func _Busi_XaNotify_Handler(srv interface{}, ctx context.Context, dec fu...
function _Busi_TransInXa_Handler (line 536) | func _Busi_TransInXa_Handler(srv interface{}, ctx context.Context, dec f...
function _Busi_TransOutXa_Handler (line 554) | func _Busi_TransOutXa_Handler(srv interface{}, ctx context.Context, dec ...
function _Busi_TransInTcc_Handler (line 572) | func _Busi_TransInTcc_Handler(srv interface{}, ctx context.Context, dec ...
function _Busi_TransOutTcc_Handler (line 590) | func _Busi_TransOutTcc_Handler(srv interface{}, ctx context.Context, dec...
function _Busi_TransInTccNested_Handler (line 608) | func _Busi_TransInTccNested_Handler(srv interface{}, ctx context.Context...
function _Busi_TransInBSaga_Handler (line 626) | func _Busi_TransInBSaga_Handler(srv interface{}, ctx context.Context, de...
function _Busi_TransOutBSaga_Handler (line 644) | func _Busi_TransOutBSaga_Handler(srv interface{}, ctx context.Context, d...
function _Busi_TransInRevertBSaga_Handler (line 662) | func _Busi_TransInRevertBSaga_Handler(srv interface{}, ctx context.Conte...
function _Busi_TransOutRevertBSaga_Handler (line 680) | func _Busi_TransOutRevertBSaga_Handler(srv interface{}, ctx context.Cont...
function _Busi_TransOutHeaderYes_Handler (line 698) | func _Busi_TransOutHeaderYes_Handler(srv interface{}, ctx context.Contex...
function _Busi_TransOutHeaderNo_Handler (line 716) | func _Busi_TransOutHeaderNo_Handler(srv interface{}, ctx context.Context...
function _Busi_TransInRedis_Handler (line 734) | func _Busi_TransInRedis_Handler(srv interface{}, ctx context.Context, de...
function _Busi_TransOutRedis_Handler (line 752) | func _Busi_TransOutRedis_Handler(srv interface{}, ctx context.Context, d...
function _Busi_TransInRevertRedis_Handler (line 770) | func _Busi_TransInRevertRedis_Handler(srv interface{}, ctx context.Conte...
function _Busi_TransOutRevertRedis_Handler (line 788) | func _Busi_TransOutRevertRedis_Handler(srv interface{}, ctx context.Cont...
function _Busi_QueryPrepared_Handler (line 806) | func _Busi_QueryPrepared_Handler(srv interface{}, ctx context.Context, d...
function _Busi_QueryPreparedB_Handler (line 824) | func _Busi_QueryPreparedB_Handler(srv interface{}, ctx context.Context, ...
function _Busi_QueryPreparedRedis_Handler (line 842) | func _Busi_QueryPreparedRedis_Handler(srv interface{}, ctx context.Conte...
FILE: test/busi/data.go
function PopulateDB (line 21) | func PopulateDB(skipDrop bool) {
constant TransOutUID (line 36) | TransOutUID = 1
constant TransInUID (line 39) | TransInUID = 2
constant Redis (line 42) | Redis = "redis"
constant Mongo (line 45) | Mongo = "mongo"
function handleGrpcBusiness (line 47) | func handleGrpcBusiness(in *ReqGrpc, result1 string, result2 string, bus...
function handleGeneralBusiness (line 60) | func handleGeneralBusiness(c *gin.Context, result1 string, result2 strin...
function handleGeneralBusinessCompatible (line 74) | func handleGeneralBusinessCompatible(c *gin.Context, result1 string, res...
function sagaGrpcAdjustBalance (line 84) | func sagaGrpcAdjustBalance(db dtmcli.DB, uid int, amount int64, result s...
function SagaAdjustBalance (line 93) | func SagaAdjustBalance(db dtmcli.DB, uid int, amount int, result string)...
function SagaMongoAdjustBalance (line 102) | func SagaMongoAdjustBalance(ctx context.Context, mc *mongo.Client, uid i...
function tccAdjustTrading (line 126) | func tccAdjustTrading(db dtmcli.DB, uid int, amount int) error {
function tccAdjustBalance (line 136) | func tccAdjustBalance(db dtmcli.DB, uid int, amount int) error {
FILE: test/busi/quick_start.go
constant qsBusiAPI (line 14) | qsBusiAPI = "/api/busi_start"
constant qsBusiPort (line 15) | qsBusiPort = 8082
function QsMain (line 20) | func QsMain() {
function QsStartSvr (line 27) | func QsStartSvr() {
function qsAddRoute (line 37) | func qsAddRoute(app *gin.Engine) {
constant dtmServer (line 57) | dtmServer = "http://localhost:36789/api/dtmsvr"
function QsFireRequest (line 60) | func QsFireRequest() string {
FILE: test/busi/startup.go
function Startup (line 9) | func Startup() (*gin.Engine, *grpc.Server) {
FILE: test/busi/utils.go
function dbGet (line 28) | func dbGet() *dtmutil.DB {
function pdbGet (line 32) | func pdbGet() *sql.DB {
function txGet (line 38) | func txGet() *sql.Tx {
function ResetXaData (line 46) | func ResetXaData() {
function MustBarrierFromGin (line 63) | func MustBarrierFromGin(c *gin.Context) *dtmcli.BranchBarrier {
function MustBarrierFromGrpc (line 70) | func MustBarrierFromGrpc(ctx context.Context) *dtmcli.BranchBarrier {
function string2DtmError (line 77) | func string2DtmError(str string) error {
function SetGrpcHeaderForHeadersYes (line 87) | func SetGrpcHeaderForHeadersYes(ctx context.Context, method string, req,...
function SetHTTPHeaderForHeadersYes (line 97) | func SetHTTPHeaderForHeadersYes(c *resty.Client, r *resty.Request) error {
function oldWrapHandler (line 106) | func oldWrapHandler(fn func(*gin.Context) (interface{}, error)) gin.Hand...
function RedisGet (line 139) | func RedisGet() redis.Cmdable {
function MongoGet (line 157) | func MongoGet() *mongo.Client {
function SetRedisBothAccount (line 171) | func SetRedisBothAccount(amountA int, ammountB int) {
function SetMongoBothAccount (line 180) | func SetMongoBothAccount(amountA int, amountB int) {
function SetupMongoBarrierAndBusi (line 191) | func SetupMongoBarrierAndBusi() {
FILE: test/common_test.go
function TestGeneralDB (line 15) | func TestGeneralDB(t *testing.T) {
function testSQL (line 22) | func testSQL(t *testing.T) {
function testDbAlone (line 34) | func testDbAlone(t *testing.T) {
function TestMustGenGid (line 46) | func TestMustGenGid(t *testing.T) {
function MaySkipMongo (line 51) | func MaySkipMongo(t *testing.T) {
FILE: test/dtmsvr_test.go
function getTransStatus (line 29) | func getTransStatus(gid string) string {
function getTrans (line 33) | func getTrans(gid string) *dtmsvr.TransGlobal {
function getBranchesStatus (line 37) | func getBranchesStatus(gid string) []string {
function isSQLStore (line 46) | func isSQLStore() bool {
function TestUpdateBranchAsync (line 49) | func TestUpdateBranchAsync(t *testing.T) {
function TestGrpcPanic (line 87) | func TestGrpcPanic(t *testing.T) {
FILE: test/main_test.go
function TestMain (line 26) | func TestMain(m *testing.M) {
FILE: test/msg_barrier_mongo_test.go
function TestMsgMongoDoSucceed (line 14) | func TestMsgMongoDoSucceed(t *testing.T) {
function TestMsgMongoDoBusiFailed (line 33) | func TestMsgMongoDoBusiFailed(t *testing.T) {
function TestMsgMongoDoBusiLater (line 47) | func TestMsgMongoDoBusiLater(t *testing.T) {
function TestMsgMongoDoCommitFailed (line 73) | func TestMsgMongoDoCommitFailed(t *testing.T) {
function TestMsgMongoDoCommitAfterFailed (line 91) | func TestMsgMongoDoCommitAfterFailed(t *testing.T) {
FILE: test/msg_barrier_redis_test.go
function TestMsgRedisDo (line 13) | func TestMsgRedisDo(t *testing.T) {
function TestMsgRedisDoBusiFailed (line 29) | func TestMsgRedisDoBusiFailed(t *testing.T) {
function TestMsgRedisDoBusiLater (line 42) | func TestMsgRedisDoBusiLater(t *testing.T) {
function TestMsgRedisDoPrepareFailed (line 65) | func TestMsgRedisDoPrepareFailed(t *testing.T) {
function TestMsgRedisDoCommitFailed (line 78) | func TestMsgRedisDoCommitFailed(t *testing.T) {
function TestMsgRedisDoCommitAfterFailed (line 91) | func TestMsgRedisDoCommitAfterFailed(t *testing.T) {
FILE: test/msg_barrier_test.go
function TestMsgDoAndSubmit (line 17) | func TestMsgDoAndSubmit(t *testing.T) {
function TestMsgDoAndSubmitBusiFailed (line 33) | func TestMsgDoAndSubmitBusiFailed(t *testing.T) {
function TestMsgDoAndSubmitBusiLater (line 46) | func TestMsgDoAndSubmitBusiLater(t *testing.T) {
function TestMsgDoAndSubmitPrepareFailed (line 69) | func TestMsgDoAndSubmitPrepareFailed(t *testing.T) {
function TestMsgDoAndSubmitCommitFailed (line 82) | func TestMsgDoAndSubmitCommitFailed(t *testing.T) {
function TestMsgDoAndSubmitCommitAfterFailed (line 105) | func TestMsgDoAndSubmitCommitAfterFailed(t *testing.T) {
FILE: test/msg_delay_test.go
function genMsgDelay (line 14) | func genMsgDelay(gid string) *dtmcli.Msg {
function TestMsgDelayNormal (line 23) | func TestMsgDelayNormal(t *testing.T) {
FILE: test/msg_grpc_barrier_redis_test.go
function TestMsgGrpcRedisDo (line 14) | func TestMsgGrpcRedisDo(t *testing.T) {
function TestMsgGrpcRedisDoBusiFailed (line 30) | func TestMsgGrpcRedisDoBusiFailed(t *testing.T) {
function TestMsgGrpcRedisDoPrepareFailed (line 43) | func TestMsgGrpcRedisDoPrepareFailed(t *testing.T) {
function TestMsgGrpcRedisDoCommitFailed (line 56) | func TestMsgGrpcRedisDoCommitFailed(t *testing.T) {
function TestMsgGrpcRedisDoCommitAfterFailed (line 69) | func TestMsgGrpcRedisDoCommitAfterFailed(t *testing.T) {
FILE: test/msg_grpc_barrier_test.go
function TestMsgGrpcPrepareAndSubmit (line 17) | func TestMsgGrpcPrepareAndSubmit(t *testing.T) {
function TestMsgGrpcPrepareAndSubmitCommitAfterFailed (line 33) | func TestMsgGrpcPrepareAndSubmitCommitAfterFailed(t *testing.T) {
function TestMsgGrpcPrepareAndSubmitCommitFailed (line 57) | func TestMsgGrpcPrepareAndSubmitCommitFailed(t *testing.T) {
FILE: test/msg_grpc_test.go
function TestMsgGrpcNormal (line 21) | func TestMsgGrpcNormal(t *testing.T) {
function TestMsgGrpcTimeoutSuccess (line 30) | func TestMsgGrpcTimeoutSuccess(t *testing.T) {
function TestMsgGrpcTimeoutFailed (line 47) | func TestMsgGrpcTimeoutFailed(t *testing.T) {
function genGrpcMsg (line 61) | func genGrpcMsg(gid string) *dtmgrpc.MsgGrpc {
function subscribeGrpcTopic (line 69) | func subscribeGrpcTopic() {
FILE: test/msg_jrpc_test.go
function TestMsgJrpcNormal (line 21) | func TestMsgJrpcNormal(t *testing.T) {
function TestMsgJrpcResults (line 29) | func TestMsgJrpcResults(t *testing.T) {
function TestMsgJrpcDoAndSubmit (line 48) | func TestMsgJrpcDoAndSubmit(t *testing.T) {
function TestMsgJrpcDoAndSubmitBusiFailed (line 65) | func TestMsgJrpcDoAndSubmitBusiFailed(t *testing.T) {
function TestMsgJrpcRepeated (line 79) | func TestMsgJrpcRepeated(t *testing.T) {
function TestMsgJprcAbnormal (line 89) | func TestMsgJprcAbnormal(t *testing.T) {
function TestMsgJprcAbnormal2 (line 128) | func TestMsgJprcAbnormal2(t *testing.T) {
function genJrpcMsg (line 135) | func genJrpcMsg(gid string) *dtmcli.Msg {
FILE: test/msg_options_test.go
function TestMsgOptionsTimeout (line 18) | func TestMsgOptionsTimeout(t *testing.T) {
function TestMsgOptionsTimeoutCustom (line 28) | func TestMsgOptionsTimeoutCustom(t *testing.T) {
function TestMsgOptionsTimeoutFailed (line 41) | func TestMsgOptionsTimeoutFailed(t *testing.T) {
function TestMsgConcurrent (line 55) | func TestMsgConcurrent(t *testing.T) {
FILE: test/msg_test.go
function TestMsgNormal (line 20) | func TestMsgNormal(t *testing.T) {
function TestMsgTimeoutSuccess (line 29) | func TestMsgTimeoutSuccess(t *testing.T) {
function TestMsgTimeoutFailed (line 45) | func TestMsgTimeoutFailed(t *testing.T) {
function TestMsgAbnormal (line 59) | func TestMsgAbnormal(t *testing.T) {
function TestMsgTopicNotFoundFailed (line 71) | func TestMsgTopicNotFoundFailed(t *testing.T) {
function genMsg (line 79) | func genMsg(gid string) *dtmcli.Msg {
function subscribeTopic (line 88) | func subscribeTopic() {
FILE: test/msg_webhook_test.go
function TestMsgWebhook (line 11) | func TestMsgWebhook(t *testing.T) {
function TestMsgWebhookError (line 27) | func TestMsgWebhookError(t *testing.T) {
FILE: test/saga_barrier_mongo_test.go
function TestSagaBarrierMongoNormal (line 18) | func TestSagaBarrierMongoNormal(t *testing.T) {
function TestSagaBarrierMongoRollback (line 30) | func TestSagaBarrierMongoRollback(t *testing.T) {
function genSagaBarrierMongo (line 42) | func genSagaBarrierMongo(gid string, transInFailed bool) *dtmcli.Saga {
FILE: test/saga_barrier_redis_test.go
function TestSagaBarrierRedisNormal (line 18) | func TestSagaBarrierRedisNormal(t *testing.T) {
function TestSagaBarrierRedisRollback (line 30) | func TestSagaBarrierRedisRollback(t *testing.T) {
function genSagaBarrierRedis (line 42) | func genSagaBarrierRedis(gid string) *dtmcli.Saga {
FILE: test/saga_barrier_test.go
function TestSagaBarrierNormal (line 18) | func TestSagaBarrierNormal(t *testing.T) {
function TestSagaBarrierRollback (line 27) | func TestSagaBarrierRollback(t *testing.T) {
function genSagaBarrier (line 36) | func genSagaBarrier(gid string, outFailed, inFailed bool) *dtmcli.Saga {
function TestSagaBarrier2Normal (line 43) | func TestSagaBarrier2Normal(t *testing.T) {
FILE: test/saga_compatible_test.go
function TestSagaCompatibleNormal (line 20) | func TestSagaCompatibleNormal(t *testing.T) { // compatible with old htt...
FILE: test/saga_concurrent_test.go
function genSagaCon (line 18) | func genSagaCon(gid string, outFailed bool, inFailed bool) *dtmcli.Saga {
function TestSagaConNormal (line 22) | func TestSagaConNormal(t *testing.T) {
function TestSagaConRollbackNormal (line 30) | func TestSagaConRollbackNormal(t *testing.T) {
function TestSagaConRollbackOrder (line 44) | func TestSagaConRollbackOrder(t *testing.T) {
function TestSagaConRollbackOrder2 (line 54) | func TestSagaConRollbackOrder2(t *testing.T) {
function TestSagaConCommittedOngoing (line 63) | func TestSagaConCommittedOngoing(t *testing.T) {
FILE: test/saga_grpc_barrier_test.go
function TestSagaGrpcBarrierNormal (line 19) | func TestSagaGrpcBarrierNormal(t *testing.T) {
function TestSagaGrpcBarrierRollback (line 28) | func TestSagaGrpcBarrierRollback(t *testing.T) {
function genSagaGrpcBarrier (line 37) | func genSagaGrpcBarrier(gid string, outFailed bool, inFailed bool) *dtmg...
FILE: test/saga_grpc_test.go
function TestSagaGrpcNormal (line 21) | func TestSagaGrpcNormal(t *testing.T) {
function TestSagaGrpcRollback (line 29) | func TestSagaGrpcRollback(t *testing.T) {
function TestSagaGrpcCurrent (line 43) | func TestSagaGrpcCurrent(t *testing.T) {
function TestSagaGrpcCurrentOrder (line 52) | func TestSagaGrpcCurrentOrder(t *testing.T) {
function TestSagaGrpcCommittedOngoing (line 62) | func TestSagaGrpcCommittedOngoing(t *testing.T) {
function TestSagaGrpcNormalWait (line 75) | func TestSagaGrpcNormalWait(t *testing.T) {
function TestSagaGrpcEmptyUrl (line 85) | func TestSagaGrpcEmptyUrl(t *testing.T) {
function genSagaGrpc (line 97) | func genSagaGrpc(gid string, outFailed bool, inFailed bool) *dtmgrpc.Sag...
function TestSagaGrpcWithGlobalTransRequestTimeout (line 105) | func TestSagaGrpcWithGlobalTransRequestTimeout(t *testing.T) {
function TestSagaGrpcOptionsRollbackWait (line 116) | func TestSagaGrpcOptionsRollbackWait(t *testing.T) {
function TestSagaGrpcHeaders (line 130) | func TestSagaGrpcHeaders(t *testing.T) {
function TestSagaGrpcCronHeaders (line 143) | func TestSagaGrpcCronHeaders(t *testing.T) {
FILE: test/saga_options_test.go
function TestSagaOptionsRetryOngoing (line 19) | func TestSagaOptionsRetryOngoing(t *testing.T) {
function TestSagaOptionsRetryError (line 32) | func TestSagaOptionsRetryError(t *testing.T) {
function TestSagaOptionsTimeout (line 48) | func TestSagaOptionsTimeout(t *testing.T) {
function TestSagaGlobalTransWithRequestTimeout (line 63) | func TestSagaGlobalTransWithRequestTimeout(t *testing.T) {
function TestSagaOptionsNormalWait (line 74) | func TestSagaOptionsNormalWait(t *testing.T) {
function TestSagaOptionsCommittedOngoingWait (line 84) | func TestSagaOptionsCommittedOngoingWait(t *testing.T) {
function TestSagaOptionsRollbackWait (line 99) | func TestSagaOptionsRollbackWait(t *testing.T) {
function TestSagaHeaders (line 112) | func TestSagaHeaders(t *testing.T) {
function TestSagaHeadersYes1 (line 125) | func TestSagaHeadersYes1(t *testing.T) {
function TestSagaGlobalTransWithRetryLimitYes (line 141) | func TestSagaGlobalTransWithRetryLimitYes(t *testing.T) {
function TestSagaGlobalTransWithRetryLimitNo (line 156) | func TestSagaGlobalTransWithRetryLimitNo(t *testing.T) {
FILE: test/saga_test.go
function TestSagaNormal (line 19) | func TestSagaNormal(t *testing.T) {
function TestSagaRollback (line 28) | func TestSagaRollback(t *testing.T) {
function TestSagaOngoingSucceed (line 39) | func TestSagaOngoingSucceed(t *testing.T) {
function TestSagaFailed (line 53) | func TestSagaFailed(t *testing.T) {
function TestSagaAbnormal (line 66) | func TestSagaAbnormal(t *testing.T) {
function TestSagaEmptyUrl (line 79) | func TestSagaEmptyUrl(t *testing.T) {
function genSaga (line 90) | func genSaga(gid string, outFailed bool, inFailed bool) *dtmcli.Saga {
function genSaga1 (line 98) | func genSaga1(gid string, outFailed bool, inFailed bool) *dtmcli.Saga {
FILE: test/store_test.go
function initTransGlobal (line 15) | func initTransGlobal(gid string) (*storage.TransGlobalStore, storage.Sto...
function initTransGlobalByNextCronTime (line 20) | func initTransGlobalByNextCronTime(gid string, next time.Time) (*storage...
function TestStoreSave (line 31) | func TestStoreSave(t *testing.T) {
function TestStoreChangeStatus (line 60) | func TestStoreChangeStatus(t *testing.T) {
function TestStoreLockTrans (line 73) | func TestStoreLockTrans(t *testing.T) {
function TestStoreResetCronTime (line 96) | func TestStoreResetCronTime(t *testing.T) {
function testStoreResetCronTime (line 103) | func testStoreResetCronTime(t *testing.T, funcName string, resetCronHand...
function TestUpdateBranches (line 175) | func TestUpdateBranches(t *testing.T) {
function TestResetTransGlobalCronTime (line 182) | func TestResetTransGlobalCronTime(t *testing.T) {
FILE: test/tcc_barrier_test.go
function TestTccBarrierNormal (line 24) | func TestTccBarrierNormal(t *testing.T) {
function TestTccBarrierRollback (line 38) | func TestTccBarrierRollback(t *testing.T) {
function TestTccBarrierDisorderMysql (line 52) | func TestTccBarrierDisorderMysql(t *testing.T) {
function TestTccBarrierDisorderMongo (line 56) | func TestTccBarrierDisorderMongo(t *testing.T) {
function TestTccBarrierDisorderRedis (line 60) | func TestTccBarrierDisorderRedis(t *testing.T) {
function runTestTccBarrierDisorder (line 65) | func runTestTccBarrierDisorder(t *testing.T, store string) {
function TestTccBarrierPanic (line 143) | func TestTccBarrierPanic(t *testing.T) {
FILE: test/tcc_cover_test.go
function TestTccCoverNotConnected (line 14) | func TestTccCoverNotConnected(t *testing.T) {
function TestTccCoverPanic (line 22) | func TestTccCoverPanic(t *testing.T) {
function TestTccNested (line 34) | func TestTccNested(t *testing.T) {
FILE: test/tcc_grpc_cover_test.go
function TestTccGrpcCoverNotConnected (line 14) | func TestTccGrpcCoverNotConnected(t *testing.T) {
function TestTccGrpcCoverPanic (line 22) | func TestTccGrpcCoverPanic(t *testing.T) {
function TestTccGrpcCoverCallBranch (line 34) | func TestTccGrpcCoverCallBranch(t *testing.T) {
FILE: test/tcc_grpc_test.go
function TestTccGrpcNormal (line 23) | func TestTccGrpcNormal(t *testing.T) {
function TestTccGrpcRollback (line 39) | func TestTccGrpcRollback(t *testing.T) {
function TestTccGrpcNested (line 58) | func TestTccGrpcNested(t *testing.T) {
function TestTccGrpcType (line 73) | func TestTccGrpcType(t *testing.T) {
function TestTccGrpcHeaders (line 81) | func TestTccGrpcHeaders(t *testing.T) {
FILE: test/tcc_jrpc_test.go
function TestTccJrpcNormal (line 14) | func TestTccJrpcNormal(t *testing.T) {
FILE: test/tcc_old_test.go
function TestTccOldNormal (line 14) | func TestTccOldNormal(t *testing.T) {
function TestTccOldRollback (line 28) | func TestTccOldRollback(t *testing.T) {
function TestTccOldTimeout (line 45) | func TestTccOldTimeout(t *testing.T) {
FILE: test/tcc_test.go
function TestTccNormal (line 20) | func TestTccNormal(t *testing.T) {
function TestTccRollback (line 34) | func TestTccRollback(t *testing.T) {
function TestTccTimeout (line 52) | func TestTccTimeout(t *testing.T) {
function TestTccCompatible (line 75) | func TestTccCompatible(t *testing.T) {
function TestTccHeaders (line 90) | func TestTccHeaders(t *testing.T) {
FILE: test/topic_test.go
constant testTopicTestTopicNormal (line 19) | testTopicTestTopicNormal = "test_topic_TestTopicNormal"
constant testTopicTestConcurrentUpdateTopic (line 20) | testTopicTestConcurrentUpdateTopic = "concurrent_topic_TestConcurrentUpd...
function TestTopicNormal (line 23) | func TestTopicNormal(t *testing.T) {
function TestConcurrentUpdateTopic (line 33) | func TestConcurrentUpdateTopic(t *testing.T) {
function testSubscribe (line 72) | func testSubscribe(t *testing.T, subscribe func(topic, url string) error) {
function testUnsubscribe (line 80) | func testUnsubscribe(t *testing.T, unsubscribe func(topic, url string) e...
function testDeleteTopic (line 90) | func testDeleteTopic(t *testing.T, deleteTopic func(topic string) error) {
function httpSubscribe (line 95) | func httpSubscribe(topic, url string) error {
function httpUnsubscribe (line 108) | func httpUnsubscribe(topic, url string) error {
function httpDeleteTopic (line 120) | func httpDeleteTopic(topic string) error {
function grpcSubscribe (line 129) | func grpcSubscribe(topic, url string) error {
function grpcUnsubscribe (line 138) | func grpcUnsubscribe(topic, url string) error {
function grpcDeleteTopic (line 146) | func grpcDeleteTopic(topic string) error {
FILE: test/types.go
function dbGet (line 25) | func dbGet() *dtmutil.DB {
function waitTransProcessed (line 30) | func waitTransProcessed(gid string) {
function cronTransOnce (line 41) | func cronTransOnce(t *testing.T, gid string) {
function cronTransOnceForwardNow (line 57) | func cronTransOnceForwardNow(t *testing.T, gid string, seconds int) {
function cronTransOnceForwardCron (line 64) | func cronTransOnceForwardCron(t *testing.T, gid string, seconds int) {
function submitForwardCron (line 71) | func submitForwardCron(seconds int, fn func()) {
constant StatusPrepared (line 80) | StatusPrepared = dtmcli.StatusPrepared
constant StatusSubmitted (line 82) | StatusSubmitted = dtmcli.StatusSubmitted
constant StatusSucceed (line 84) | StatusSucceed = dtmcli.StatusSucceed
constant StatusFailed (line 86) | StatusFailed = dtmcli.StatusFailed
constant StatusAborting (line 88) | StatusAborting = dtmcli.StatusAborting
function getBeforeBalances (line 91) | func getBeforeBalances(store string) []int {
function assertSameBalance (line 97) | func assertSameBalance(t *testing.T, before []int, store string) {
function assertNotSameBalance (line 104) | func assertNotSameBalance(t *testing.T, before []int, store string) {
FILE: test/workflow_base_test.go
function TestWorkflowBranchConflict (line 20) | func TestWorkflowBranchConflict(t *testing.T) {
FILE: test/workflow_grpc_test.go
function TestWorkflowGrpcSimple (line 22) | func TestWorkflowGrpcSimple(t *testing.T) {
function TestWorkflowGrpcRollback (line 41) | func TestWorkflowGrpcRollback(t *testing.T) {
function TestWorkflowMixed (line 70) | func TestWorkflowMixed(t *testing.T) {
function TestWorkflowGrpcError (line 115) | func TestWorkflowGrpcError(t *testing.T) {
FILE: test/workflow_http_ret_test.go
function TestWorkflowRet (line 12) | func TestWorkflowRet(t *testing.T) {
FILE: test/workflow_http_test.go
function TestWorkflowNormal (line 21) | func TestWorkflowNormal(t *testing.T) {
function TestWorkflowRollback (line 49) | func TestWorkflowRollback(t *testing.T) {
function TestWorkflowTcc (line 91) | func TestWorkflowTcc(t *testing.T) {
function TestWorkflowTccRollback (line 129) | func TestWorkflowTccRollback(t *testing.T) {
function TestWorkflowError (line 167) | func TestWorkflowError(t *testing.T) {
function TestWorkflowOngoing (line 186) | func TestWorkflowOngoing(t *testing.T) {
function TestWorkflowResumeSkip (line 207) | func TestWorkflowResumeSkip(t *testing.T) {
FILE: test/workflow_interceptor_test.go
function TestWorkflowInterceptorOutsideSaga (line 12) | func TestWorkflowInterceptorOutsideSaga(t *testing.T) {
FILE: test/workflow_ongoing_test.go
function fetchOngoingStep (line 24) | func fetchOngoingStep(dest int) bool {
function TestWorkflowSimpleResume (line 34) | func TestWorkflowSimpleResume(t *testing.T) {
function TestWorkflowGrpcRollbackResume (line 56) | func TestWorkflowGrpcRollbackResume(t *testing.T) {
function TestWorkflowXaResume (line 113) | func TestWorkflowXaResume(t *testing.T) {
FILE: test/workflow_xa_test.go
function TestWorkflowXaAction (line 21) | func TestWorkflowXaAction(t *testing.T) {
function TestWorkflowXaRollback (line 43) | func TestWorkflowXaRollback(t *testing.T) {
FILE: test/xa_cover_test.go
function TestXaCoverDBError (line 13) | func TestXaCoverDBError(t *testing.T) {
function TestXaCoverDTMError (line 33) | func TestXaCoverDTMError(t *testing.T) {
function TestXaCoverGidError (line 41) | func TestXaCoverGidError(t *testing.T) {
FILE: test/xa_grpc_test.go
function TestXaGrpcNormal (line 21) | func TestXaGrpcNormal(t *testing.T) {
function TestXaGrpcRollback (line 38) | func TestXaGrpcRollback(t *testing.T) {
function TestXaGrpcType (line 55) | func TestXaGrpcType(t *testing.T) {
function TestXaGrpcLocalError (line 70) | func TestXaGrpcLocalError(t *testing.T) {
FILE: test/xa_test.go
function TestXaNormal (line 21) | func TestXaNormal(t *testing.T) {
function TestXaDuplicate (line 37) | func TestXaDuplicate(t *testing.T) {
function TestXaRollback (line 59) | func TestXaRollback(t *testing.T) {
function TestXaLocalError (line 75) | func TestXaLocalError(t *testing.T) {
function TestXaTimeout (line 84) | func TestXaTimeout(t *testing.T) {
function TestXaNotTimeout (line 101) | func TestXaNotTimeout(t *testing.T) {
Condensed preview — 239 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,122K chars).
[
{
"path": ".github/workflows/codeql-analysis.yml",
"chars": 2319,
"preview": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# Y"
},
{
"path": ".github/workflows/docker.yml",
"chars": 1473,
"preview": "name: Build Docker\non:\n push:\n tags:\n - 'v*.*.*'\n\njobs:\n docker:\n name: Build docker\n runs-on: ubuntu-la"
},
{
"path": ".github/workflows/release.yml",
"chars": 1885,
"preview": "name: Release\non:\n push:\n tags:\n - 'v*.*.*'\n\njobs:\n release:\n name: Release on GitHub\n runs-on: ubuntu-l"
},
{
"path": ".github/workflows/tests.yml",
"chars": 1905,
"preview": "name: Tests\non:\n push:\n branches-ignore:\n - 'tmp-*'\n pull_request:\n branches-ignore:\n - 'tmp-*'\n\njobs:"
},
{
"path": ".gitignore",
"chars": 202,
"preview": "conf.yml\n*.out\n*.log\n# dist\n.idea/**\n.vscode\ndefault.etcd\n*/**/*.bolt\nbench/bench\nhelper/bench/bench\nhelper/qs/qs\n# Outp"
},
{
"path": "LICENSE",
"chars": 1512,
"preview": "BSD 3-Clause License\n\nCopyright (c) 2021, yedf\nAll rights reserved.\n\nRedistribution and use in source and binary forms, "
},
{
"path": "Makefile",
"chars": 412,
"preview": "# dev env https://www.dtm.pub/other/develop.html\nall: fmt lint test_redis\n.PHONY: all\n\nfmt:\n\t@gofmt -s -w ./\n\nlint:\n\trev"
},
{
"path": "README.md",
"chars": 5462,
"preview": "\n\nconst components: IObject<() => Promise<typeof import('*.vue')>> "
},
{
"path": "admin/src/router/index.ts",
"chars": 3207,
"preview": "import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'\nimport { IMenubarList } from '../type/store/"
},
{
"path": "admin/src/store/index.ts",
"chars": 71,
"preview": "import { createPinia } from 'pinia'\nexport const pinia = createPinia()\n"
},
{
"path": "admin/src/store/modules/layout.ts",
"chars": 1193,
"preview": "import { defineStore } from 'pinia'\nimport { allowRouter } from '/@/router'\nimport { ILayout, IMenubar, IMenubarList, IS"
},
{
"path": "admin/src/type/index.d.ts",
"chars": 361,
"preview": "export { }\ndeclare global {\n interface IObject<T> {\n [index: string]: T\n }\n interface ImportMetaEnv {\n VITE_APP"
},
{
"path": "admin/src/type/shim.vue.d.ts",
"chars": 148,
"preview": "declare module '*.vue' {\n import { defineComponent } from 'vue'\n const Component: ReturnType<typeof defineComponent>\n "
},
{
"path": "admin/src/type/store/layout.ts",
"chars": 602,
"preview": "export interface IMenubar {\n menuList: Array<IMenubarList>\n}\n\nexport interface ILayout {\n menubar: IMenubar\n status: "
},
{
"path": "admin/src/utils/request.ts",
"chars": 104,
"preview": "import axios from 'axios'\n\nconst request = axios.create({\n timeout: 60000\n})\n\nexport default request\n"
},
{
"path": "admin/src/utils/util.ts",
"chars": 854,
"preview": "import { useRoute } from 'vue-router'\nimport { IMenubarList } from '../type/store/layout'\n\nexport const findCurrentMenub"
},
{
"path": "admin/src/views/Dashboard/GlobalTransactions/AllTransactions.vue",
"chars": 7142,
"preview": "<template>\n <div>\n <a-form\n layout=\"inline\"\n :model=\"{}\"\n @finish=\"searchFini"
},
{
"path": "admin/src/views/Dashboard/GlobalTransactions/DialogTransactionDetail.vue",
"chars": 7073,
"preview": "<template>\n <div>\n <a-modal v-model:visible=\"visible\" :closable=\"closeable\" title=\"Transaction Detail\" width=\""
},
{
"path": "admin/src/views/Dashboard/GlobalTransactions/UnfinishedTransactions.vue",
"chars": 82,
"preview": "<template>\n <h1>Coming Soon</h1>\n</template>\n<script setup lang=\"ts\">\n</script>"
},
{
"path": "admin/src/views/Dashboard/KVPairs/Topics.vue",
"chars": 4424,
"preview": "<template>\n <div>\n <a-button type=\"primary\" class=\"mb-2\" @click=\"handleTopicSubscribe('')\">Subscribe</a-button"
},
{
"path": "admin/src/views/Dashboard/KVPairs/_Components/DialogTopicDetail.vue",
"chars": 2483,
"preview": "<template>\n <div>\n <a-modal v-model:visible=\"visible\" :title=\"topicName\" width=\"100%\" wrap-class-name=\"full-mo"
},
{
"path": "admin/src/views/Dashboard/KVPairs/_Components/DialogTopicSubscribe.vue",
"chars": 1931,
"preview": "<template>\n <div>\n <a-modal\n v-model:visible=\"visible\"\n width=\"60%\"\n title=\"T"
},
{
"path": "admin/src/views/Dashboard/Nodes/LivingNodes.vue",
"chars": 83,
"preview": "<template>\n <h1>Coming Soon</h1>\n</template>\n\n<script setup lang=\"ts\">\n</script>"
},
{
"path": "admin/tailwind.config.js",
"chars": 141,
"preview": "module.exports = {\n content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],\n theme: {\n extend: {}\n "
},
{
"path": "admin/tsconfig.json",
"chars": 502,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"esnext\",\n \"useDefineForClassFields\": true,\n \"module\": \"esnext\",\n \"modul"
},
{
"path": "admin/vite.config.ts",
"chars": 2382,
"preview": "import { ConfigEnv, UserConfigExport } from 'vite'\nimport path from 'path'\nimport vue from '@vitejs/plugin-vue'\nimport {"
},
{
"path": "charts/.helmignore",
"chars": 349,
"preview": "# Patterns to ignore when building packages.\n# This supports shell glob matching, relative path matching, and\n# negation"
},
{
"path": "charts/Chart.yaml",
"chars": 1139,
"preview": "apiVersion: v2\nname: dtm\ndescription: A Helm chart for Kubernetes\n\n# A chart can be either an 'application' or a 'librar"
},
{
"path": "charts/README.md",
"chars": 2833,
"preview": "# DTM charts\n\n## Usage\n\nInstall the dtm chart:\n\n```bash\nhelm install --create-namespace -n dtm-system dtm ./charts\n```\n\n"
},
{
"path": "charts/templates/NOTES.txt",
"chars": 1731,
"preview": "1. Get the application URL by running these commands:\n{{- if .Values.ingress.enabled }}\n{{- range $host := .Values.ingre"
},
{
"path": "charts/templates/_helpers.tpl",
"chars": 1742,
"preview": "{{/*\nExpand the name of the chart.\n*/}}\n{{- define \"dtm.name\" -}}\n{{- default .Chart.Name .Values.nameOverride | trunc 6"
},
{
"path": "charts/templates/configmap.yaml",
"chars": 209,
"preview": "apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: {{ include \"dtm.fullname\" . }}-conf\n labels:\n {{- include \"dtm.labe"
},
{
"path": "charts/templates/deployment.yaml",
"chars": 2069,
"preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: {{ include \"dtm.fullname\" . }}\n labels:\n {{- include \"dtm.lab"
},
{
"path": "charts/templates/hpa.yaml",
"chars": 904,
"preview": "{{- if .Values.autoscaling.enabled }}\napiVersion: autoscaling/v2beta1\nkind: HorizontalPodAutoscaler\nmetadata:\n name: {{"
},
{
"path": "charts/templates/ingress.yaml",
"chars": 2077,
"preview": "{{- if .Values.ingress.enabled -}}\n{{- $fullName := include \"dtm.fullname\" . -}}\n{{- $svcPort := .Values.service.ports.h"
},
{
"path": "charts/templates/service.yaml",
"chars": 460,
"preview": "apiVersion: v1\nkind: Service\nmetadata:\n name: {{ include \"dtm.fullname\" . }}\n labels:\n {{- include \"dtm.labels\" . |"
},
{
"path": "charts/templates/tests/test-connection.yaml",
"chars": 367,
"preview": "apiVersion: v1\nkind: Pod\nmetadata:\n name: \"{{ include \"dtm.fullname\" . }}-test-connection\"\n labels:\n {{- include \"d"
},
{
"path": "charts/values.yaml",
"chars": 1396,
"preview": "# Default values for dtm.\n# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\n\n# DTM "
},
{
"path": "client/README.md",
"chars": 1663,
"preview": "# Go Client for DTM\n\nThere are there packages:\n\n## workflow\nWorkflow is a new client for DTM. It support the mixed usage"
},
{
"path": "client/dtmcli/barrier.go",
"chars": 3932,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmcli/barrier_mongo.go",
"chars": 3289,
"preview": "package dtmcli\n\nimport (\n\t\"context\"\n\t\"strings\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli/dtmimp\"\n\t\"github.com/dtm-labs/lo"
},
{
"path": "client/dtmcli/barrier_redis.go",
"chars": 2225,
"preview": "package dtmcli\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli/dtmimp\"\n\t\"github.com/dtm-labs/logger"
},
{
"path": "client/dtmcli/consts.go",
"chars": 1785,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmcli/cover_test.go",
"chars": 487,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmcli/dtmimp/README-cn.md",
"chars": 47,
"preview": "## 注意\n此包带imp后缀,主要被dtm内部使用,相关接口可能会发生变更,请勿使用这里的接口"
},
{
"path": "client/dtmcli/dtmimp/README.md",
"chars": 162,
"preview": "## Notice\nPlease donot use this package, and this package should only be used in dtm internally. The interfaces are not "
},
{
"path": "client/dtmcli/dtmimp/consts.go",
"chars": 1912,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmcli/dtmimp/db_special.go",
"chars": 2474,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmcli/dtmimp/db_special_test.go",
"chars": 990,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmcli/dtmimp/trans_base.go",
"chars": 5882,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmcli/dtmimp/trans_xa_base.go",
"chars": 2330,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmcli/dtmimp/types.go",
"chars": 641,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmcli/dtmimp/types_test.go",
"chars": 521,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmcli/dtmimp/utils.go",
"chars": 7828,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmcli/dtmimp/utils_test.go",
"chars": 1763,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmcli/dtmimp/vars.go",
"chars": 2028,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmcli/logger/logger.go",
"chars": 703,
"preview": "package logger\n\nimport (\n\t\"github.com/dtm-labs/logger\"\n)\n\nvar (\n\t// WithLogger replaces default logger\n\tWithLogger = log"
},
{
"path": "client/dtmcli/trans_msg.go",
"chars": 2956,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmcli/trans_saga.go",
"chars": 1744,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmcli/trans_tcc.go",
"chars": 2232,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmcli/types.go",
"chars": 1113,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmcli/types_test.go",
"chars": 631,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmcli/utils.go",
"chars": 2213,
"preview": "package dtmcli\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli/dtmimp\"\n\t\"gith"
},
{
"path": "client/dtmcli/xa.go",
"chars": 2523,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmgrpc/barrier.go",
"chars": 533,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmgrpc/dtmgimp/README-cn.md",
"chars": 47,
"preview": "## 注意\n此包带imp后缀,主要被dtm内部使用,相关接口可能会发生变更,请勿使用这里的接口"
},
{
"path": "client/dtmgrpc/dtmgimp/README.md",
"chars": 162,
"preview": "## Notice\nPlease donot use this package, and this package should only be used in dtm internally. The interfaces are not "
},
{
"path": "client/dtmgrpc/dtmgimp/grpc_clients.go",
"chars": 3075,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmgrpc/dtmgimp/types.go",
"chars": 2629,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmgrpc/dtmgimp/utils.go",
"chars": 3957,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmgrpc/dtmgpb/dtmgimp.pb.go",
"chars": 35364,
"preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.28.1\n// \tprotoc v3.21.12\n// so"
},
{
"path": "client/dtmgrpc/dtmgpb/dtmgimp.proto",
"chars": 2224,
"preview": "syntax = \"proto3\";\n\noption go_package = \"./dtmgpb\";\nimport \"google/protobuf/empty.proto\";\n\npackage dtmgimp;\n\n// The dtm "
},
{
"path": "client/dtmgrpc/dtmgpb/dtmgimp_grpc.pb.go",
"chars": 13849,
"preview": "// Code generated by protoc-gen-go-grpc. DO NOT EDIT.\n// versions:\n// - protoc-gen-go-grpc v1.2.0\n// - protoc "
},
{
"path": "client/dtmgrpc/msg.go",
"chars": 3033,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmgrpc/options.go",
"chars": 360,
"preview": "package dtmgrpc\n\nimport (\n\t\"github.com/dtm-labs/dtm/client/dtmcli/dtmimp\"\n)\n\n// TransBaseOption setup func for TransBase"
},
{
"path": "client/dtmgrpc/options_test.go",
"chars": 3753,
"preview": "package dtmgrpc\n\nimport (\n\t\"context\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli\"\n)\n\n// TestNewMsgGrp"
},
{
"path": "client/dtmgrpc/saga.go",
"chars": 1785,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmgrpc/tcc.go",
"chars": 2515,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmgrpc/type.go",
"chars": 2007,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmgrpc/type_test.go",
"chars": 470,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/dtmgrpc/xa.go",
"chars": 3232,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "client/workflow/dummyReadCloser.go",
"chars": 510,
"preview": "package workflow\n\nimport (\n\t\"bytes\"\n\t\"io\"\n)\n\n// NewRespBodyFromBytes creates an io.ReadCloser from a byte slice\n// that "
},
{
"path": "client/workflow/factory.go",
"chars": 1045,
"preview": "package workflow\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/dtm-labs/logger\"\n)\n\ntype workflowFactory struct {\n\tprotocol "
},
{
"path": "client/workflow/imp.go",
"chars": 5811,
"preview": "package workflow\n\nimport (\n\t\"context\"\n\t\"encoding/base64\"\n\t\"errors\"\n\t\"fmt\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli\"\n\t\"gi"
},
{
"path": "client/workflow/rpc.go",
"chars": 2387,
"preview": "package workflow\n\nimport (\n\t\"context\"\n\t\"encoding/base64\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli\"\n\t\"github.com/dtm-labs"
},
{
"path": "client/workflow/server.go",
"chars": 834,
"preview": "package workflow\n\nimport (\n\t\"context\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli/dtmimp\"\n\t\"github.com/dtm-labs/dtm/client/"
},
{
"path": "client/workflow/utils.go",
"chars": 3948,
"preview": "package workflow\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmc"
},
{
"path": "client/workflow/wfpb/wf.pb.go",
"chars": 5246,
"preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.28.0\n// \tprotoc v3.17.3\n// sou"
},
{
"path": "client/workflow/wfpb/wf.proto",
"chars": 272,
"preview": "syntax = \"proto3\";\n\noption go_package = \"./wfpb\";\nimport \"google/protobuf/empty.proto\";\n\npackage workflow;\n\n// The Workf"
},
{
"path": "client/workflow/wfpb/wf_grpc.pb.go",
"chars": 3592,
"preview": "// Code generated by protoc-gen-go-grpc. DO NOT EDIT.\n// versions:\n// - protoc-gen-go-grpc v1.2.0\n// - protoc "
},
{
"path": "client/workflow/workflow.go",
"chars": 9271,
"preview": "package workflow\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\n\t\"github.com/dtm-labs/dtm/client/dt"
},
{
"path": "client/workflow/workflow_test.go",
"chars": 623,
"preview": "package workflow\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli/dtmimp\"\n\t\"github.com/stretchr/"
},
{
"path": "conf.sample.yml",
"chars": 3656,
"preview": "#####################################################################\n### dtm can be run without any config.\n### all con"
},
{
"path": "dtmsvr/api.go",
"chars": 4394,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "dtmsvr/api_grpc.go",
"chars": 2796,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "dtmsvr/api_http.go",
"chars": 6328,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "dtmsvr/api_json_rpc.go",
"chars": 3635,
"preview": "package dtmsvr\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli\"\n\t\"github.co"
},
{
"path": "dtmsvr/config/config.go",
"chars": 5493,
"preview": "package config\n\nimport (\n\t\"encoding/json\"\n\t\"io/ioutil\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli\"\n\t\"github.com/dtm-labs/d"
},
{
"path": "dtmsvr/config/config_test.go",
"chars": 2628,
"preview": "package config\n\nimport (\n\t\"errors\"\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestLoadFromEnv(t *te"
},
{
"path": "dtmsvr/config/config_utils.go",
"chars": 2356,
"preview": "package config\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli"
},
{
"path": "dtmsvr/cron.go",
"chars": 2353,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "dtmsvr/entry/main.go",
"chars": 1811,
"preview": "package entry\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"time\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli/dtmimp\"\n\t"
},
{
"path": "dtmsvr/metrics.go",
"chars": 3447,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "dtmsvr/microservices/drivers.go",
"chars": 361,
"preview": "package microservices\n\nimport (\n\t// load the microserver drivers\n\t_ \"github.com/dtm-labs/dtmdriver-dapr\"\n\t_ \"github.com/"
},
{
"path": "dtmsvr/storage/boltdb/boltdb.go",
"chars": 16000,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "dtmsvr/storage/boltdb/boltdb_test.go",
"chars": 8443,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "dtmsvr/storage/redis/redis.go",
"chars": 14960,
"preview": "/*\n * Copyright (c) 2022 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "dtmsvr/storage/registry/factory.go",
"chars": 449,
"preview": "package registry\n\nimport (\n\t\"sync\"\n\n\t\"github.com/dtm-labs/dtm/dtmsvr/storage\"\n)\n\n// SingletonFactory is the factory to b"
},
{
"path": "dtmsvr/storage/registry/registry.go",
"chars": 1287,
"preview": "package registry\n\nimport (\n\t\"time\"\n\n\t\"github.com/dtm-labs/logger\"\n\n\t\"github.com/dtm-labs/dtm/dtmsvr/config\"\n\t\"github.com"
},
{
"path": "dtmsvr/storage/sql/sql.go",
"chars": 10683,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "dtmsvr/storage/store.go",
"chars": 1878,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "dtmsvr/storage/trans.go",
"chars": 3325,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "dtmsvr/svr.go",
"chars": 4331,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "dtmsvr/topics.go",
"chars": 2835,
"preview": "package dtmsvr\n\nimport (\n\t\"errors\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli/dtmimp\"\n\t\"github.com/dtm-labs/dtm/client/dtm"
},
{
"path": "dtmsvr/trans_class.go",
"chars": 2768,
"preview": "package dtmsvr\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli\"\n\t\"github.com/dtm-labs/dtm/client/d"
},
{
"path": "dtmsvr/trans_process.go",
"chars": 2781,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "dtmsvr/trans_status.go",
"chars": 9339,
"preview": "package dtmsvr\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"math\"\n\t\"net/url\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/dtm-labs/dtm/cl"
},
{
"path": "dtmsvr/trans_type_msg.go",
"chars": 2977,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "dtmsvr/trans_type_saga.go",
"chars": 8664,
"preview": "package dtmsvr\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli\"\n\t\"github.com/dtm-"
},
{
"path": "dtmsvr/trans_type_tcc.go",
"chars": 1311,
"preview": "package dtmsvr\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli\"\n\t\"github.com/dtm-labs/dtm/client/dt"
},
{
"path": "dtmsvr/trans_type_workflow.go",
"chars": 1083,
"preview": "package dtmsvr\n\nimport (\n\t\"context\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli\"\n\t\"github.com/dtm-labs/dtm/client/dtmcli/dt"
},
{
"path": "dtmsvr/trans_type_xa.go",
"chars": 1146,
"preview": "package dtmsvr\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli\"\n\t\"github.com/dtm-labs/dtm/client/dt"
},
{
"path": "dtmsvr/utils.go",
"chars": 1670,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "dtmsvr/utils_test.go",
"chars": 3588,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "dtmutil/consts.go",
"chars": 583,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "dtmutil/db.go",
"chars": 3799,
"preview": "package dtmutil\n\nimport (\n\t\"database/sql\"\n\t\"fmt\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli\"\n\t\"github.com/"
},
{
"path": "dtmutil/utils.go",
"chars": 4717,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "dtmutil/utils_test.go",
"chars": 1339,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "go.mod",
"chars": 8512,
"preview": "module github.com/dtm-labs/dtm\n\ngo 1.22\n\nrequire (\n\tgithub.com/agiledragon/gomonkey/v2 v2.2.0\n\tgithub.com/dtm-labs/dtmdr"
},
{
"path": "go.sum",
"chars": 358747,
"preview": "bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=\nbazil.org/fuse "
},
{
"path": "helper/.goreleaser.yml",
"chars": 434,
"preview": "# .goreleaser.yml\nproject_name: dtm\nbuilds:\n - id: dtm_amd64\n env: [CGO_ENABLED=0]\n goos:\n - linux\n - w"
},
{
"path": "helper/Dockerfile-release",
"chars": 894,
"preview": "# syntax=docker/dockerfile:1\n# FROM node:14.19-alpine as builder1\n# ARG RELEASE_VERSION\n# WORKDIR /app/dtm\n# COPY . .\n# "
},
{
"path": "helper/README-cn.md",
"chars": 4158,
"preview": "\n\n 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "helper/bench/test-boltdb.sh",
"chars": 93,
"preview": "# !/bin/bash\n\nset -x\n\nab -n 50000 -c 10 \"http://127.0.0.1:8083/api/busi_bench/benchEmptyUrl\"\n"
},
{
"path": "helper/bench/test-flash-sales.sh",
"chars": 377,
"preview": "# !/bin/bash\n\nset -x\n\nexport LOG_LEVEL=fatal\nexport STORE_DRIVER=redis\nexport STORE_HOST=localhost\nexport STORE_PORT=637"
},
{
"path": "helper/bench/test-mysql.sh",
"chars": 1771,
"preview": "# !/bin/bash\n\nset -x\n\ncd /usr/share/sysbench/\necho 'create database sbtest;' > mysql -h 127.0.0.1 -uroot\n\nsysbench oltp_"
},
{
"path": "helper/bench/test-redis.sh",
"chars": 943,
"preview": "# !/bin/bash\n\nset -x\n\nexport LOG_LEVEL=warn\nexport STORE_DRIVER=redis\nexport STORE_HOST=localhost\nexport STORE_PORT=6379"
},
{
"path": "helper/compose.store.yml",
"chars": 1035,
"preview": "version: '3.3'\nservices:\n mysql:\n image: 'mysql:8'\n volumes:\n - /etc/localtime:/etc/localtime:ro\n environ"
},
{
"path": "helper/golint.sh",
"chars": 88,
"preview": "set -x\n\ngo install github.com/mgechev/revive@latest && revive -config revive.toml ./...\n"
},
{
"path": "helper/sync-client.sh",
"chars": 647,
"preview": "#! /bin/bash\nset -x\nver=$1\nif [ x$ver == x ]; then\n echo please specify you version like vx.x.x;\n exit 1;\nfi\n\nif [ ${v"
},
{
"path": "helper/test-cover.sh",
"chars": 1165,
"preview": "set -x\nexport DTM_DEBUG=1\necho \"mode: count\" > coverage.txt\nfor store in redis boltdb mysql postgres sqlserver; do\n TES"
},
{
"path": "main.go",
"chars": 4742,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "qs/main.go",
"chars": 255,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "revive.toml",
"chars": 547,
"preview": "ignoreGeneratedHeader = false\nseverity = \"warning\"\nconfidence = 0.8\nerrorCode = 0\nwarningCode = 0\n\n[rule.blank-imports]\n"
},
{
"path": "sqls/busi.mongo.js",
"chars": 245,
"preview": "use dtm_busi\ndb.user_account.drop()\ndb.user_account.createIndex({ user_id: NumberLong(1) }, { unique: true })\n\ndb.user_a"
},
{
"path": "sqls/busi.mysql.sql",
"chars": 642,
"preview": "CREATE DATABASE if not exists dtm_busi\n/*!40100 DEFAULT CHARACTER SET utf8mb4 */\n;\ndrop table if exists dtm_busi.user_ac"
},
{
"path": "sqls/busi.postgres.sql",
"chars": 940,
"preview": "CREATE SCHEMA if not exists dtm_busi\n/* SQLINES DEMO *** RACTER SET utf8mb4 */\n;\ndrop table if exists dtm_busi.user_acco"
},
{
"path": "sqls/dtmcli.barrier.mongo.js",
"chars": 223,
"preview": "use dtm_barrier\ndb.barrier.drop()\ndb.barrier.createIndex({ gid: 1, branch_id: 1, op: 1, barrier_id: 1 }, { unique: true "
},
{
"path": "sqls/dtmcli.barrier.mysql.sql",
"chars": 678,
"preview": "create database if not exists dtm_barrier\n/*!40100 DEFAULT CHARACTER SET utf8mb4 */\n;\ndrop table if exists dtm_barrier.b"
},
{
"path": "sqls/dtmcli.barrier.postgres.sql",
"chars": 654,
"preview": "create schema if not exists dtm_barrier;\ndrop table if exists dtm_barrier.barrier;\nCREATE SEQUENCE if not EXISTS dtm_bar"
},
{
"path": "sqls/dtmsvr.storage.mysql.sql",
"chars": 3100,
"preview": "CREATE DATABASE IF NOT EXISTS dtm\n/*!40100 DEFAULT CHARACTER SET utf8mb4 */\n;\ndrop table IF EXISTS dtm.trans_global;\nCRE"
},
{
"path": "sqls/dtmsvr.storage.postgres.sql",
"chars": 2205,
"preview": "drop table IF EXISTS trans_global;\n\nCREATE SEQUENCE if not EXISTS trans_global_seq;\nCREATE TABLE if not EXISTS trans_glo"
},
{
"path": "sqls/dtmsvr.storage.sqlserver.sql",
"chars": 3148,
"preview": "if db_id('dtm') is null\nbegin \n\tCREATE DATABASE dtm\nend;\n\ndrop table IF EXISTS dtm.dbo.trans_global;\nCREATE TABLE dtm.db"
},
{
"path": "sqls/dtmsvr.storage.tdsql.sql",
"chars": 3100,
"preview": "CREATE DATABASE IF NOT EXISTS dtm\n/*!40100 DEFAULT CHARACTER SET utf8mb4 */\n;\ndrop table IF EXISTS dtm.trans_global;\nCRE"
},
{
"path": "test/api_test.go",
"chars": 9933,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "test/base_test.go",
"chars": 2235,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "test/busi/barrier.go",
"chars": 11473,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "test/busi/base_grpc.go",
"chars": 6255,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "test/busi/base_http.go",
"chars": 8928,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "test/busi/base_jrpc.go",
"chars": 921,
"preview": "package busi\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli/dtmimp\"\n\t\"github.com/dtm-labs/dtm/dtmutil\"\n\t\"gith"
},
{
"path": "test/busi/base_types.go",
"chars": 4008,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "test/busi/busi.pb.go",
"chars": 19486,
"preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.28.0\n// \tprotoc v3.17.3\n// sou"
},
{
"path": "test/busi/busi.proto",
"chars": 1954,
"preview": "syntax = \"proto3\";\n\npackage busi;\nimport \"google/protobuf/empty.proto\";\n\noption go_package = \"./busi\";\n\n// DtmRequest re"
},
{
"path": "test/busi/busi_grpc.pb.go",
"chars": 35146,
"preview": "// Code generated by protoc-gen-go-grpc. DO NOT EDIT.\n// versions:\n// - protoc-gen-go-grpc v1.2.0\n// - protoc "
},
{
"path": "test/busi/data.go",
"chars": 5005,
"preview": "package busi\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli\"\n\t\"github.com/dtm"
},
{
"path": "test/busi/quick_start.go",
"chars": 2088,
"preview": "package busi\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"time\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli\"\n\t\"github.com/gin-gonic/gin\"\n\t\"git"
},
{
"path": "test/busi/startup.go",
"chars": 248,
"preview": "package busi\n\nimport (\n\t\"github.com/gin-gonic/gin\"\n\tgrpc \"google.golang.org/grpc\"\n)\n\n// Startup startup the busi's grpc "
},
{
"path": "test/busi/utils.go",
"chars": 6060,
"preview": "package busi\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strings\"\n\tsync \"sync\"\n\t\"time\"\n\n\t\"github.com/"
},
{
"path": "test/common_test.go",
"chars": 1320,
"preview": "package test\n\nimport (\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli\"\n\t\"github.com/dtm-labs/dtm/client/dtmcl"
},
{
"path": "test/dtmsvr_test.go",
"chars": 2571,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "test/main_test.go",
"chars": 2633,
"preview": "/*\n * Copyright (c) 2021 yedf. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license tha"
},
{
"path": "test/msg_barrier_mongo_test.go",
"chars": 3627,
"preview": "package test\n\nimport (\n\t\"errors\"\n\t\"testing\"\n\n\t\"github.com/dtm-labs/dtm/client/dtmcli\"\n\t\"github.com/dtm-labs/dtm/client/d"
}
]
// ... and 39 more files (download for full content)
About this extraction
This page contains the full source code of the dtm-labs/dtm GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 239 files (1.0 MB), approximately 413.1k tokens, and a symbol index with 1235 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.