Skip to content

Commit 65e18ee

Browse files
dev SLO: Dapper over ADO.NET (#466)
1 parent dcc2428 commit 65e18ee

File tree

8 files changed

+120
-12
lines changed

8 files changed

+120
-12
lines changed

.github/workflows/slo.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ jobs:
3131
matrix:
3232
workload:
3333
- AdoNet
34-
- EF
34+
- Dapper
35+
# - EF
3536

3637
concurrency:
3738
group: slo-${{ github.ref }}-${{ matrix.workload }}

slo/src/AdoNet/Program.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
// See https://aka.ms/new-console-template for more information
2-
3-
using AdoNet;
1+
using AdoNet;
42
using Internal;
53

64
await Cli.Run(new SloTableContext(), args);

slo/src/AdoNet/SloTableContext.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace AdoNet;
99

1010
public class SloTableContext : SloTableContext<YdbDataSource>
1111
{
12-
private readonly AsyncPolicy _policy = Policy.Handle<YdbException>(exception => exception.IsTransient)
12+
private static readonly AsyncPolicy Policy = Polly.Policy.Handle<YdbException>(exception => exception.IsTransient)
1313
.WaitAndRetryAsync(10, attempt => TimeSpan.FromMilliseconds(attempt * 10),
1414
(e, _, _, _) => { Logger.LogWarning(e, "Failed read / write operation"); });
1515

@@ -45,8 +45,10 @@ PRIMARY KEY (Guid, Id)
4545
int writeTimeout
4646
)
4747
{
48-
var policyResult = await _policy.ExecuteAndCaptureAsync(async _ =>
48+
var attempts = 0;
49+
var policyResult = await Policy.ExecuteAndCaptureAsync(async _ =>
4950
{
51+
attempts++;
5052
await using var ydbConnection = await client.OpenConnectionAsync();
5153

5254
var ydbCommand = new YdbCommand(ydbConnection)
@@ -95,8 +97,7 @@ int writeTimeout
9597
}, new Context());
9698

9799

98-
return (policyResult.Context.TryGetValue("RetryCount", out var countAttempts) ? (int)countAttempts : 1,
99-
((YdbException)policyResult.FinalException)?.Code ?? StatusCode.Success);
100+
return (attempts, ((YdbException)policyResult.FinalException)?.Code ?? StatusCode.Success);
100101
}
101102

102103
protected override async Task<(int, StatusCode, object?)> Select(
@@ -106,7 +107,7 @@ int readTimeout
106107
)
107108
{
108109
var attempts = 0;
109-
var policyResult = await _policy.ExecuteAndCaptureAsync(async _ =>
110+
var policyResult = await Policy.ExecuteAndCaptureAsync(async _ =>
110111
{
111112
attempts++;
112113
await using var ydbConnection = await client.OpenConnectionAsync();
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
<RootNamespace>AdoNet.Dapper</RootNamespace>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<ProjectReference Include="..\Internal\Internal.csproj"/>
13+
</ItemGroup>
14+
15+
<ItemGroup>
16+
<PackageReference Include="Polly" Version="8.4.1"/>
17+
<PackageReference Include="Dapper" Version="2.1.66"/>
18+
</ItemGroup>
19+
</Project>

slo/src/Dapper/Program.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
using AdoNet.Dapper;
2+
using Internal;
3+
4+
await Cli.Run(new SloTableContext(), args);

slo/src/Dapper/SloTableContext.cs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
using Dapper;
2+
using Internal;
3+
using Microsoft.Extensions.Logging;
4+
using Polly;
5+
using Ydb.Sdk;
6+
using Ydb.Sdk.Ado;
7+
8+
namespace AdoNet.Dapper;
9+
10+
public class SloTableContext : SloTableContext<YdbDataSource>
11+
{
12+
private static readonly AsyncPolicy Policy = Polly.Policy.Handle<YdbException>(exception => exception.IsTransient)
13+
.WaitAndRetryAsync(10, attempt => TimeSpan.FromMilliseconds(attempt * 10),
14+
(e, _, _, _) => { Logger.LogWarning(e, "Failed read / write operation"); });
15+
16+
protected override string Job => "Dapper";
17+
18+
protected override YdbDataSource CreateClient(Config config) => new(
19+
new YdbConnectionStringBuilder(config.ConnectionString) { LoggerFactory = ISloContext.Factory }
20+
);
21+
22+
protected override async Task Create(YdbDataSource client, int operationTimeout)
23+
{
24+
await using var connection = await client.OpenConnectionAsync();
25+
await connection.ExecuteAsync($"""
26+
CREATE TABLE `{SloTable.Name}` (
27+
Guid Uuid,
28+
Id Int32,
29+
PayloadStr Text,
30+
PayloadDouble Double,
31+
PayloadTimestamp Timestamp,
32+
PRIMARY KEY (Guid, Id)
33+
);
34+
{SloTable.Options}
35+
""");
36+
}
37+
38+
protected override async Task<(int, StatusCode)> Save(YdbDataSource client, SloTable sloTable, int writeTimeout)
39+
{
40+
var attempt = 0;
41+
var policyResult = await Policy.ExecuteAndCaptureAsync(async _ =>
42+
{
43+
attempt++;
44+
await using var connection = await client.OpenConnectionAsync();
45+
await connection.ExecuteAsync($"""
46+
UPSERT INTO `{SloTable.Name}` (Guid, Id, PayloadStr, PayloadDouble, PayloadTimestamp)
47+
VALUES (@Guid, @Id, @PayloadStr, @PayloadDouble, @PayloadTimestamp)
48+
""", sloTable);
49+
}, new Context()
50+
);
51+
52+
return (attempt, ((YdbException)policyResult.FinalException)?.Code ?? StatusCode.Success);
53+
}
54+
55+
protected override async Task<(int, StatusCode, object?)> Select(YdbDataSource client, (Guid Guid, int Id) select,
56+
int readTimeout)
57+
{
58+
var attempts = 0;
59+
var policyResult = await Policy.ExecuteAndCaptureAsync(async _ =>
60+
{
61+
attempts++;
62+
await using var connection = await client.OpenConnectionAsync();
63+
64+
return await connection.QueryFirstOrDefaultAsync<SloTable>(
65+
$"""
66+
SELECT Guid, Id, PayloadStr, PayloadDouble, PayloadTimestamp
67+
FROM `{SloTable.Name}` WHERE Guid = @Guid AND Id = @Id;
68+
""",
69+
new { select.Guid, select.Id }
70+
);
71+
}, new Context());
72+
73+
return (attempts, ((YdbException)policyResult.FinalException)?.Code ?? StatusCode.Success, policyResult.Result);
74+
}
75+
76+
protected override async Task<int> SelectCount(YdbDataSource client)
77+
{
78+
await using var connection = await client.OpenConnectionAsync();
79+
return await connection.ExecuteScalarAsync<int>($"SELECT MAX(Id) FROM {SloTable.Name}");
80+
}
81+
}

slo/src/EF/Program.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
// See https://aka.ms/new-console-template for more information
2-
3-
using EF;
1+
using EF;
42
using Internal;
53

64
await Cli.Run(new SloTableContext(), args);

slo/src/src.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TopicService", "TopicServic
1111
EndProject
1212
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EF", "EF\EF.csproj", "{291A2C64-8A20-40AA-B68A-B9E2A730B66C}"
1313
EndProject
14+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdoNet.Dapper", "Dapper\AdoNet.Dapper.csproj", "{A6B9B4F1-4C7C-42C1-A212-B71A9B0D67F7}"
15+
EndProject
1416
Global
1517
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1618
Debug|Any CPU = Debug|Any CPU
@@ -33,6 +35,10 @@ Global
3335
{291A2C64-8A20-40AA-B68A-B9E2A730B66C}.Debug|Any CPU.Build.0 = Debug|Any CPU
3436
{291A2C64-8A20-40AA-B68A-B9E2A730B66C}.Release|Any CPU.ActiveCfg = Release|Any CPU
3537
{291A2C64-8A20-40AA-B68A-B9E2A730B66C}.Release|Any CPU.Build.0 = Release|Any CPU
38+
{A6B9B4F1-4C7C-42C1-A212-B71A9B0D67F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39+
{A6B9B4F1-4C7C-42C1-A212-B71A9B0D67F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
40+
{A6B9B4F1-4C7C-42C1-A212-B71A9B0D67F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
41+
{A6B9B4F1-4C7C-42C1-A212-B71A9B0D67F7}.Release|Any CPU.Build.0 = Release|Any CPU
3642
EndGlobalSection
3743
GlobalSection(SolutionProperties) = preSolution
3844
HideSolutionNode = FALSE

0 commit comments

Comments
 (0)