This is an automated email from the ASF dual-hosted git repository.
thunguo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-seata-go-samples.git
The following commit(s) were added to refs/heads/main by this push:
new ed0c37a feature: add RocketMQ TCC sample with fence integration (#88)
ed0c37a is described below
commit ed0c37add962f6559f206863758caea0c85bec8c
Author: CAICAII <[email protected]>
AuthorDate: Thu Jul 9 20:04:56 2026 +0800
feature: add RocketMQ TCC sample with fence integration (#88)
* feature: add RocketMQ TCC sample with fence integration
This sample demonstrates how to use Seata-Go's RocketMQ TCC integration for
distributed transactional messaging:
- Send RocketMQ transactional messages within Seata global transactions
- TCC (Try-Confirm-Cancel) pattern for message reliability
- Idempotency protection using TCC fence mechanism
- Both commit and rollback scenarios via --mode flag
* refactor: remove double TCC wrapping in rocketmq sample
- Remove redundant TCC service wrapper layer
- Remove fence table (handled by TCC framework)
- Use SDK's producer.Send() directly
- Pass correct *primitive.Message type
- Update README with correct architecture
* fix: comment out local replace directive for CI compatibility
* fix: remove unsupported skip-go-installation parameter
* Revert "fix: remove unsupported skip-go-installation parameter"
This reverts commit 35456086544ab10f5afa8c52739c296da3a75846.
* Revert "fix: comment out local replace directive for CI compatibility"
* fix: remove invalid v2 pseudo-version dependency
---
go.mod | 8 ++-
go.sum | 21 +++++++
tcc/rocketmq/README.md | 152 +++++++++++++++++++++++++++++++++++++++++++++++
tcc/rocketmq/cmd/main.go | 112 ++++++++++++++++++++++++++++++++++
4 files changed, 292 insertions(+), 1 deletion(-)
diff --git a/go.mod b/go.mod
index c1b7e23..cca9d95 100644
--- a/go.mod
+++ b/go.mod
@@ -4,6 +4,7 @@ go 1.20
require (
dubbo.apache.org/dubbo-go/v3 v3.1.1
+ github.com/apache/rocketmq-client-go/v2 v2.1.2
github.com/gin-gonic/gin v1.9.1
github.com/go-sql-driver/mysql v1.7.0
github.com/parnurzeal/gorequest v0.2.16
@@ -18,8 +19,13 @@ require (
cloud.google.com/go/compute v1.20.1 // indirect
github.com/antlr/antlr4/runtime/Go/antlr/v4
v4.0.0-20230305170008-8188dc5388df // indirect
github.com/google/cel-go v0.18.0 // indirect
+ github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/robertkrimen/otto v0.4.0 // indirect
+ github.com/sirupsen/logrus v1.8.1 // indirect
github.com/stoewer/go-strcase v1.2.0 // indirect
+ github.com/tidwall/gjson v1.13.0 // indirect
+ github.com/tidwall/match v1.1.1 // indirect
+ github.com/tidwall/pretty v1.2.0 // indirect
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 // indirect
google.golang.org/genproto/googleapis/api
v0.0.0-20230803162519-f966b187b2e5 // indirect
google.golang.org/genproto/googleapis/rpc
v0.0.0-20230803162519-f966b187b2e5 // indirect
@@ -167,4 +173,4 @@ require (
)
// For local testing only.
-//replace seata.apache.org/seata-go => ../incubator-seata-go
+// replace seata.apache.org/seata-go => ../incubator-seata-go
diff --git a/go.sum b/go.sum
index 837ed75..c12d3be 100644
--- a/go.sum
+++ b/go.sum
@@ -391,6 +391,7 @@ dubbo.apache.org/dubbo-go/v3 v3.1.1
h1:ApofZ45tIH1WCsJjibXHuz3ltiR3ExpNP/hkTBD+n
dubbo.apache.org/dubbo-go/v3 v3.1.1/go.mod
h1:5YAAJShCNV+NaFKzbqcvc7nVt2+0804oFS/3XOmf+Ow=
github.com/BurntSushi/toml v0.3.1/go.mod
h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.1.0
h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
+github.com/BurntSushi/toml v1.1.0/go.mod
h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod
h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DATA-DOG/go-sqlmock v1.5.0
h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod
h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
@@ -434,6 +435,8 @@ github.com/apache/dubbo-go-hessian2 v1.9.1/go.mod
h1:xQUjE7F8PX49nm80kChFvepA/Av
github.com/apache/dubbo-go-hessian2 v1.9.3/go.mod
h1:xQUjE7F8PX49nm80kChFvepA/AvqAZ0oh/UaB6+6pBE=
github.com/apache/dubbo-go-hessian2 v1.12.2
h1:2/56JRPng2lnLziJF3fqmSgsg28Yt1a5YZ5RX+jHDGs=
github.com/apache/dubbo-go-hessian2 v1.12.2/go.mod
h1:QP9Tc0w/B/mDopjusebo/c7GgEfl6Lz8jeuFg8JA6yw=
+github.com/apache/rocketmq-client-go/v2 v2.1.2
h1:yt73olKe5N6894Dbm+ojRf/JPiP0cxfDNNffKwhpJVg=
+github.com/apache/rocketmq-client-go/v2 v2.1.2/go.mod
h1:6I6vgxHR3hzrvn+6n/4mrhS+UTulzK/X9LB2Vk1U5gE=
github.com/apache/thrift v0.12.0/go.mod
h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod
h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/arana-db/parser v0.2.17
h1:4wNfSgza2N3pjpwR5jmWLvu4L6Sme6EtoLuZOgwWlsU=
@@ -543,6 +546,7 @@ github.com/davecgh/go-spew v1.1.0/go.mod
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1
h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod
h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod
h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod
h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dlclark/regexp2 v1.7.0
h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo=
github.com/dlclark/regexp2 v1.7.0/go.mod
h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
@@ -580,6 +584,7 @@ github.com/elazarl/goproxy
v0.0.0-20221015165544-a0805db90819/go.mod h1:Ro8st/El
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod
h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/emicklei/go-restful/v3 v3.10.1
h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ=
github.com/emicklei/go-restful/v3 v3.10.1/go.mod
h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
+github.com/emirpasic/gods v1.12.0/go.mod
h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/envoyproxy/go-control-plane v0.6.9/go.mod
h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod
h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane
v0.9.1-0.20191026205805-5f8ba28d4473/go.mod
h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@@ -663,6 +668,7 @@ github.com/go-playground/universal-translator
v0.18.1/go.mod h1:xekY+UJKNuX9WP91
github.com/go-playground/validator/v10 v10.12.0/go.mod
h1:hCAPuzYvKdP33pxWa+2+6AIKXEKqjIUyqsNCtbsSJrA=
github.com/go-playground/validator/v10 v10.14.0
h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
github.com/go-playground/validator/v10 v10.14.0/go.mod
h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
+github.com/go-redis/redis/v8 v8.11.5/go.mod
h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-resty/resty/v2 v2.7.0
h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
github.com/go-resty/resty/v2 v2.7.0/go.mod
h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
github.com/go-sql-driver/mysql v1.4.0/go.mod
h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
@@ -773,6 +779,7 @@ github.com/google/pprof
v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod
h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod
h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod
h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod
h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod
h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod
h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod
h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
@@ -1080,10 +1087,13 @@ github.com/onsi/ginkgo v1.7.0/go.mod
h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
github.com/onsi/ginkgo v1.12.1/go.mod
h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4/go.mod
h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5/go.mod
h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
+github.com/onsi/ginkgo/v2 v2.0.0/go.mod
h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/gomega v1.4.3/go.mod
h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod
h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod
h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.16.0/go.mod
h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
+github.com/onsi/gomega v1.17.0/go.mod
h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
+github.com/onsi/gomega v1.18.1/go.mod
h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod
h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opentracing-contrib/go-observer
v0.0.0-20170622124052-a52f23424492/go.mod
h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
github.com/opentracing/basictracer-go v1.0.0/go.mod
h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
@@ -1102,6 +1112,8 @@ github.com/parnurzeal/gorequest v0.2.16
h1:T/5x+/4BT+nj+3eSknXmCTnEVGSzFzPGdpqmU
github.com/parnurzeal/gorequest v0.2.16/go.mod
h1:3Kh2QUMJoqw3icWAecsyzkpY7UzRfDhbRdTjtNwNiUE=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod
h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0/go.mod
h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
+github.com/patrickmn/go-cache v2.1.0+incompatible
h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
+github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod
h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pborman/uuid v1.2.0/go.mod
h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod
h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.7.0/go.mod
h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
@@ -1218,6 +1230,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod
h1:1NzhyTcUVG4SuEtjjoZeV
github.com/sijms/go-ora/v2 v2.5.17
h1:7FS8vswmAHint/r/fmgpKEczBnLZH64PNSkTiVradhY=
github.com/sijms/go-ora/v2 v2.5.17/go.mod
h1:EHxlY6x7y9HAsdfumurRfTd+v8NrEOTR3Xl4FWlH6xk=
github.com/sirupsen/logrus v1.2.0/go.mod
h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.0/go.mod
h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod
h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod
h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod
h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
@@ -1271,6 +1284,12 @@ github.com/stretchr/testify v1.8.3
h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gt
github.com/stretchr/testify v1.8.3/go.mod
h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/subosito/gotenv v1.2.0/go.mod
h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tebeka/strftime v0.1.3/go.mod
h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIUJUJH6XQ=
+github.com/tidwall/gjson v1.13.0
h1:3TFY9yxOQShrvmjdM76K+jc66zJeT6D3/VFFYCGQf7M=
+github.com/tidwall/gjson v1.13.0/go.mod
h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
+github.com/tidwall/match v1.1.1/go.mod
h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
+github.com/tidwall/pretty v1.2.0
h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
+github.com/tidwall/pretty v1.2.0/go.mod
h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tklauser/go-sysconf v0.3.6/go.mod
h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
github.com/tklauser/go-sysconf v0.3.9/go.mod
h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
github.com/tklauser/go-sysconf v0.3.10
h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
@@ -1377,6 +1396,7 @@ go.opentelemetry.io/proto/otlp v0.19.0/go.mod
h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI
go.uber.org/atomic v1.3.2/go.mod
h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod
h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod
h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
+go.uber.org/atomic v1.5.1/go.mod
h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.6.0/go.mod
h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0/go.mod
h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.9.0/go.mod
h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
@@ -2162,6 +2182,7 @@ sigs.k8s.io/yaml v1.1.0/go.mod
h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod
h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
+stathat.com/c/consistent v1.0.0/go.mod
h1:QkzMWzcbB+yQBL2AttO6sgsQS/JSTapcDISJalmCDS0=
vimagination.zapto.org/byteio v0.0.0-20200222190125-d27cba0f0b10
h1:pxt6fVJP67Hxo1qk8JalUghLlk3abYByl+3e0JYfUlE=
vimagination.zapto.org/byteio v0.0.0-20200222190125-d27cba0f0b10/go.mod
h1:fl9OF22g6MTKgvHA1hqMXe/L7+ULWofVTwbC9loGu7A=
vimagination.zapto.org/memio v0.0.0-20200222190306-588ebc67b97d
h1:Mp6WiHHuiwHaknxTdxJ8pvC9/B4pOgW1PamKGexG7Fs=
diff --git a/tcc/rocketmq/README.md b/tcc/rocketmq/README.md
new file mode 100644
index 0000000..be8ab70
--- /dev/null
+++ b/tcc/rocketmq/README.md
@@ -0,0 +1,152 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+# RocketMQ TCC Sample
+
+This sample demonstrates how to use Seata-Go's RocketMQ integration for
distributed transactional messaging.
+
+## Use Case Description
+
+This sample showcases:
+- Sending RocketMQ transactional messages within Seata global transactions
+- Automatic TCC (Try-Confirm-Cancel) handling by the SDK
+- Both commit and rollback scenarios
+
+## Key Teaching Point
+
+**The RocketMQ integration has TCC built-in.** When you call
`producer.Send(ctx, msg)` inside a global transaction, the SDK automatically:
+1. Detects the global transaction context via `tm.IsGlobalTx(ctx)`
+2. Invokes its internal TCC proxy to register a branch transaction
+3. Sends a half-message to RocketMQ (Prepare phase)
+4. Delegates Commit/Rollback to RocketMQ's transaction listener based on
global transaction outcome
+
+**You do NOT need to create a TCC service wrapper** - just use the producer
directly.
+
+## Architecture
+
+```
+main.go
+ ↓
+tm.WithGlobalTx() ← Global Transaction Boundary
+ ↓
+producer.Send(ctx, msg) ← SDK auto-applies TCC
+ ↓
+[SDK Internal] tccProxy.Prepare() → RocketMQ half-message
+ ↓
+[On Commit] → TransactionListener → Message becomes consumable
+[On Rollback] → TransactionListener → Message deleted
+```
+
+## Prerequisites
+
+1. **Seata TC Server**
+ - Version: Compatible with seata-go v2.x
+ - Address: `127.0.0.1:8091`
+
+2. **RocketMQ**
+ - Version: 4.x or 5.x
+ - NameServer: `127.0.0.1:9876`
+ - Broker running
+
+## Setup Steps
+
+### 1. Start Infrastructure
+
+```bash
+# Start Seata Server and RocketMQ using docker-compose
+cd ../../dockercompose
+docker-compose up -d
+```
+
+### 2. Run the Sample
+
+**Commit Scenario** (message will be sent and committed):
+```bash
+cd cmd
+go run main.go --mode=commit
+```
+
+**Rollback Scenario** (message will be sent but rolled back):
+```bash
+cd cmd
+go run main.go --mode=rollback
+```
+
+## Expected Behavior
+
+### Commit Mode
+1. Application starts global transaction (XID logged)
+2. `producer.Send()` is called → SDK internally calls `tccProxy.Prepare()`
+3. RocketMQ half-message sent (not consumable yet)
+4. Business function returns `nil` → global transaction commits
+5. RocketMQ TransactionListener receives commit signal
+6. Message becomes consumable
+7. Consumers can now receive the message
+
+### Rollback Mode
+1. Application starts global transaction (XID logged)
+2. `producer.Send()` is called → SDK internally calls `tccProxy.Prepare()`
+3. RocketMQ half-message sent
+4. Business function returns `error` → global transaction rolls back
+5. RocketMQ TransactionListener receives rollback signal
+6. Message is deleted/canceled
+7. Message never becomes consumable
+
+## Verification
+
+Check Seata TC server logs for branch registration:
+```
+Branch registered: xid=..., branchId=..., resourceId=RocketMQTCC
+```
+
+Check RocketMQ console or CLI tools to verify message visibility:
+- Commit mode: Message appears in topic `seata-tcc-test`
+- Rollback mode: No message in topic
+
+## Code Walkthrough
+
+```go
+// Create producer - SDK creates internal TCC proxy
+producer, _ := rocketmq.NewSeataMQProducer(cfg)
+producer.Start()
+
+// Execute global transaction
+tm.WithGlobalTx(ctx, config, func(ctx context.Context) error {
+ // Direct SDK usage - no wrapper needed
+ msg := primitive.NewMessage("topic", payload)
+ _, err := producer.Send(ctx, msg) // SDK handles TCC automatically
+
+ if mode == "rollback" {
+ return fmt.Errorf("trigger rollback") // Error triggers rollback
+ }
+ return nil // Success triggers commit
+})
+```
+
+## Troubleshooting
+
+**Issue**: `seata server not available`
+- Check Seata TC server is running on `127.0.0.1:8091`
+- Verify `conf/seatago.yml` configuration
+
+**Issue**: `RocketMQ connection failed`
+- Ensure RocketMQ NameServer and Broker are running
+- Check network connectivity to `127.0.0.1:9876`
+
+**Issue**: `params must be *primitive.Message`
+- This error indicates incorrect SDK usage
+- Always pass `*primitive.Message` to `producer.Send()`, not other types
diff --git a/tcc/rocketmq/cmd/main.go b/tcc/rocketmq/cmd/main.go
new file mode 100644
index 0000000..3f7009e
--- /dev/null
+++ b/tcc/rocketmq/cmd/main.go
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+ "context"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "os"
+ "time"
+
+ "github.com/apache/rocketmq-client-go/v2/primitive"
+ "seata.apache.org/seata-go/v2/pkg/client"
+ "seata.apache.org/seata-go/v2/pkg/integration/rocketmq"
+ "seata.apache.org/seata-go/v2/pkg/tm"
+ "seata.apache.org/seata-go/v2/pkg/util/log"
+)
+
+var (
+ mode = flag.String("mode", "commit", "Transaction mode: commit or
rollback")
+)
+
+func main() {
+ flag.Parse()
+
+ // Initialize Seata client
+ client.InitPath("../../../conf/seatago.yml")
+
+ // Create RocketMQ producer
+ // Note: SeataMQProducer internally creates TCC proxy - no need to wrap
it again
+ cfg := rocketmq.NewDefaultSeataMQProducerConfig()
+ cfg.NameServerAddrs = []string{"127.0.0.1:9876"}
+ cfg.GroupName = "seata-tcc-producer-group"
+ cfg.InstanceName = "seata-tcc-producer-instance"
+
+ producer, err := rocketmq.NewSeataMQProducer(cfg)
+ if err != nil {
+ log.Errorf("Create producer failed: %v", err)
+ os.Exit(1)
+ }
+
+ if err := producer.Start(); err != nil {
+ log.Errorf("Start producer failed: %v", err)
+ os.Exit(1)
+ }
+ defer producer.Shutdown()
+
+ // Execute global transaction
+ err = tm.WithGlobalTx(context.Background(), &tm.GtxConfig{
+ Name: "RocketMQTCCSample",
+ Timeout: 60000,
+ }, func(ctx context.Context) error {
+ return sendMessage(ctx, producer, *mode)
+ })
+
+ if err != nil {
+ log.Errorf("Global transaction failed: %v", err)
+ os.Exit(1)
+ }
+
+ log.Infof("Global transaction completed successfully in %s mode", *mode)
+}
+
+func sendMessage(ctx context.Context, producer *rocketmq.SeataMQProducer, mode
string) error {
+ xid := tm.GetXID(ctx)
+ log.Infof("Sending message in %s mode, XID: %s", mode, xid)
+
+ // Prepare message payload
+ payload, _ := json.Marshal(map[string]interface{}{
+ "mode": mode,
+ "timestamp": time.Now().Unix(),
+ "message": "RocketMQ TCC test message",
+ "xid": xid,
+ })
+
+ msg := primitive.NewMessage("seata-tcc-test", payload)
+ msg.WithTag("TCC_TEST")
+
+ // SDK auto-detects global transaction context and applies TCC
automatically
+ // When tm.IsGlobalTx(ctx) is true, producer.Send() internally calls
tccProxy.Prepare()
+ result, err := producer.Send(ctx, msg)
+ if err != nil {
+ log.Errorf("Send message failed: %v", err)
+ return err
+ }
+
+ log.Infof("Message sent successfully, msgId=%s, offsetMsgId=%s",
result.MsgID, result.OffsetMsgID)
+
+ // Simulate rollback scenario by returning error
+ if mode == "rollback" {
+ log.Infof("Simulating rollback scenario")
+ return fmt.Errorf("simulated rollback scenario")
+ }
+
+ return nil
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]