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]

Reply via email to