dtm-labs/dtm

go回滚不了,请教下是什么问题?

Opened this issue · 2 comments

代码如下:
func CreateByDtm(ctx context.Context) (uint64, error) {
userId = generate.userID() //生成自增ID
userData := user.CreateUserInfoRequest{//省略非重要代码}
storeData := store.CreateStoreInfoRequest{ //省略非重要代码 }

// 初始化 DTM 工作流,三个参数分别为: dtm 服务器地址、业务服务器地址、gRPC 服务器
grpcServer := grpc.NewServer()
//workflow.InitGrpc(dtmutil.DefaultGrpcServer, busi.BusiGrpc, grpcServer)
    workflow.InitGrpc("127.0.0.1:36790", "127.0.0.1:9090", grpcServer)

gid := shortuuid.New()
wfName := fmt.Sprintf("%s-grpc-%s", dtmimp.GetFuncName(), gid)
err := workflow.Register(wfName, func(wf *workflow.Workflow, data []byte) error {
	// 创建用户事务分支
	wf.NewBranch().OnRollback(func(bb *dtmcli.BranchBarrier) error {
		fmt.Println("===CreateUserRevert===")
		// 回滚时删除用户
		_, err := rpc.UserClient.CreateUserRevert(wf.Context, &user.IdRequest{
			Id: userId,
		})
		return err
	})

	// 创建用户
	userInfo, err := rpc.UserClient.CreateUser(wf.Context, &userData)
	if err != nil {
		fmt.Println("用户创建失败:", err)
		return err
	}

	// 创建店铺事务分支
	wf.NewBranch().OnRollback(func(bb *dtmcli.BranchBarrier) error {
		fmt.Println("===CreateStoreRevert===", storeId)
		// 回滚时删除店铺
		_, err = rpc.StoreClient.CreateStoreRevert(wf.Context, &store.StoreIdequest{
			Id: storeId,
		})
		return err
	})

	// 创建店铺--故意触发第二个子事务的失败
	storeInfo, err := rpc.StoreClient.CreateStore(wf.Context, &storeData)
	if err != nil {
		fmt.Println("店铺创建失败:", err)
		return err
	}

	return nil
})

// 事务注册失败返回
if err != nil {
	fmt.Println("事务注册失败:", err.Error())
	return 0, errors.New("事务注册失败")
}

// 事务提交-执行工作流
    data, err := proto.Marshal(&user.IdRequest{Id: userId })
_, err = workflow.ExecuteCtx(context.Background(), wfName, gid, data)
if err != nil {
	fmt.Println("出错:" + err.Error())
	// 处理事务提交失败的情况
	return 0, errors.New("处理事务提交失败的情况")
}

return userId, err

}

func main() {
go busi.RunGrpc(grpcServer)
//注册用户
CreateByDtm(context.Background())
}

成功提交至DTM服务,也正确创建了用户。现在遇到的问题是,当创建店铺事务子步骤失败后,代码没有执行预期的回滚逻辑 wf.NewBranch().OnRollback(...)。而且直接又执行创建用户的正常事务逻辑?请问那里出了问题?

yedf2 commented

当创建店铺事务子步骤失败后,代码没有执行预期的回滚逻辑

你需要按照约定返回失败,其他的失败,DTM不清楚是暂时的失败还是业务真正失败了,所以会不断地尝试

直接又执行创建用户的正常事务逻辑

对于分布式事务来说,需要子业务时幂等的,可以看看dtm相关的文档

dtm-examples下面有许多的例子,参考例子做一下实验。如果你的问题能够通过例子复现,那么就容易解决了

要想实现回滚,rpc.UserClient.CreateUser()返回的gRPC状态码必须是ABORTED(10)