Skip to content
This repository was archived by the owner on Mar 20, 2025. It is now read-only.

Commit 4b2bceb

Browse files
authored
Implement SQL query transaction isolation level from Akka.NET 1.5.3 (#198)
1 parent 2c73867 commit 4b2bceb

File tree

16 files changed

+660
-88
lines changed

16 files changed

+660
-88
lines changed

build.fsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ Target "RunTests" <| fun _ ->
136136
let projects =
137137
match (isWindows) with
138138
| true -> !! "./src/**/*.Tests.*sproj"
139+
-- "./src/**/*.Performance.Tests.*sproj"
139140
| _ -> !! "./src/**/*.Tests.*sproj" // if you need to filter specs for Linux vs. Windows, do it here
140141

141142
ensureDirectory outputTests
@@ -158,6 +159,7 @@ Target "RunTestsNet" <| fun _ ->
158159
let projects =
159160
match (isWindows) with
160161
| true -> !! "./src/**/*.Tests.*sproj"
162+
-- "./src/**/*.Performance.Tests.*sproj"
161163
| _ -> !! "./src/**/*.Tests.*sproj" // if you need to filter specs for Linux vs. Windows, do it here
162164

163165
ensureDirectory outputTests
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+
<PropertyGroup>
3+
<TargetFrameworks>$(NetFrameworkTestVersion);$(NetCoreTestVersion)</TargetFrameworks>
4+
<IsPackable>false</IsPackable>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<PackageReference Include="Docker.DotNet" />
9+
<PackageReference Include="Akka.Persistence.Sql.TestKit" />
10+
<PackageReference Include="Microsoft.NET.Test.Sdk" />
11+
<PackageReference Include="xunit" />
12+
<PackageReference Include="xunit.runner.visualstudio" />
13+
<PackageReference Include="Npgsql" />
14+
</ItemGroup>
15+
16+
<ItemGroup>
17+
<ProjectReference Include="..\Akka.Persistence.PostgreSql\Akka.Persistence.PostgreSql.csproj" />
18+
</ItemGroup>
19+
</Project>
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//-----------------------------------------------------------------------
2+
// <copyright file="DbUtils.cs" company="Akka.NET Project">
3+
// Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
4+
// Copyright (C) 2013-2016 Akka.NET project <https://github.com/akkadotnet/akka.net>
5+
// </copyright>
6+
//-----------------------------------------------------------------------
7+
8+
using System;
9+
using Npgsql;
10+
11+
namespace Akka.Persistence.PostgreSql.Performance.Tests
12+
{
13+
public static class DbUtils
14+
{
15+
public static string ConnectionString { get; private set; }
16+
17+
public static void Initialize(PostgresFixture fixture)
18+
{
19+
ConnectionString = fixture.ConnectionString;
20+
var connectionBuilder = new NpgsqlConnectionStringBuilder(ConnectionString);
21+
22+
//connect to postgres database to create a new database
23+
var databaseName = connectionBuilder.Database;
24+
connectionBuilder.Database = databaseName;
25+
ConnectionString = connectionBuilder.ToString();
26+
27+
using (var conn = new NpgsqlConnection(ConnectionString))
28+
{
29+
conn.Open();
30+
31+
bool dbExists;
32+
using (var cmd = new NpgsqlCommand())
33+
{
34+
cmd.CommandText = $@"SELECT TRUE FROM pg_database WHERE datname='{databaseName}'";
35+
cmd.Connection = conn;
36+
37+
var result = cmd.ExecuteScalar();
38+
dbExists = result != null && Convert.ToBoolean(result);
39+
}
40+
41+
if (dbExists)
42+
{
43+
Clean();
44+
}
45+
else
46+
{
47+
DoCreate(conn, databaseName);
48+
}
49+
}
50+
}
51+
52+
public static void Clean()
53+
{
54+
using (var conn = new NpgsqlConnection(ConnectionString))
55+
{
56+
conn.Open();
57+
58+
DoClean(conn);
59+
}
60+
}
61+
62+
private static void DoCreate(NpgsqlConnection conn, string databaseName)
63+
{
64+
using (var cmd = new NpgsqlCommand())
65+
{
66+
cmd.CommandText = $@"CREATE DATABASE {databaseName}";
67+
cmd.Connection = conn;
68+
cmd.ExecuteNonQuery();
69+
}
70+
}
71+
72+
private static void DoClean(NpgsqlConnection conn)
73+
{
74+
using (var cmd = new NpgsqlCommand())
75+
{
76+
cmd.CommandText = @"
77+
DROP TABLE IF EXISTS public.event_journal;
78+
DROP TABLE IF EXISTS public.snapshot_store;
79+
DROP TABLE IF EXISTS public.metadata;";
80+
cmd.Connection = conn;
81+
cmd.ExecuteNonQuery();
82+
}
83+
}
84+
}
85+
}

src/Akka.Persistence.PostgreSql.Tests/Performance/PostgreSqlJournalPerfSpec.cs renamed to src/Akka.Persistence.PostgreSql.Performance.Tests/PostgreSqlJournalPerfSpec.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
using Xunit;
1212
using Xunit.Abstractions;
1313

14-
namespace Akka.Persistence.PostgreSql.Tests.Performance
14+
namespace Akka.Persistence.PostgreSql.Performance.Tests
1515
{
1616
[Collection("PostgreSqlSpec")]
1717
public class PostgreSqlJournalPerfSpec : JournalPerfSpec
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Runtime.InteropServices;
4+
using System.Threading.Tasks;
5+
using Akka.Util;
6+
using Docker.DotNet;
7+
using Docker.DotNet.Models;
8+
using Xunit;
9+
10+
namespace Akka.Persistence.PostgreSql.Performance.Tests
11+
{
12+
[CollectionDefinition("PostgreSqlSpec")]
13+
public sealed class PostgresSpecsFixture : ICollectionFixture<PostgresFixture>
14+
{
15+
}
16+
17+
/// <summary>
18+
/// Fixture used to run PostgresSQL Server
19+
/// </summary>
20+
public class PostgresFixture : IAsyncLifetime
21+
{
22+
protected readonly string PostgresContainerName = $"postgresSqlServer-{Guid.NewGuid():N}";
23+
protected DockerClient Client;
24+
25+
public PostgresFixture()
26+
{
27+
DockerClientConfiguration config;
28+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
29+
config = new DockerClientConfiguration(new Uri("unix://var/run/docker.sock"));
30+
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
31+
config = new DockerClientConfiguration(new Uri("npipe://./pipe/docker_engine"));
32+
else
33+
throw new NotSupportedException($"Unsupported OS [{RuntimeInformation.OSDescription}]");
34+
35+
Client = config.CreateClient();
36+
}
37+
38+
protected string ImageName => "postgres";
39+
protected string Tag => "latest";
40+
41+
protected string PostgresImageName => $"{ImageName}:{Tag}";
42+
43+
public string ConnectionString { get; private set; }
44+
45+
public async Task InitializeAsync()
46+
{
47+
var images = await Client.Images.ListImagesAsync(new ImagesListParameters
48+
{
49+
Filters = new Dictionary<string, IDictionary<string, bool>>
50+
{
51+
{
52+
"reference",
53+
new Dictionary<string, bool>
54+
{
55+
{PostgresImageName, true}
56+
}
57+
}
58+
}
59+
});
60+
61+
if (images.Count == 0)
62+
await Client.Images.CreateImageAsync(
63+
new ImagesCreateParameters { FromImage = ImageName, Tag = Tag }, null,
64+
new Progress<JSONMessage>(message =>
65+
{
66+
Console.WriteLine(!string.IsNullOrEmpty(message.ErrorMessage)
67+
? message.ErrorMessage
68+
: $"{message.ID} {message.Status} {message.ProgressMessage}");
69+
}));
70+
71+
var sqlServerHostPort = ThreadLocalRandom.Current.Next(9000, 10000);
72+
73+
// create the container
74+
await Client.Containers.CreateContainerAsync(new CreateContainerParameters
75+
{
76+
Image = PostgresImageName,
77+
Name = PostgresContainerName,
78+
Tty = true,
79+
ExposedPorts = new Dictionary<string, EmptyStruct>
80+
{
81+
{"5432/tcp", new EmptyStruct()}
82+
},
83+
HostConfig = new HostConfig
84+
{
85+
PortBindings = new Dictionary<string, IList<PortBinding>>
86+
{
87+
{
88+
"5432/tcp",
89+
new List<PortBinding>
90+
{
91+
new PortBinding
92+
{
93+
HostPort = $"{sqlServerHostPort}"
94+
}
95+
}
96+
}
97+
}
98+
},
99+
Env = new[]
100+
{
101+
"POSTGRES_PASSWORD=postgres",
102+
"POSTGRES_USER=postgres"
103+
}
104+
});
105+
106+
// start the container
107+
await Client.Containers.StartContainerAsync(PostgresContainerName, new ContainerStartParameters());
108+
109+
// Provide a 10 second startup delay
110+
await Task.Delay(TimeSpan.FromSeconds(10));
111+
112+
ConnectionString = $"Server=127.0.0.1;Port={sqlServerHostPort};" +
113+
"Database=postgres;User Id=postgres;Password=postgres";
114+
}
115+
116+
public async Task DisposeAsync()
117+
{
118+
if (Client != null)
119+
{
120+
await Client.Containers.StopContainerAsync(PostgresContainerName, new ContainerStopParameters());
121+
await Client.Containers.RemoveContainerAsync(PostgresContainerName,
122+
new ContainerRemoveParameters { Force = true });
123+
Client.Dispose();
124+
}
125+
}
126+
}
127+
}

src/Akka.Persistence.PostgreSql.Tests/DbUtils.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
using Npgsql;
99
using System;
10+
using System.IO;
1011

1112
namespace Akka.Persistence.PostgreSql.Tests
1213
{
@@ -47,6 +48,11 @@ public static void Initialize(PostgresFixture fixture)
4748
DoCreate(conn, databaseName);
4849
}
4950
}
51+
52+
// Delete local snapshot flat file database
53+
var path = "./snapshots";
54+
if (Directory.Exists(path))
55+
Directory.Delete(path, true);
5056
}
5157

5258
public static void Clean()

0 commit comments

Comments
 (0)