From 382cb5cdfd40ce246fbb9e5ed22e082155bfee92 Mon Sep 17 00:00:00 2001 From: wang1309 <1028960576@qq.com> Date: Fri, 16 Dec 2022 16:02:23 +0800 Subject: [PATCH] Feat xa branch xid (#389) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add xa branch xid Co-authored-by: 王瑞 --- go.mod | 2 + go.sum | 1 + pkg/datasource/sql/xa/xa_branch_xid.go | 129 ++++++++++++++++++++ pkg/datasource/sql/xa/xa_branch_xid_test.go | 46 +++++++ pkg/datasource/sql/xa/xa_xid.go | 30 +++++ pkg/datasource/sql/xa/xa_xid_builder.go | 26 ++++ 6 files changed, 234 insertions(+) create mode 100644 pkg/datasource/sql/xa/xa_branch_xid.go create mode 100644 pkg/datasource/sql/xa/xa_branch_xid_test.go create mode 100644 pkg/datasource/sql/xa/xa_xid.go create mode 100644 pkg/datasource/sql/xa/xa_xid_builder.go diff --git a/go.mod b/go.mod index 93020fe1..bace7086 100644 --- a/go.mod +++ b/go.mod @@ -28,6 +28,7 @@ require ( google.golang.org/grpc v1.49.0 google.golang.org/protobuf v1.28.1 gopkg.in/yaml.v2 v2.4.0 + gotest.tools v2.2.0+incompatible vimagination.zapto.org/byteio v0.0.0-20200222190125-d27cba0f0b10 ) @@ -73,6 +74,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.4 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect diff --git a/go.sum b/go.sum index 85e77822..08702f50 100644 --- a/go.sum +++ b/go.sum @@ -1425,6 +1425,7 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/pkg/datasource/sql/xa/xa_branch_xid.go b/pkg/datasource/sql/xa/xa_branch_xid.go new file mode 100644 index 00000000..52ad1470 --- /dev/null +++ b/pkg/datasource/sql/xa/xa_branch_xid.go @@ -0,0 +1,129 @@ +/* + * 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 xa + +import ( + "strconv" + "strings" +) + +const ( + BranchIdPrefix = "-" + SeataXaXidFormatId = 9752 +) + +type XABranchXid struct { + xid string + branchId int64 + globalTransactionId []byte + branchQualifier []byte +} + +type Option func(*XABranchXid) + +func NewXABranchXid(opt ...Option) *XABranchXid { + xABranchXid := &XABranchXid{} + + for _, fn := range opt { + fn(xABranchXid) + } + + // encode + if (xABranchXid.xid != "" || xABranchXid.branchId != 0) && + len(xABranchXid.globalTransactionId) == 0 && + len(xABranchXid.branchQualifier) == 0 { + encode(xABranchXid) + } + + // decode + if xABranchXid.xid == "" && xABranchXid.branchId == 0 && + (len(xABranchXid.globalTransactionId) > 0 || len(xABranchXid.branchQualifier) > 0) { + decode(xABranchXid) + } + + return xABranchXid +} + +func (x *XABranchXid) GetGlobalXid() string { + return x.xid +} + +func (x *XABranchXid) GetBranchId() int64 { + return x.branchId +} + +func (x *XABranchXid) GetFormatId() int { + return SeataXaXidFormatId +} + +func (x *XABranchXid) GetGlobalTransactionId() []byte { + return x.globalTransactionId +} + +func (x *XABranchXid) GetBranchQualifier() []byte { + return x.branchQualifier +} + +func (x *XABranchXid) String() string { + return x.xid + BranchIdPrefix + strconv.FormatInt(x.branchId, 10) +} + +func WithXid(xid string) Option { + return func(x *XABranchXid) { + x.xid = xid + } +} + +func WithBranchId(branchId int64) Option { + return func(x *XABranchXid) { + x.branchId = branchId + } +} + +func WithGlobalTransactionId(globalTransactionId []byte) Option { + return func(x *XABranchXid) { + x.globalTransactionId = globalTransactionId + } +} + +func WithBranchQualifier(branchQualifier []byte) Option { + return func(x *XABranchXid) { + x.branchQualifier = branchQualifier + } +} + +func encode(x *XABranchXid) { + if x.xid != "" { + x.globalTransactionId = []byte(x.xid) + } + + if x.branchId != 0 { + x.branchQualifier = []byte(BranchIdPrefix + strconv.FormatInt(x.branchId, 10)) + } +} + +func decode(x *XABranchXid) { + if len(x.globalTransactionId) > 0 { + x.xid = string(x.globalTransactionId) + } + + if len(x.branchQualifier) > 0 { + branchId := strings.TrimLeft(string(x.branchQualifier), BranchIdPrefix) + x.branchId, _ = strconv.ParseInt(branchId, 10, 64) + } +} diff --git a/pkg/datasource/sql/xa/xa_branch_xid_test.go b/pkg/datasource/sql/xa/xa_branch_xid_test.go new file mode 100644 index 00000000..16b2340b --- /dev/null +++ b/pkg/datasource/sql/xa/xa_branch_xid_test.go @@ -0,0 +1,46 @@ +/* + * 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 xa + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestXABranchXidBuild(t *testing.T) { + xid := "111" + branchId := int64(222) + x := Build(xid, branchId) + assert.Equal(t, x.GetGlobalXid(), xid) + assert.Equal(t, x.GetBranchId(), branchId) + + assert.Equal(t, x.GetGlobalTransactionId(), []byte(xid)) + assert.Equal(t, x.GetBranchQualifier(), []byte("-222")) +} + +func TestXABranchXidBuildWithByte(t *testing.T) { + xid := []byte("111") + branchId := []byte(BranchIdPrefix + "222") + x := BuildWithByte(xid, branchId) + assert.Equal(t, x.GetGlobalTransactionId(), xid) + assert.Equal(t, x.GetBranchQualifier(), branchId) + + assert.Equal(t, x.GetGlobalXid(), "111") + assert.Equal(t, x.GetBranchId(), int64(222)) +} diff --git a/pkg/datasource/sql/xa/xa_xid.go b/pkg/datasource/sql/xa/xa_xid.go new file mode 100644 index 00000000..5114f278 --- /dev/null +++ b/pkg/datasource/sql/xa/xa_xid.go @@ -0,0 +1,30 @@ +/* + * 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 xa + +type Xid interface { + GetFormatId() int + GetGlobalTransactionId() []byte + GetBranchQualifier() []byte +} + +type XAXid interface { + Xid + GetGlobalXid() string + GetBranchId() int64 +} diff --git a/pkg/datasource/sql/xa/xa_xid_builder.go b/pkg/datasource/sql/xa/xa_xid_builder.go new file mode 100644 index 00000000..8afdab83 --- /dev/null +++ b/pkg/datasource/sql/xa/xa_xid_builder.go @@ -0,0 +1,26 @@ +/* + * 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 xa + +func Build(xid string, branchId int64) *XABranchXid { + return NewXABranchXid(WithXid(xid), WithBranchId(branchId)) +} + +func BuildWithByte(globalTransactionId []byte, branchQualifier []byte) *XABranchXid { + return NewXABranchXid(WithGlobalTransactionId(globalTransactionId), WithBranchQualifier(branchQualifier)) +}