首页 > 其他分享 >Go+seata实现分布式事务-tcc

Go+seata实现分布式事务-tcc

时间:2024-04-26 13:44:06浏览次数:24  
标签:github seata err go pkg Go com tcc

上篇用的ta跟xa。这次试试tcc

client

package main

import (
	"context"
	"flag"
	"fmt"
	"net/http"
	"time"

	"github.com/parnurzeal/gorequest"

	"github.com/seata/seata-go/pkg/client"
	"github.com/seata/seata-go/pkg/constant"
	"github.com/seata/seata-go/pkg/tm"
	"github.com/seata/seata-go/pkg/util/log"
)

func main() {
	flag.Parse()
	client.InitPath("../../../conf/seatago.yml")
	bgCtx, cancel := context.WithTimeout(context.Background(), time.Minute*10)
	defer cancel()
	serverIpPort := "http://127.0.0.1:8080"
	var jsonData = map[string]interface{}{
		"name": "xxJohn",
		"age":  6000,
	}
	tm.WithGlobalTx(
		bgCtx,
		&tm.GtxConfig{
			Name: "TccSampleLocalGlobalTx",
		},
		func(ctx context.Context) (re error) {
			request := gorequest.New()
			log.Infof("branch transaction begin")
			request.Post(serverIpPort+"/prepare").Send(jsonData).
				Set("Content-Type", "application/json").
				Set(constant.XidKey, tm.GetXID(ctx)).
				End(func(response gorequest.Response, body string, errs []error) {
					if response.StatusCode != http.StatusOK {
						re = fmt.Errorf("update data fail")
					}
				})
			return
		})
}

server

package main

import (
	"fmt"
	"net/http"

	"github.com/gin-gonic/gin"
    "github.com/seata/seata-go/pkg/tm"
	"github.com/seata/seata-go/pkg/client"
	ginmiddleware "github.com/seata/seata-go/pkg/integration/gin"
	"github.com/seata/seata-go/pkg/rm/tcc"
	"github.com/seata/seata-go/pkg/util/log"
)

func main() {
	client.InitPath("../../../conf/seatago.yml")

	r := gin.Default()

	r.Use(ginmiddleware.TransactionMiddleware())

	userProviderProxy, err := tcc.NewTCCServiceProxy(&RMService{})
	if err != nil {
		log.Errorf("get userProviderProxy tcc service proxy error, %v", err.Error())
		return
	}
	// 定义 JSON 数据的结构体
	type Person struct {
		Name string `json:"name"`
		Age  int    `json:"age"`
	}

	r.POST("/prepare", func(c *gin.Context) {
		var person Person
		// 绑定请求体到 person 结构体
		if err := c.BindJSON(&person); err != nil {
			fmt.Println("请求json错误", err)
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}
		c.Set("rollbackData", person)
		if _, err := userProviderProxy.Prepare(c, person); err != nil {
			c.JSON(http.StatusBadRequest, "prepare failure")
			return
		}
		c.JSON(http.StatusOK, "prepare ok")
		//c.JSON(http.StatusBadRequest, "prepare error") // 模拟错误
	})

	if err := r.Run(":8080"); err != nil {
		log.Fatalf("start tcc server fatal: %v", err)
	}
}

type RMService struct {
	Param interface{} //参数保存,防止rollback找不到
}

// 预提交事务,把参数保存起来
func (b *RMService) Prepare(ctx context.Context, params interface{}) (bool, error) {
	b.Param = params
	log.Infof("TRMService Prepare, param %v", params)
	return true, nil
}
// 提交
func (b *RMService) Commit(ctx context.Context, businessActionContext *tm.BusinessActionContext) (bool, error) {
	log.Infof("RMService Commit, param %v", businessActionContext)
	return true, nil
}
// 回滚
func (b *RMService) Rollback(ctx context.Context, businessActionContext *tm.BusinessActionContext) (bool, error) {
	log.Infof("RMService Rollback, param %v", b.Param)
	return true, nil
}

func (b *RMService) GetActionName() string {
	return "ginTccRMService"
}

标签:github,seata,err,go,pkg,Go,com,tcc
From: https://www.cnblogs.com/qcy-blog/p/18159878

相关文章

  • Godot中设置Sprite2D节点透明度
    Godot中设置Sprite2D节点透明度该方法可以用于所有CanvasItem​类及其子类···#假设在`CancasItem`节点自身脚本中执行#设置范围0~1##设置自己及子节点modulate.a=0.5##仅设置自己节点的透明度self_modulate.a=0.5#设置范围(0~255)8bit##设置自己及子节点mod......
  • Godot中设置Sprite2D节点透明度
    Godot中设置Sprite2D节点透明度该方法可以用于所有CanvasItem​类及其子类···#假设在`CancasItem`节点自身脚本中执行#设置范围0~1##设置自己及子节点modulate.a=0.5##仅设置自己节点的透明度self_modulate.a=0.5#设置范围(0~255)8bit##设置自己及子节点mod......
  • golang之json.RawMessage
    RawMessage具体来讲是json库中定义的一个类型。它实现了Marshaler接口以及Unmarshaler接口,以此来支持序列化的能力。注意上面我们引用 官方doc 的说明。 使用场景设想一下,我们给某种业务场景定义了一个通用的model,其中部分数据需要在不同场景下对应不同的结构体......
  • GoogleTest
    简单测试使用TEST()宏,其中第一个参数是测试套件名称(对应具体功能),第二个参数是测试用例名称(测试方向,比如测试判断是否为质数的函数,就有测试小数,测试负数,测试正数这三个反向),二者都必须是合法的C++标识符,并且不应该包含下划线。#include<gtest/gtest.h>#include"factorial.h"......
  • 精选 | Google Cloud Next'24 拉斯维加斯会议 BigQuery 连续查询报告
    本篇由CloudAce数据解决方案部高级工程师撰写。 我听说了拉斯维加斯GoogleCloudNext'24举办的“使用BigQuery连续查询构建连续数据和AI管道”(“BuildcontinuousdataandAIpipelineswithBigQuerycontinuousqueries”)会议,我想对此进行报道。 本次会议......
  • MongoDB基础操作
    目录一、什么是MongoDB二、MongoDB与关系型数据库对比三、数据类型四、部署MongoDB1、下载二进制包2、下载安装包并解压3、创建用于存放数据和日志的目录,并修改权限4、启动MongoDB4.1前台启动4.2后台启动4.3、配置文件启动服务4.4、配置systemd服务4.5、systemctl启动MongoDB5、......
  • Go+seata实现分布式事务
    docker安装seataversion:'3'services:seata-server:image:seataio/seata-server:latestports:-"8091:8091"-"7091:7091"environment:-SEATA_PORT=8091-STORE_MODE=filemysql:ima......
  • docker.from_env() 获取docker守护进程时出现 TypeError: load_config() got an unexp
    某天使用python重启docker容器时,出现了一个令人费解的BUG,我的代码为1defrestart_docker(container_name):2#连接到docker守护进程3client=docker.from_env()4try:5#获取容器对象6container=client.containers.get(containe......
  • spannerlib优雅的go异常处理
    蹩脚的go异常处理一般写go的人,如果他不是写算法,正常写业务代码的话,可能都会为优雅的异常处理而烦恼,因为脑子抽筋的go设计者们,总是感觉语法糖是一种很低级的东西。但是在我们大多数公司的业务逻辑中,没有语法糖让代码非常丑陋,不易于维护。如何让go代码更具有可读性,哪么就要给go......
  • Golang - 空指针如何预防
    在Go语言中,空指针是一个常见的运行时错误来源,它通常发生在尝试访问一个未被初始化或已被设置为nil的指针所指向的值。1、凡是有点『.』操作的的行为都要先进行非nil判断:例如,想记录一个err的msg,通过err.Error()就可以获取到err的string类型的错误消息msg,但这里需要对err进行非nil......