go回滚不了,请教下是什么问题?
Opened this issue · 2 comments
BlackAntSir commented
代码如下:
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下面有许多的例子,参考例子做一下实验。如果你的问题能够通过例子复现,那么就容易解决了
furucong commented
要想实现回滚,rpc.UserClient.CreateUser()返回的gRPC状态码必须是ABORTED(10)