Skip to content

Commit 6b3602f

Browse files
authored
support RollbackReason (#49) (#54)
* support RollbackReason (#49) * chore: update dtm version * fix: null rollback reason
1 parent 883c327 commit 6b3602f

10 files changed

Lines changed: 137 additions & 22 deletions

File tree

.github/workflows/build_and_it.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Build_And_IntegrationTests
1+
name: Build_And_GRPC_IntegrationTests
22

33
on:
44
push:
@@ -48,8 +48,8 @@ jobs:
4848
mysql -h127.0.0.1 -uroot -p123456 < /home/runner/work/client-csharp/client-csharp/sqls/busi.mysql.sql
4949
- name: Setup DTM server
5050
run: |
51-
wget https://github.com/dtm-labs/dtm/releases/download/v1.12.1/dtm_1.12.1_linux_amd64.tar.gz
52-
tar -xvf dtm_1.12.1_linux_amd64.tar.gz
51+
wget https://github.com/dtm-labs/dtm/releases/download/v1.16.1/dtm_1.16.1_linux_amd64.tar.gz
52+
tar -xvf dtm_1.16.1_linux_amd64.tar.gz
5353
pwd
5454
mkdir /home/runner/work/client-csharp/client-csharp/logs
5555
nohup ./dtm > /home/runner/work/client-csharp/client-csharp/logs/dtm.log 2>&1 &

src/DtmCommon/Imp/TransBase.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ public class TransBase
5959
[JsonPropertyName("query_prepared")]
6060
public string QueryPrepared { get; set; }
6161

62+
[JsonPropertyName("protocol")]
63+
public string Protocol { get; set; }
64+
65+
[JsonPropertyName("rollback_reason")]
66+
public string RollbackReason { get; set; }
67+
6268
[JsonIgnore]
6369
public string Dtm { get; set; }
6470

src/Dtmcli/Tcc/TccGlobalTransaction.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public async Task<string> Excecute(string gid, Action<Tcc> custom, Func<Tcc, Tas
4444
}
4545
catch (Exception ex)
4646
{
47+
tcc.GetTransBase().RollbackReason = ex.Message.Substring(0, ex.Message.Length > 1023 ? 1023 : ex.Message.Length);
4748
logger.LogError(ex, "prepare or submitting global transaction error");
4849
await dtmClient.TransCallDtm(tcc.GetTransBase(), tcc.GetTransBase(), Constant.Request.OPERATION_ABORT, cancellationToken);
4950
return string.Empty;

src/Dtmgrpc/DtmgRPCClient.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ private dtmgpb.DtmRequest BuildDtmRequest(TransBase transBase)
119119
QueryPrepared = transBase.QueryPrepared ?? string.Empty,
120120
CustomedData = transBase.CustomData ?? string.Empty,
121121
Steps = transBase.Steps == null ? string.Empty : Utils.ToJsonString(transBase.Steps),
122+
RollbackReason = transBase.RollbackReason ?? string.Empty,
122123
};
123124

124125
foreach (var item in transBase.BinPayloads ?? new List<byte[]>())

src/Dtmgrpc/Tcc/TccGlobalTransaction.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public async Task<string> Excecute(string gid, Action<TccGrpc> custom, Func<TccG
3939
}
4040
catch (Exception ex)
4141
{
42+
tcc.GetTransBase().RollbackReason = ex.Message.Substring(0, ex.Message.Length > 1023 ? 1023 : ex.Message.Length);
4243
_logger.LogError(ex, "submitting or abort global transaction error");
4344
await _dtmClient.DtmGrpcCall(tcc.GetTransBase(), Constant.Op.Abort);
4445
return string.Empty;

src/Dtmgrpc/dtmgpb/dtmgimp.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ message DtmRequest {
3232
repeated bytes BinPayloads = 5; // for MSG/SAGA branch payloads
3333
string QueryPrepared = 6; // for MSG
3434
string Steps = 7;
35+
map<string, string> ReqExtra = 8;
36+
string RollbackReason = 9;
3537
}
3638

3739
message DtmGidReply {

tests/Dtmcli.Tests/TccTests.cs

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public async void Execute_Should_Submit()
1919
TestHelper.MockTransCallDtm(dtmClient, Constant.Request.OPERATION_PREPARE, false);
2020
TestHelper.MockTransRegisterBranch(dtmClient, Constant.Request.OPERATION_REGISTERBRANCH, false);
2121
TestHelper.MockTransRequestBranch(dtmClient, System.Net.HttpStatusCode.OK);
22-
22+
2323
var globalTrans = new TccGlobalTransaction(dtmClient.Object, NullLoggerFactory.Instance);
2424
var res = await globalTrans.Excecute(async (tcc) =>
2525
{
@@ -101,31 +101,80 @@ public async void Set_TransOptions_Should_Succeed()
101101

102102
var gid = "tcc_gid";
103103
var globalTrans = new TccGlobalTransaction(dtmClient.Object, NullLoggerFactory.Instance);
104-
var res = await globalTrans.Excecute(gid, tcc =>
104+
var res = await globalTrans.Excecute(gid, tcc =>
105105
{
106106
tcc.EnableWaitResult();
107107
tcc.SetRetryInterval(10);
108108
tcc.SetTimeoutToFail(100);
109-
tcc.SetBranchHeaders(new Dictionary<string, string>
109+
tcc.SetBranchHeaders(new Dictionary<string, string>
110110
{
111111
{ "bh1", "123" },
112112
{ "bh2", "456" },
113113
});
114-
}, async (tcc) =>
114+
}, async (tcc) =>
115+
{
116+
var res1 = await tcc.CallBranch(new { }, "http://localhost:9999/TransOutTry", "http://localhost:9999/TransOutConfirm", "http://localhost:9999/TransOutCancel", default);
117+
var res2 = await tcc.CallBranch(new { }, "http://localhost:9999/TransInTry", "http://localhost:9999/TransInConfirm", "http://localhost:9999/TransInCancel", default);
118+
119+
var transBase = tcc.GetTransBase();
120+
121+
Assert.True(transBase.WaitResult);
122+
Assert.Equal(10, transBase.RetryInterval);
123+
Assert.Equal(100, transBase.TimeoutToFail);
124+
Assert.Contains("bh1", transBase.BranchHeaders.Keys);
125+
Assert.Contains("bh2", transBase.BranchHeaders.Keys);
126+
});
127+
128+
Assert.Equal(gid, res);
129+
}
130+
131+
[Fact]
132+
public async void Execute_Should_Abort_With_RollbackReason_When_Occure_Exception()
133+
{
134+
var dtmClient = new Mock<IDtmClient>();
135+
TestHelper.MockTransCallDtm(dtmClient, Constant.Request.OPERATION_PREPARE, false);
136+
TestHelper.MockTransCallDtm(dtmClient, Constant.Request.OPERATION_ABORT, false);
137+
TestHelper.MockTransRegisterBranch(dtmClient, Constant.Request.OPERATION_REGISTERBRANCH, true, "123123123");
138+
TestHelper.MockTransRequestBranch(dtmClient, System.Net.HttpStatusCode.BadRequest);
139+
140+
var gid = "tcc_gid";
141+
var globalTrans = new TccGlobalTransaction(dtmClient.Object, NullLoggerFactory.Instance);
142+
var res = await globalTrans.Excecute(gid, async (tcc) =>
115143
{
116144
var res1 = await tcc.CallBranch(new { }, "http://localhost:9999/TransOutTry", "http://localhost:9999/TransOutConfirm", "http://localhost:9999/TransOutCancel", default);
117145
var res2 = await tcc.CallBranch(new { }, "http://localhost:9999/TransInTry", "http://localhost:9999/TransInConfirm", "http://localhost:9999/TransInCancel", default);
146+
});
118147

119-
var transBase = tcc.GetTransBase();
148+
Assert.Empty(res);
149+
dtmClient.Verify(x => x.TransCallDtm(It.Is<TransBase>(x => x.RollbackReason.Equals("123123123")), It.IsAny<object>(), Constant.Request.OPERATION_ABORT, It.IsAny<CancellationToken>()), Times.Once);
150+
}
151+
152+
[Fact]
153+
public async void Execute_Should_Abort_With_Big_RollbackReason_When_Occure_Exception()
154+
{
155+
var builder = new System.Text.StringBuilder(2048);
156+
for (int i = 0; i < 1100; i++)
157+
{
158+
builder.Append("r");
159+
}
160+
var ex = builder.ToString();
161+
162+
var dtmClient = new Mock<IDtmClient>();
163+
TestHelper.MockTransCallDtm(dtmClient, Constant.Request.OPERATION_PREPARE, false);
164+
TestHelper.MockTransCallDtm(dtmClient, Constant.Request.OPERATION_ABORT, false);
165+
TestHelper.MockTransRegisterBranch(dtmClient, Constant.Request.OPERATION_REGISTERBRANCH, true, ex);
166+
TestHelper.MockTransRequestBranch(dtmClient, System.Net.HttpStatusCode.BadRequest);
120167

121-
Assert.True(transBase.WaitResult);
122-
Assert.Equal(10, transBase.RetryInterval);
123-
Assert.Equal(100, transBase.TimeoutToFail);
124-
Assert.Contains("bh1", transBase.BranchHeaders.Keys);
125-
Assert.Contains("bh2", transBase.BranchHeaders.Keys);
168+
var gid = "tcc_gid";
169+
var globalTrans = new TccGlobalTransaction(dtmClient.Object, NullLoggerFactory.Instance);
170+
var res = await globalTrans.Excecute(gid, async (tcc) =>
171+
{
172+
var res1 = await tcc.CallBranch(new { }, "http://localhost:9999/TransOutTry", "http://localhost:9999/TransOutConfirm", "http://localhost:9999/TransOutCancel", default);
173+
var res2 = await tcc.CallBranch(new { }, "http://localhost:9999/TransInTry", "http://localhost:9999/TransInConfirm", "http://localhost:9999/TransInCancel", default);
126174
});
127175

128-
Assert.Equal(gid, res);
176+
Assert.Empty(res);
177+
dtmClient.Verify(x => x.TransCallDtm(It.Is<TransBase>(x => x.RollbackReason.Equals(ex.Substring(0, 1023))), It.IsAny<object>(), Constant.Request.OPERATION_ABORT, It.IsAny<CancellationToken>()), Times.Once);
129178
}
130179
}
131180
}

tests/Dtmcli.Tests/TestHelper.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,29 @@ namespace Dtmcli.Tests
1212
{
1313
public class TestHelper
1414
{
15-
public static void MockTransCallDtm(Mock<IDtmClient> mock, string op, bool isEx)
15+
public static void MockTransCallDtm(Mock<IDtmClient> mock, string op, bool isEx, string ex = "")
1616
{
1717
var setup = mock
1818
.Setup(x => x.TransCallDtm(It.IsAny<TransBase>(), It.IsAny<object>(), op, It.IsAny<CancellationToken>()));
1919

2020
if (isEx)
2121
{
22-
setup.Throws(new Exception(""));
22+
setup.Throws(new Exception(ex));
2323
}
2424
else
2525
{
2626
setup.Returns(Task.CompletedTask);
2727
}
2828
}
2929

30-
public static void MockTransRegisterBranch(Mock<IDtmClient> mock, string op, bool isEx)
30+
public static void MockTransRegisterBranch(Mock<IDtmClient> mock, string op, bool isEx, string ex = "")
3131
{
3232
var setup = mock
3333
.Setup(x => x.TransRegisterBranch(It.IsAny<TransBase>(), It.IsAny<Dictionary<string, string>>(), op, It.IsAny<CancellationToken>()));
3434

3535
if (isEx)
3636
{
37-
setup.Throws(new Exception(""));
37+
setup.Throws(new Exception(ex));
3838
}
3939
else
4040
{

tests/Dtmgrpc.Tests/TccTests.cs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,5 +97,60 @@ public async void Set_TransOptions_Should_Succeed()
9797

9898
Assert.Equal(gid, res);
9999
}
100+
101+
[Fact]
102+
public async void Execute_Should_Abort_With_RollbackReason_When_Occure_Exception()
103+
{
104+
var dtmClient = new Mock<IDtmgRPCClient>();
105+
TransMockHelper.MockTransCallDtm(dtmClient, Constant.Op.Prepare, false);
106+
TransMockHelper.MockRegisterBranch(dtmClient, true, "123123123");
107+
TransMockHelper.MockTransRequestBranch(dtmClient, false);
108+
109+
var gid = "tcc_gid";
110+
111+
var transFactory = new Mock<IDtmTransFactory>();
112+
transFactory.Setup(x => x.NewTccGrpc(It.IsAny<string>())).Returns(new TccGrpc(dtmClient.Object, TransBase.NewTransBase(gid, "tcc", "", "")));
113+
114+
var globalTrans = new TccGlobalTransaction(dtmClient.Object, NullLoggerFactory.Instance, transFactory.Object);
115+
var res = await globalTrans.Excecute(gid, async (tcc) =>
116+
{
117+
await tcc.CallBranch<Empty, Empty>(new Empty(), "localhost:9999/svc/TransOutTry", "localhost:9999/svc/TransOutConfirm", "localhost:9999/svc/TransOutCancel");
118+
await tcc.CallBranch<Empty, Empty>(new Empty(), "localhost:9999/svc/TransInTry", "localhost:9999/svc/TransInConfirm", "localhost:9999/svc/TransInCancel");
119+
});
120+
121+
Assert.Empty(res);
122+
dtmClient.Verify(x => x.DtmGrpcCall(It.Is<TransBase>(x => x.RollbackReason.Equals("123123123")), Constant.Op.Abort), Times.Once);
123+
}
124+
125+
[Fact]
126+
public async void Execute_Should_Abort_With_Big_RollbackReason_When_Occure_Exception()
127+
{
128+
var builder = new System.Text.StringBuilder(2048);
129+
for (int i = 0; i < 1100; i++)
130+
{
131+
builder.Append("r");
132+
}
133+
var ex = builder.ToString();
134+
135+
var dtmClient = new Mock<IDtmgRPCClient>();
136+
TransMockHelper.MockTransCallDtm(dtmClient, Constant.Op.Prepare, false);
137+
TransMockHelper.MockRegisterBranch(dtmClient, true, ex);
138+
TransMockHelper.MockTransRequestBranch(dtmClient, false);
139+
140+
var gid = "tcc_gid";
141+
142+
var transFactory = new Mock<IDtmTransFactory>();
143+
transFactory.Setup(x => x.NewTccGrpc(It.IsAny<string>())).Returns(new TccGrpc(dtmClient.Object, TransBase.NewTransBase(gid, "tcc", "", "")));
144+
145+
var globalTrans = new TccGlobalTransaction(dtmClient.Object, NullLoggerFactory.Instance, transFactory.Object);
146+
var res = await globalTrans.Excecute(gid, async (tcc) =>
147+
{
148+
await tcc.CallBranch<Empty, Empty>(new Empty(), "localhost:9999/svc/TransOutTry", "localhost:9999/svc/TransOutConfirm", "localhost:9999/svc/TransOutCancel");
149+
await tcc.CallBranch<Empty, Empty>(new Empty(), "localhost:9999/svc/TransInTry", "localhost:9999/svc/TransInConfirm", "localhost:9999/svc/TransInCancel");
150+
});
151+
152+
Assert.Empty(res);
153+
dtmClient.Verify(x => x.DtmGrpcCall(It.Is<TransBase>(x => x.RollbackReason.Equals(ex.Substring(0, 1023))), Constant.Op.Abort), Times.Once);
154+
}
100155
}
101156
}

tests/Dtmgrpc.Tests/TransMockHelper.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,22 @@ namespace Dtmgrpc.Tests
1111
{
1212
public class TransMockHelper
1313
{
14-
public static void MockTransCallDtm(Mock<IDtmgRPCClient> mock, string op, bool isEx)
14+
public static void MockTransCallDtm(Mock<IDtmgRPCClient> mock, string op, bool isEx, string ex = "")
1515
{
1616
var setup = mock
1717
.Setup(x => x.DtmGrpcCall(It.IsAny<TransBase>(), op));
1818

1919
if (isEx)
2020
{
21-
setup.Throws(new Exception(""));
21+
setup.Throws(new Exception(ex));
2222
}
2323
else
2424
{
2525
setup.Returns(Task.CompletedTask);
2626
}
2727
}
2828

29-
public static void MockRegisterBranch(Mock<IDtmgRPCClient> mock, bool isEx)
29+
public static void MockRegisterBranch(Mock<IDtmgRPCClient> mock, bool isEx, string ex = "")
3030
{
3131
var setup = mock
3232
.Setup(x => x.RegisterBranch(
@@ -38,7 +38,7 @@ public static void MockRegisterBranch(Mock<IDtmgRPCClient> mock, bool isEx)
3838

3939
if (isEx)
4040
{
41-
setup.Throws(new Exception(""));
41+
setup.Throws(new Exception(ex));
4242
}
4343
else
4444
{

0 commit comments

Comments
 (0)