### Start etcd for Kratos DTM Example Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/kratos.md Instructions to start the etcd server, which acts as the service registry for the Kratos DTM example. Ensure etcd is installed and accessible before running this command. ```shell etcd ``` -------------------------------- ### Running a DTM Go-Zero Example with Etcd Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/gozero.md Detailed steps to set up and execute a distributed transaction example using DTM and Go-Zero, with Etcd serving as the service registry. This includes commands to start Etcd, configure DTM, launch the DTM server, run a Go-Zero business service, and initiate a DTM transaction to observe its successful completion. ```shell etcd ``` ```yaml MicroService: Driver: 'dtm-driver-gozero' # 配置dtm使用go-zero的微服务协议 Target: 'etcd://localhost:2379/dtmservice' # 把dtm注册到etcd的这个地址 EndPoint: 'localhost:36790' # dtm的本地地址 ``` ```shell go run app/main.go -c conf.yml ``` ```shell git clone https://github.com/dtm-labs/dtmdriver-clients && cd dtmdriver-clients cd gozero/trans && go run trans.go ``` ```shell cd gozero/app && go run main.go ``` -------------------------------- ### Start DTM Server for Kratos Integration Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/kratos.md Command to start the DTM server application. This command uses a Go executable and a specified configuration file (conf.yml), which should contain DTM's database settings and other configurations. ```shell go run app/main.go -c conf.yml # conf.yml is your dtm configuration file ``` -------------------------------- ### Run Kratos Transaction Service with DTM Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/kratos.md Steps to clone the dtmdriver-clients repository, navigate to the Kratos transaction example, build the service, and then execute it. This service will be a participant in DTM distributed transactions. ```shell git clone https://github.com/dtm-labs/dtmdriver-clients && cd dtmdriver-clients cd kratos/trans make build && ./bin/trans -conf configs/config.yaml ``` -------------------------------- ### Integrating DTM into Go-Zero Application for Distributed Transactions Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/gozero.md Go code demonstrating the integration of DTM into a Go-Zero application to manage distributed transactions. It illustrates how to import the DTM Go-Zero driver, configure the DTM server address, load service configurations, and initiate a message-type distributed transaction using `dtmgrpc.NewMsgGrpc`. The example shows adding transaction steps by dynamically calling Go-Zero service methods. ```go // 下面这行导入gozero的dtm驱动 import _ "github.com/dtm-labs/driver-gozero" // dtm已经通过前面的配置,注册到下面这个地址,因此在dtmgrpc中使用该地址 var dtmServer = "etcd://localhost:2379/dtmservice" // 下面从配置文件中Load配置,然后通过BuildTarget获得业务服务的地址 var c zrpc.RpcClientConf conf.MustLoad(*configFile, &c) busiServer, err := c.BuildTarget() // 使用dtmgrpc生成一个消息型分布式事务并提交 gid := dtmgrpc.MustGenGid(dtmServer) msg := dtmgrpc.NewMsgGrpc(dtmServer, gid). // 事务的第一步为调用trans.TransSvcClient.TransOut // 可以从trans.pb.go中找到上述方法对应的Method名称为"/trans.TransSvc/TransOut" // dtm需要从dtm服务器调用该方法,所以不走强类型 // 而是走动态的url: busiServer+"/trans.TransSvc/TransOut" Add(busiServer+"/trans.TransSvc/TransOut", &busi.BusiReq{Amount: 30, UserId: 1}). Add(busiServer+"/trans.TransSvc/TransIn", &busi.BusiReq{Amount: 30, UserId: 2}) err := msg.Submit() ``` -------------------------------- ### Install XORM with DTM Compatibility Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/sdk.md This bash command updates the XORM library to a specific commit (`7cd6a74c9f`) that includes a recently merged PR exposing `sql.Tx`, which is necessary for DTM integration. Users should install this version as it's not yet part of a released XORM version. ```Bash go get -u xorm.io/xorm@7cd6a74c9f ``` -------------------------------- ### Kratos DTM Go Client Integration with Consul Registry Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/kratos.md Go code demonstrating how to integrate DTM with a Kratos application using Consul as the service registry. It shows importing necessary Consul-related packages and initializing the Consul client and registry, following a similar pattern to the etcd setup. ```go import( consulAPI "github.com/hashicorp/consul/api" consul "github.com/go-kratos/kratos/contrib/registry/consul/v2" // ... other imports ) var consulServer = "localhost:2379" // Create registry using Kratos method, https://go-kratos.dev/docs/component/registry/ client, err := consulAPI.New(consulAPI.Config{ Endpoints: strings.Split(consulServer, ","), }) if err != nil { panic(err) } registry := consul.New(client) // Register global resolver, now business server can access dtm using discovery:///dtmservice resolver.Register(discovery.NewBuilder(registry, discovery.WithInsecure(true))) // Actual call logic var dtmServer = "discovery:///dtmservice" // Business address, replace 'busi' below with the actual name set during server initialization var busiServer = "discovery:///busi" // ... transaction initiation logic (similar to etcd example) ``` -------------------------------- ### Register DTM Workflow Processing Function (Saga Example) Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/practice/workflow.md This Go code registers a workflow processing function, "wf_saga", which implements a Saga-like pattern for a transfer scenario. It defines OnRollback callbacks for both TransOut and TransIn operations, ensuring compensation actions are automatically invoked if the global transaction rolls back. This registration should occur after the business service starts. ```Go wfName := "wf_saga" err := workflow.Register(wfName, func(wf *workflow.Workflow, data []byte) error { req := MustUnmarshalReqGrpc(data) wf.NewBranch().OnRollback(func(bb *dtmcli.BranchBarrier) error { _, err := busi.BusiCli.TransOutRevert(wf.Context, req) return err }) _, err := busi.BusiCli.TransOut(wf.Context, req) if err != nil { return err } wf.NewBranch().OnRollback(func(bb *dtmcli.BranchBarrier) error { _, err := busi.BusiCli.TransInRevert(wf.Context, req) return err }) _, err = busi.BusiCli.TransIn(wf.Context, req) return err }) ``` -------------------------------- ### Configure DTM with Kratos Driver and etcd Registry Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/kratos.md YAML configuration for DTM to use the Kratos driver and register itself with an etcd service registry. This setup specifies the driver name, the etcd target URL for DTM service registration, and DTM's gRPC endpoint. ```yaml MicroService: Driver: 'dtm-driver-kratos' Target: 'etcd://127.0.0.1:2379/dtmservice' EndPoint: 'grpc://localhost:36790' ``` -------------------------------- ### Execute DTM Workflow Transaction Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/practice/workflow.md This Go example demonstrates how to initiate a DTM workflow. The workflow.Execute function takes the registered workflow name, a unique global transaction ID, and the marshaled request data. The return value indicates the final status of the global transaction (success or rollback). ```Go req := &busi.ReqGrpc{Amount: 30} err = workflow.Execute(wfName, shortuuid.New(), dtmgimp.MustProtoMarshal(req)) ``` -------------------------------- ### Initialize DTM Workflow SDK for gRPC Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/practice/workflow.md This Go snippet demonstrates the initialization of the DTM Workflow SDK for gRPC communication. It requires specifying the DTM server address, the business server address, and a gRPC server instance, enabling the business server to receive callbacks from DTM. ```Go import "github.com/dtm-labs/dtmgrpc/workflow" // 初始化workflow SDK,三个参数分别为: // 第一个参数,dtm服务器地址 // 第二个参数,业务服务器地址 // 第三个参数,grpcServer // workflow的需要从"业务服务器地址"+"grpcServer"上接收dtm服务器的回调 workflow.InitGrpc(dtmGrpcServer, busi.BusiGrpc, gsvr) ``` -------------------------------- ### Kratos DTM Go Client Integration with etcd Registry Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/kratos.md Go code demonstrating how to integrate DTM with a Kratos application using etcd as the service registry. It shows importing necessary packages, initializing the etcd client and registry, registering a global resolver, and initiating a DTM MSG transaction by adding business API calls. ```go import ( "github.com/dtm-labs/client/dtmcli/logger" "github.com/dtm-labs/client/dtmgrpc" // Import kratos dtm driver _ "github.com/dtm-labs/driver-kratos" "github.com/dtm-labs/dtmdriver-clients/busi" "github.com/go-kratos/kratos/contrib/registry/etcd/v2" "github.com/go-kratos/kratos/v2/transport/grpc/resolver/discovery" etcdAPI "go.etcd.io/etcd/client/v3" "google.golang.org/grpc/resolver" "strings" ) var etcdServer = "localhost:2379" // Create registry using Kratos method, https://go-kratos.dev/docs/component/registry/ client, err := etcdAPI.New(etcdAPI.Config{ Endpoints: strings.Split(etcdServer, ","), }) if err != nil { panic(err) } registry := etcd.New(client) // Register global resolver, now business server can access dtm using discovery:///dtmservice resolver.Register(discovery.NewBuilder(registry, discovery.WithInsecure(true))) var dtmServer = "discovery:///dtmservice" // Business address, replace 'busi' below with the actual name set during server initialization, dtm will access busi using the registry var busiServer = "discovery:///busi" // Initiate a msg transaction to ensure TransOut and TransIn are completed gid := dtmgrpc.MustGenGid(dtmServer) m := dtmgrpc.NewMsgGrpc(dtmServer, gid). Add(busiServer+"/api.trans.v1.Trans/TransOut", &busi.BusiReq{Amount: 30, UserId: 1}). Add(busiServer+"/api.trans.v1.Trans/TransIn", &busi.BusiReq{Amount: 30, UserId: 2}) m.WaitResult = true err := m.Submit() logger.FatalIfError(err) ``` -------------------------------- ### Implement DTM Barrier Transaction with XORM Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/sdk.md This Go code shows how to integrate XORM with DTM's barrier transaction. It initializes an XORM engine, creates a session, begins a transaction, and then uses `dtmcli.barrier.Call` with the underlying `sql.Tx` from the XORM session to perform a database update. ```Go x, _ := xorm.NewEngineWithDB("mysql", "dtm", core.FromDB(sdbGet())) se := x.NewSession() defer se.Close() err := se.Begin() if err != nil { return nil, err } // se is a xorm session, the following code shows how to obtain tx return dtmcli.ResultSuccess, barrier.Call(se.Tx().Tx, func(tx1 *sql.Tx) error { _, err := se.Exec("update dtm_busi.user_account set balance = balance + ? where user_id = ?", -req.Amount, 2) return err }) ``` -------------------------------- ### Submitting Ordinary Messages with DTM Go Client Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/practice/msg.md This Go snippet demonstrates how to use DTM's two-phase message to handle an ordinary asynchronous task, such as granting permanent access to e-books. It uses `dtmcli.NewMsg` to define multiple operations (granting two books) and `Submit()` to execute them, providing an asynchronous interface without relying on a traditional message queue. ```Go msg := dtmcli.NewMsg(DtmServer, gid). Add(busi.Busi+"/AuthBook", &Req{UID: 1, BookID: 5}). Add(busi.Busi+"/AuthBook", &Req{UID: 1, BookID: 6}) err := msg.Submit() ``` -------------------------------- ### Implement DTM Barrier Transaction with goqu Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/sdk.md This Go code demonstrates how to use `goqu` with DTM's barrier transaction pattern. It initializes a `goqu` dialect database, obtains a transaction, and then calls `dtmcli.barrier.Call` to ensure atomicity for a database update operation. ```Go dialect := goqu.Dialect("mysql") sdb, err := dbGet().DB.DB() if err != nil { return nil, err } gdb := dialect.DB(sdb) // gdb is a goqu dialect.DB, the following code shows how to obtain tx tx, err := gdb.Begin() return dtmcli.ResultSuccess, barrier.Call(tx, func(tx1 *sql.Tx) error { _, err := tx.Exec("update dtm_busi.user_account set balance = balance + ? where user_id = ?", -req.Amount, 2) return err }) ``` -------------------------------- ### Implement DTM XA Transaction with goqu Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/sdk.md This Go code illustrates how to perform an XA local transaction using `goqu` and `dtmcli.XaLocalTransaction`. It obtains a `goqu` database instance from the provided `sql.DB` and executes a database update within the XA context. ```Go return dtmcli.XaLocalTransaction(c.Request.URL.Query(), BusiConf, func(db *sql.DB, xa *dtmcli.Xa) error { dialect := goqu.Dialect("mysql") godb := dialect.DB(db) _, err := godb.Exec("update dtm_busi.user_account set balance=balance-? where user_id=?", reqFrom(c).Amount, 1) return err }) ``` -------------------------------- ### Initiate a Kratos DTM Distributed Transaction Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/kratos.md Command to run the Kratos application responsible for initiating a distributed transaction via DTM. This command should be executed from the dtmdriver-clients/kratos/app directory. ```shell cd kratos/app && go run main.go ``` -------------------------------- ### Implement DTM XA Transaction with Go-zero Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/sdk.md This Go code demonstrates how to integrate `go-zero` with DTM's XA local transaction. It creates a `SqlConn` from the provided `sql.DB` and performs a database update using `conn.Exec` within the XA context. Requires go-zero >= v1.2.0. ```Go return dtmcli.XaLocalTransaction(c.Request.URL.Query(), BusiConf, func(db *sql.DB, xa *dtmcli.Xa) error { conn := NewSqlConnFromDB(db) _, err := conn.Exec("update dtm_busi.user_account set balance=balance-? where user_id=?", reqFrom(c).Amount, 1) return err }) ``` -------------------------------- ### DTM Microservice Configuration for Go-Zero with Consul Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/gozero.md YAML configuration for DTM to integrate with Go-Zero microservices using Consul as the service discovery mechanism. This configuration specifies the 'dtm-driver-gozero' and the target Consul address for DTM registration. It also notes that for direct connection or Kubernetes deployments, the 'Target' field can be left empty. ```yaml MicroService: Driver: 'dtm-driver-gozero' # 配置dtm使用go-zero的微服务协议 Target: 'consul://localhost:2379/dtmservice' # 把dtm注册到consul的这个地址 EndPoint: 'localhost:36790' # dtm的本地地址 ``` -------------------------------- ### Implement DTM Barrier Transaction with Go-zero Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/sdk.md This Go code illustrates how to use `go-zero`'s `sqlx.SqlConn` with DTM's barrier transaction. It obtains the raw `sql.DB` from `sqlx.SqlConn` and then calls `dtmcli.barrier.CallWithDB` to execute a database update within the barrier transaction. Requires go-zero >= v1.2.0. ```Go // 假设conn为go-zero里面的 sqlx.SqlConn db, err := conn.RawDB() if err != nil { return err } return dtmcli.ResultSuccess, barrier.CallWithDB(db, func(tx *sql.Tx) error { _, err := tx.Exec("update dtm_busi.user_account set balance = balance + ? where user_id = ?", -req.Amount, 2) return err }) ``` -------------------------------- ### Implementing SAGA Transaction in Go Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/practice/saga.md This Go code snippet demonstrates how to integrate a SAGA transaction using the DTM client library. It initializes a new SAGA instance, adds two sub-transactions (TransOut and TransIn) each with a forward action and a compensation action, and then submits the SAGA transaction to the DTM server for execution. The `req` variable defines the request body for the microservices. ```go req := &gin.H{"amount": 30} // 微服务的请求Body // DtmServer为DTM服务的地址 saga := dtmcli.NewSaga(DtmServer, shortuuid.New()). // 添加一个TransOut的子事务,正向操作为url: qsBusi+"/TransOut", 逆向操作为url: qsBusi+"/TransOutCompensate" Add(qsBusi+"/TransOut", qsBusi+"/TransOutCompensate", req). // 添加一个TransIn的子事务,正向操作为url: qsBusi+"/TransIn", 逆向操作为url: qsBusi+"/TransInCompensate" Add(qsBusi+"/TransIn", qsBusi+"/TransInCompensate", req) // 提交saga事务,dtm会完成所有的子事务/回滚所有的子事务 err := saga.Submit() ``` -------------------------------- ### Implementing Stock Deduction and Reversion with DTM Barrier Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/app/order.md These Go code snippets show the implementation of the `stockDeduct` and `stockDeductRevert` API endpoints. The `stockDeduct` function attempts to decrease product stock, returning `dtmcli.ErrFailure` if stock is insufficient, triggering a rollback. The `stockDeductRevert` function compensates by increasing stock. Both operations are wrapped with `common.MustBarrierFrom(c).CallWithDB`, which leverages DTM's sub-transaction barrier to ensure idempotency, precise compensation, and prevent suspension. ```Go app.POST("/api/busi/stockDeduct", common.WrapHandler(func(c *gin.Context) interface{} { req := common.MustGetReq(c) return common.MustBarrierFrom(c).CallWithDB(common.DBGet(), func(tx *sql.Tx) error { affected, err := dtmimp.DBExec(tx, "update busi.stock set stock=stock-?, update_time=now() where product_id=? and stock >= ?", req.ProductCount, req.ProductID, req.ProductCount) if err == nil && affected == 0 { return dtmcli.ErrFailure // not enough stock, return Failure to rollback } return err }) })) ``` ```Go app.POST("/api/busi/stockDeductRevert", common.WrapHandler(func(c *gin.Context) interface{} { req := common.MustGetReq(c) return common.MustBarrierFrom(c).CallWithDB(common.DBGet(), func(tx *sql.Tx) error { _, err := dtmimp.DBExec(tx, "update busi.stock set stock=stock+?, update_time=now() where product_id=?", req.ProductCount, req.ProductID) return err }) })) ``` -------------------------------- ### Implement DTM XA Transaction with XORM Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/sdk.md This Go code demonstrates how to use XORM within a DTM XA local transaction. It initializes an XORM engine from the provided `sql.DB` and executes a database update operation within the XA context. ```Go return dtmcli.XaLocalTransaction(c.Request.URL.Query(), BusiConf, func(db *sql.DB, xa *dtmcli.Xa) error { xdb, _ := xorm.NewEngineWithDB("mysql", "dtm", core.FromDB(db)) _, err := xdb.Exec("update dtm_busi.user_account set balance=balance-? where user_id=?", reqFrom(c).Amount, 1) return err }) ``` -------------------------------- ### Configure DTM with Kratos Driver and Consul Registry Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/kratos.md YAML configuration for DTM to use the Kratos driver and register itself with a Consul service registry. This provides an alternative to etcd, requiring only a change in the Target URL to point to the Consul endpoint. ```yaml MicroService: Driver: 'dtm-driver-kratos' # name of the driver to handle register/discover Target: 'consul://127.0.0.1:8500/dtmservice' # register dtm server to this url EndPoint: 'grpc://localhost:36790' ``` -------------------------------- ### Defining a DTM Saga Transaction for Order Submission Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/app/order.md This Go code defines an API endpoint for submitting an order. It uses DTM's Saga transaction pattern to orchestrate multiple distributed operations: order creation, stock deduction, coupon usage, and payment creation. Each operation includes a corresponding revert action for rollback in case of failure. ```Go app.POST("/api/busi/submitOrder", common.WrapHandler(func(c *gin.Context) interface{} { req := common.MustGetReq(c) saga := dtmcli.NewSaga(conf.DtmServer, "gid-"+req.OrderID). Add(conf.BusiUrl+"/orderCreate", conf.BusiUrl+"/orderCreateRevert", &req). Add(conf.BusiUrl+"/stockDeduct", conf.BusiUrl+"/stockDeductRevert", &req). Add(conf.BusiUrl+"/couponUse", conf.BusiUrl+"couponUseRevert", &req). Add(conf.BusiUrl+"/payCreate", conf.BusiUrl+"/payCreateRevert", &req) return saga.Submit() })) ``` -------------------------------- ### Configuring Concurrent SAGA Branches in Go Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/practice/saga.md This Go code snippet demonstrates how to enable concurrent execution for SAGA transaction branches. By calling `EnableConcurrent()`, the DTM server will execute the defined sub-transactions (e.g., booking tickets and hotel) in parallel, optimizing performance for scenarios where immediate confirmation is not required. ```go saga := dtmcli.NewSaga(DtmServer, gid). Add(Busi+"/BookTicket", Busi+"/BookTicketRevert", bookTicketInfo1). Add(Busi+"/BookHotel", Busi+"/BookHotelRevert", bookHotelInfo2). Add(Busi+"/BookTicket", Busi+"/BookTicketRevert", bookTicketBackInfo3) saga.EnableConcurrent() ``` -------------------------------- ### DTM Sub-transaction Barrier Go API: BranchBarrier.CallWithDB Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/practice/barrier.md The `BranchBarrier.CallWithDB` method is a core component of DTM's sub-transaction barrier technology, designed to simplify distributed transaction development by automatically handling empty compensation, hanging, and idempotency issues. Developers integrate their business logic within the `busiCall` parameter, and the barrier ensures correct execution across various distributed transaction scenarios. ```Go func (bb *BranchBarrier) CallWithDB(db *sql.DB, busiCall BusiFunc) error ``` ```APIDOC Method: BranchBarrier.CallWithDB Description: Integrates business logic with the sub-transaction barrier. Parameters: db: *sql.DB (Database connection for the local transaction) busiCall: BusiFunc (A function containing the actual business logic) Returns: error: An error if the operation fails. Guarantees: - busiCall is not invoked in empty compensation or hanging scenarios. - Idempotency control ensures busiCall is submitted only once for repeated calls. - Manages TCC, SAGA, and transaction messages. ``` -------------------------------- ### Configure gRPC Client with DTM Workflow Interceptor Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/practice/workflow.md This Go snippet shows how to integrate the workflow.Interceptor into a gRPC client connection. This interceptor is crucial for DTM's workflow mechanism, as it automatically records RPC call results to the DTM server, enabling idempotency and proper retry handling for distributed transactions. ```Go conn1, err := grpc.Dial(busi.BusiGrpc, grpc.WithUnaryInterceptor(workflow.Interceptor), nossl) busi.BusiCli = busi.NewBusiClient(conn1) ``` -------------------------------- ### Simulating TCC Sub-transaction Failure with Barrier in Go Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/guide/e-tcc.md This Go code snippet shows an enhanced simulation of a TCC 'Try' phase failure, incorporating the sub-transaction barrier technology. Even with an immediate failure return, the barrier ensures that the `tccAdjustTrading` operation is correctly handled, preventing data inconsistencies during rollback. ```Go app.POST(BusiAPI+"/TccBTransInTry", dtmutil.WrapHandler2(func(c *gin.Context) interface{} { bb := MustBarrierFromGin(c) bb.Call(txGet(), func(tx *sql.Tx) error { return tccAdjustTrading(tx, TransInUID, req.Amount) }) return dtmcli.ErrFailure })) ``` -------------------------------- ### Register TCC Branch Request Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/http.md Registers a TCC (Try-Confirm-Cancel) branch with the DTM server. This request specifies the URLs for the `cancel` and `confirm` operations, along with any `data` that needs to be passed to these operations. The `gid` identifies the global transaction. ```bash curl --location --request POST 'localhost:36789/api/dtmsvr/registerTccBranch' \ --header 'Content-Type: application/json' \ --data-raw '{ "branch_id":"01", "cancel":"http://localhost:8081/api/busi/TransOutRevert", "confirm":"http://localhost:8081/api/busi/TransOutConfirm", "data":"{\"amount\":30,\"transInResult\":\"\",\"transOutResult\":\"\"}", "gid":"c0a8038b_4nxEEGy7W5h", "trans_type":"tcc" }' ``` ```JSON { "dtm_result":"SUCCESS" } ``` -------------------------------- ### Configuring SAGA Branch for Failure Rollback in Go Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/practice/saga.md This Go code snippet shows how to configure a SAGA transaction branch to simulate a failure, triggering the rollback mechanism. By passing a `TransInResult` of 'FAILURE' in the request body for the 'TransIn' sub-transaction, DTM will detect the failure and initiate compensation operations for all previously successful branches. ```go Add(qsBusi+"/TransIn", qsBusi+"/TransInCompensate", &TransReq{Amount: 30, TransInResult: "FAILURE"}) ``` -------------------------------- ### Simulating TCC Sub-transaction Failure in Go Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/guide/e-tcc.md This Go code snippet demonstrates how to simulate a failure in a TCC 'Try' phase. It sets up a POST endpoint for `TccBTransInTry` that immediately returns `dtmcli.ErrFailure`, triggering a global transaction rollback. ```Go app.POST(BusiAPI+"/TccBTransInTry", dtmutil.WrapHandler2(func(c *gin.Context) interface{} { return dtmcli.ErrFailure })) ``` -------------------------------- ### Configure DTM Transaction Options Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/http.md This section details various options that can be configured for DTM transactions, such as `wait_result` for synchronous processing, `retry_interval` for cron job retries, `timeout_to_fail` for transaction failure timeout, and `branch_headers` for custom headers passed to branches. These options are typically sent during the `prepare` or `submit` phases of a transaction. ```APIDOC Transaction Options: wait_result: boolean - If true, the client waits for the transaction result. retry_interval: integer - The interval (in seconds) for cron job retries. timeout_to_fail: integer - The time (in seconds) after which the transaction will be marked as failed if not completed. branch_headers: object - Custom headers to be passed to branch operations. ``` ```bash curl --location --request POST 'localhost:36789/api/dtmsvr/prepare' \ --header 'Content-Type: application/json' \ --data-raw '{ "gid": "xxx", "trans_type": "tcc", "wait_result": true, "retry_interval": 15, "branch_headers":{"test_header":"test"}, "timeout_to_fail": 60 }' ``` ```JSON { "dtm_result":"SUCCESS" } ``` -------------------------------- ### DTM Sub-transaction Barrier Database Schema: dtm_barrier Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/practice/barrier.md The `dtm_barrier` table is a crucial component of the sub-transaction barrier mechanism. It stores the state of each branch operation, leveraging a unique key to enforce idempotency and correctly manage empty compensation and hanging scenarios. ```APIDOC Database Table: dtm_barrier Purpose: Manages branch operation states for distributed transactions. Key Constraint: Unique Key: (global_transaction_id, branch_id, branch_operation_type) - global_transaction_id: Identifier for the global distributed transaction. - branch_id: Identifier for the specific branch within the global transaction. - branch_operation_type: Type of the branch operation ('try', 'confirm', 'cancel'). Mechanism: - `INSERT IGNORE` on this unique key is used for idempotency control. - Specific inserts for 'cancel' and 'try' operations are used to detect and prevent empty compensation and hanging. ``` -------------------------------- ### Batch Query DTM Transactions Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/http.md This API allows for batch querying of transactions. DTM returns up to 100 transactions with IDs less than `last_id`, sorted in descending order by ID. This is useful for pagination or retrieving a list of recent transactions. ```APIDOC API Name: all Request Method: GET Request Format: - Applicable Transaction Types: - Parameters: last_id: string - The minimum ID from the previous request's returned data, used for pagination. If empty, starts from the latest. ``` ```bash curl 'localhost:36789/api/dtmsvr/all?last_id=' ``` ```JSON { "transactions":[ { "ID":69, "CreateTime":"2021-10-25T08:51:27+08:00", "UpdateTime":"2021-10-25T08:51:39+08:00", "gid":"xxx", "trans_type":"tcc", "data":"", "status":"failed", "query_prepared":"", "protocol":"http", "CommitTime":null, "FinishTime":null, "RollbackTime":"2021-10-25T08:51:39+08:00", "Options":"{}", "NextCronInterval":10, "NextCronTime":"2021-10-25T08:51:49+08:00" } ] } ``` ```JSON { "transactions":[ ] } ``` -------------------------------- ### Query DTM Transaction by GID Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/ref/http.md This API allows querying the status and details of a specific distributed transaction using its global transaction ID (GID). It returns information about the transaction's state, creation time, and associated branches. If the GID is not found, the transaction object will be null. ```APIDOC API Name: query Request Method: GET Request Format: - Applicable Transaction Types: - Parameters: gid: string - The global transaction ID to query. ``` ```bash curl 'localhost:36789/api/dtmsvr/query?gid=xxx' ``` ```JSON { "branches":[ ], "transaction":{ "ID":69, "CreateTime":"2021-10-25T08:51:27+08:00", "UpdateTime":"2021-10-25T08:51:39+08:00", "gid":"xxx", "trans_type":"tcc", "data":"", "status":"failed", "query_prepared":"", "protocol":"http", "CommitTime":null, "FinishTime":null, "RollbackTime":"2021-10-25T08:51:39+08:00", "Options":"{}", "NextCronInterval":10, "NextCronTime":"2021-10-25T08:51:49+08:00" } } ``` ```JSON { "branches":[ ], "transaction":null } ``` -------------------------------- ### Configuring Fixed Interval Retry for SAGA Branches in Go Source: https://github.com/dtm-labs/dtm.pub/blob/main/docs/practice/saga.md This Go code snippet illustrates how to set a fixed retry interval for SAGA transaction branches, which is crucial for operations with non-instantaneous results like booking confirmations. By setting `RetryInterval` and returning 'ONGOING' from the branch function, DTM will retry the branch at the specified interval until a final success or failure status is received, ensuring timely user notifications. ```go saga.RetryInterval = 60 saga.Submit() // ........ func bookTicket() string { order := loadOrder() if order == nil { // 尚未下单,进行第三方下单操作 order = submitTicketOrder() order.save() } order.Query() // 查询第三方订单状态 return order.Status // 成功-SUCCESS 失败-FAILURE 进行中-ONGOING } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.