Skip to content

Commit 94612d4

Browse files
authored
Feature: DtmClient add query single trans global status/detail (#88)
* feat(client): add query interface for global transaction - Add Query method in DtmClient and IDtmClient to retrieve global transaction details - Define TransGlobal class to represent the structure of a global transaction - Update Constant to include new URL for query endpoint * test(Dtmcli): add unit tests for DtmClient Query functionality * sample(DtmSample): add query action to MsgTestController Implement a new HTTP GET endpoint for querying transaction status * feat(DtmClient): add QueryStatus method for query single global transaction status * test(Dtmcli): improve unit test coverage
1 parent 8a4bcb1 commit 94612d4

File tree

6 files changed

+436
-3
lines changed

6 files changed

+436
-3
lines changed

samples/DtmSample/Controllers/MsgTestController.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,5 +276,29 @@ public async Task<IActionResult> MsgWithTopic(CancellationToken cancellationToke
276276

277277
return Ok(TransResponse.BuildSucceedResponse());
278278
}
279+
280+
/// <summary>
281+
/// query
282+
/// </summary>
283+
/// <param name="cancellationToken"></param>
284+
/// <returns></returns>
285+
[HttpGet("query")]
286+
public async Task<IActionResult> Query(string gid, CancellationToken cancellationToken)
287+
{
288+
TransGlobal trans = await _dtmClient.Query(gid, cancellationToken);
289+
return Ok(trans);
290+
}
291+
292+
/// <summary>
293+
/// query status
294+
/// </summary>
295+
/// <param name="cancellationToken"></param>
296+
/// <returns></returns>
297+
[HttpGet("query-status")]
298+
public async Task<IActionResult> QueryStatus(string gid, CancellationToken cancellationToken)
299+
{
300+
string status = await _dtmClient.QueryStatus(gid, cancellationToken);
301+
return Ok(status);
302+
}
279303
}
280304
}

src/Dtmcli/Constant.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ internal static class Request
5656
internal const string BRANCH_COMPENSATE = "compensate";
5757

5858
internal const string URL_NewGid = "/api/dtmsvr/newGid";
59+
60+
/// <summary>
61+
/// query single
62+
/// </summary>
63+
internal const string URL_Query = "/api/dtmsvr/query";
5964
}
6065
}
6166
}

src/Dtmcli/DtmClient.cs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using DtmCommon;
1+
using System;
2+
using DtmCommon;
23
using Microsoft.Extensions.Options;
34
using System.Collections.Generic;
45
using System.Net.Http;
@@ -46,7 +47,7 @@ public HttpClient GetHttpClient(string name)
4647
{
4748
return _httpClientFactory.CreateClient(name);
4849
}
49-
50+
5051
public async Task<HttpResponseMessage> PrepareWorkflow(TransBase tb, CancellationToken cancellationToken)
5152
{
5253
var url = string.Concat(_dtmOptions.DtmUrl.TrimEnd(Slash), Constant.Request.URLBASE_PREFIX, "prepareWorkflow");
@@ -133,6 +134,46 @@ public TransBase TransBaseFromQuery(Microsoft.AspNetCore.Http.IQueryCollection q
133134
}
134135
#endif
135136

137+
/// <summary>
138+
/// Query single global transaction
139+
/// </summary>
140+
/// <param name="gid">global id</param>
141+
/// <param name="cancellationToken"></param>
142+
/// <returns></returns>
143+
public async Task<TransGlobal> Query(string gid, CancellationToken cancellationToken)
144+
{
145+
if (string.IsNullOrEmpty(gid)) throw new ArgumentNullException(nameof(gid));
146+
147+
var url = string.Concat(_dtmOptions.DtmUrl.TrimEnd(Slash), Constant.Request.URL_Query, $"?gid={gid}");
148+
var client = _httpClientFactory.CreateClient(Constant.DtmClientHttpName);
149+
var response = await client.GetAsync(url, cancellationToken).ConfigureAwait(false);
150+
var dtmContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
151+
DtmImp.Utils.CheckStatus(response.StatusCode, dtmContent);
152+
return JsonSerializer.Deserialize<TransGlobal>(dtmContent, _jsonOptions);
153+
}
154+
155+
/// <summary>
156+
/// Query single global transaction status
157+
/// </summary>
158+
/// <param name="gid"></param>
159+
/// <param name="cancellationToken"></param>
160+
/// <returns></returns>
161+
/// <exception cref="NotImplementedException"></exception>
162+
public async Task<string> QueryStatus(string gid, CancellationToken cancellationToken)
163+
{
164+
if (string.IsNullOrEmpty(gid)) throw new ArgumentNullException(nameof(gid));
165+
166+
var url = string.Concat(_dtmOptions.DtmUrl.TrimEnd(Slash), Constant.Request.URL_Query, $"?gid={gid}");
167+
var client = _httpClientFactory.CreateClient(Constant.DtmClientHttpName);
168+
var response = await client.GetAsync(url, cancellationToken).ConfigureAwait(false);
169+
var dtmContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
170+
DtmImp.Utils.CheckStatus(response.StatusCode, dtmContent);
171+
var graph = JsonSerializer.Deserialize<TransGlobalForStatus>(dtmContent, _jsonOptions);
172+
return graph.Transaction == null
173+
? string.Empty
174+
: graph.Transaction.Status;
175+
}
176+
136177
public class DtmGid
137178
{
138179
[JsonPropertyName("gid")]

src/Dtmcli/IDtmClient.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,9 @@ public interface IDtmClient
2323
#if NET5_0_OR_GREATER
2424
TransBase TransBaseFromQuery(Microsoft.AspNetCore.Http.IQueryCollection query);
2525
#endif
26+
27+
Task<TransGlobal> Query(string gid, CancellationToken cancellationToken);
28+
29+
Task<string> QueryStatus(string gid, CancellationToken cancellationToken);
2630
}
2731
}

src/Dtmcli/TransGlobal.cs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text.Json.Serialization;
4+
5+
namespace Dtmcli;
6+
7+
/// <summary>
8+
/// query status only
9+
/// </summary>
10+
internal class TransGlobalForStatus
11+
{
12+
[JsonPropertyName("transaction")] public DtmTransactionForStatus Transaction { get; set; }
13+
14+
public class DtmTransactionForStatus
15+
{
16+
[JsonPropertyName("status")] public string Status { get; set; }
17+
}
18+
}
19+
20+
// convert from json to c# code, json sample: saga succeed http (dtm-labs/dtm/qs/main.go)
21+
public class TransGlobal
22+
{
23+
[JsonPropertyName("branches")] public List<DtmBranch> Branches { get; set; }
24+
25+
[JsonPropertyName("transaction")] public DtmTransaction Transaction { get; set; }
26+
27+
public class DtmTransaction
28+
{
29+
[JsonPropertyName("id")] public int Id { get; set; }
30+
31+
[JsonPropertyName("create_time")] public DateTimeOffset CreateTime { get; set; }
32+
33+
[JsonPropertyName("update_time")] public DateTimeOffset UpdateTime { get; set; }
34+
35+
[JsonPropertyName("gid")] public string Gid { get; set; }
36+
37+
[JsonPropertyName("trans_type")] public string TransType { get; set; }
38+
39+
[JsonPropertyName("steps")] public List<TransactionStep> Steps { get; set; }
40+
41+
[JsonPropertyName("payloads")] public List<string> Payloads { get; set; }
42+
43+
[JsonPropertyName("status")] public string Status { get; set; }
44+
45+
// [JsonPropertyName("query_prepared")] public string QueryPrepared { get; set; }
46+
47+
[JsonPropertyName("protocol")] public string Protocol { get; set; }
48+
49+
[JsonPropertyName("finish_time")] public DateTimeOffset FinishTime { get; set; }
50+
51+
[JsonPropertyName("options")] public string Options { get; set; }
52+
53+
[JsonPropertyName("next_cron_interval")]
54+
public int NextCronInterval { get; set; }
55+
56+
[JsonPropertyName("next_cron_time")] public DateTimeOffset NextCronTime { get; set; }
57+
58+
// [JsonPropertyName("wait_result")] public bool WaitResult { get; set; }
59+
60+
[JsonPropertyName("concurrent")] public bool Concurrent { get; set; }
61+
}
62+
63+
public class DtmBranch
64+
{
65+
[JsonPropertyName("id")] public int Id { get; set; }
66+
67+
[JsonPropertyName("create_time")] public DateTimeOffset CreateTime { get; set; }
68+
69+
[JsonPropertyName("update_time")] public DateTimeOffset UpdateTime { get; set; }
70+
71+
[JsonPropertyName("gid")] public string Gid { get; set; }
72+
73+
[JsonPropertyName("url")] public string Url { get; set; }
74+
75+
[JsonPropertyName("bin_data")] public string BinData { get; set; }
76+
77+
[JsonPropertyName("branch_id")] public string BranchId { get; set; }
78+
79+
[JsonPropertyName("op")] public string Op { get; set; }
80+
81+
[JsonPropertyName("status")] public string Status { get; set; }
82+
}
83+
84+
public class TransactionStep
85+
{
86+
[JsonPropertyName("action")] public string Action { get; set; }
87+
[JsonPropertyName("Compensate")] public string Compensate { get; set; }
88+
}
89+
}

0 commit comments

Comments
 (0)