diff --git a/src/Akka.Hosting.API.Tests/verify/CoreApiSpec.ApprovePersistence.verified.txt b/src/Akka.Hosting.API.Tests/verify/CoreApiSpec.ApprovePersistence.verified.txt index 3e5ea3d7..ba336a8b 100644 --- a/src/Akka.Hosting.API.Tests/verify/CoreApiSpec.ApprovePersistence.verified.txt +++ b/src/Akka.Hosting.API.Tests/verify/CoreApiSpec.ApprovePersistence.verified.txt @@ -23,6 +23,11 @@ namespace Akka.Persistence.Hosting public Akka.Persistence.Hosting.AkkaPersistenceJournalBuilder AddWriteEventAdapter(string eventAdapterName, System.Collections.Generic.IEnumerable boundTypes) where TAdapter : Akka.Persistence.Journal.IWriteEventAdapter { } } + public static class Extensions + { + public static string ToHocon(this System.Data.IsolationLevel level) { } + public static string ToHocon(this System.Data.IsolationLevel? level) { } + } public abstract class JournalOptions { protected JournalOptions(bool isDefault) { } @@ -64,9 +69,11 @@ namespace Akka.Persistence.Hosting public string ConnectionString { get; set; } public System.TimeSpan ConnectionTimeout { get; set; } public abstract string MetadataTableName { get; set; } + public abstract System.Data.IsolationLevel ReadIsolationLevel { get; set; } public abstract string SchemaName { get; set; } public abstract bool SequentialAccess { get; set; } public abstract string TableName { get; set; } + public abstract System.Data.IsolationLevel WriteIsolationLevel { get; set; } protected override System.Text.StringBuilder Build(System.Text.StringBuilder sb) { } } public abstract class SqlSnapshotOptions : Akka.Persistence.Hosting.SnapshotOptions @@ -74,9 +81,11 @@ namespace Akka.Persistence.Hosting protected SqlSnapshotOptions(bool isDefault) { } public string ConnectionString { get; set; } public System.TimeSpan ConnectionTimeout { get; set; } + public abstract System.Data.IsolationLevel ReadIsolationLevel { get; set; } public abstract string SchemaName { get; set; } public abstract bool SequentialAccess { get; set; } public abstract string TableName { get; set; } + public abstract System.Data.IsolationLevel WriteIsolationLevel { get; set; } protected override System.Text.StringBuilder Build(System.Text.StringBuilder sb) { } } } \ No newline at end of file diff --git a/src/Akka.Hosting.API.Tests/verify/CoreApiSpec.ApprovePersistencePostgre.verified.txt b/src/Akka.Hosting.API.Tests/verify/CoreApiSpec.ApprovePersistencePostgre.verified.txt index 9e6fa5ef..bc472396 100644 --- a/src/Akka.Hosting.API.Tests/verify/CoreApiSpec.ApprovePersistencePostgre.verified.txt +++ b/src/Akka.Hosting.API.Tests/verify/CoreApiSpec.ApprovePersistencePostgre.verified.txt @@ -16,9 +16,11 @@ namespace Akka.Persistence.PostgreSql.Hosting public bool UseBigIntIdentityForOrderingColumn { get; set; } public override string Identifier { get; set; } public override string MetadataTableName { get; set; } + public override System.Data.IsolationLevel ReadIsolationLevel { get; set; } public override string SchemaName { get; set; } public override bool SequentialAccess { get; set; } public override string TableName { get; set; } + public override System.Data.IsolationLevel WriteIsolationLevel { get; set; } protected override System.Text.StringBuilder Build(System.Text.StringBuilder sb) { } } public sealed class PostgreSqlSnapshotOptions : Akka.Persistence.Hosting.SqlSnapshotOptions @@ -28,9 +30,11 @@ namespace Akka.Persistence.PostgreSql.Hosting protected override Akka.Configuration.Config InternalDefaultConfig { get; } public Akka.Persistence.PostgreSql.StoredAsType StoredAs { get; set; } public override string Identifier { get; set; } + public override System.Data.IsolationLevel ReadIsolationLevel { get; set; } public override string SchemaName { get; set; } public override bool SequentialAccess { get; set; } public override string TableName { get; set; } + public override System.Data.IsolationLevel WriteIsolationLevel { get; set; } protected override System.Text.StringBuilder Build(System.Text.StringBuilder sb) { } } public static class StoredAsExtensions { } diff --git a/src/Akka.Hosting.API.Tests/verify/CoreApiSpec.ApprovePersistenceSqlServer.verified.txt b/src/Akka.Hosting.API.Tests/verify/CoreApiSpec.ApprovePersistenceSqlServer.verified.txt index 29a01bbd..86b86b0c 100644 --- a/src/Akka.Hosting.API.Tests/verify/CoreApiSpec.ApprovePersistenceSqlServer.verified.txt +++ b/src/Akka.Hosting.API.Tests/verify/CoreApiSpec.ApprovePersistenceSqlServer.verified.txt @@ -16,9 +16,11 @@ namespace Akka.Persistence.SqlServer.Hosting public bool UseConstantParameterSize { get; set; } public override string Identifier { get; set; } public override string MetadataTableName { get; set; } + public override System.Data.IsolationLevel ReadIsolationLevel { get; set; } public override string SchemaName { get; set; } public override bool SequentialAccess { get; set; } public override string TableName { get; set; } + public override System.Data.IsolationLevel WriteIsolationLevel { get; set; } protected override System.Text.StringBuilder Build(System.Text.StringBuilder sb) { } } public sealed class SqlServerSnapshotOptions : Akka.Persistence.Hosting.SqlSnapshotOptions @@ -28,9 +30,11 @@ namespace Akka.Persistence.SqlServer.Hosting protected override Akka.Configuration.Config InternalDefaultConfig { get; } public bool UseConstantParameterSize { get; set; } public override string Identifier { get; set; } + public override System.Data.IsolationLevel ReadIsolationLevel { get; set; } public override string SchemaName { get; set; } public override bool SequentialAccess { get; set; } public override string TableName { get; set; } + public override System.Data.IsolationLevel WriteIsolationLevel { get; set; } protected override System.Text.StringBuilder Build(System.Text.StringBuilder sb) { } } } \ No newline at end of file diff --git a/src/Akka.Persistence.Hosting.Tests/PostgreSql/PostgreSqlOptionsSpec.cs b/src/Akka.Persistence.Hosting.Tests/PostgreSql/PostgreSqlOptionsSpec.cs index d7ef998e..9956d5cb 100644 --- a/src/Akka.Persistence.Hosting.Tests/PostgreSql/PostgreSqlOptionsSpec.cs +++ b/src/Akka.Persistence.Hosting.Tests/PostgreSql/PostgreSqlOptionsSpec.cs @@ -307,6 +307,8 @@ private static void AssertJournalConfig(Config underTest, Config reference) AssertBoolean(underTest, reference, "sequential-access"); AssertString(underTest, reference, "stored-as"); AssertBoolean(underTest, reference, "use-bigint-identity-for-ordering-column"); + AssertString(underTest, reference, "read-isolation-level"); + AssertString(underTest, reference, "write-isolation-level"); } private static void AssertSnapshotConfig(Config underTest, Config reference) @@ -320,6 +322,8 @@ private static void AssertSnapshotConfig(Config underTest, Config reference) AssertBoolean(underTest, reference, "auto-initialize"); AssertBoolean(underTest, reference, "sequential-access"); AssertBoolean(underTest, reference, "use-constant-parameter-size"); + AssertString(underTest, reference, "read-isolation-level"); + AssertString(underTest, reference, "write-isolation-level"); } private static void AssertString(Config underTest, Config reference, string hoconPath) diff --git a/src/Akka.Persistence.Hosting.Tests/SqlServer/SqlServerOptionsSpec.cs b/src/Akka.Persistence.Hosting.Tests/SqlServer/SqlServerOptionsSpec.cs index 3e3e7193..deba1c69 100644 --- a/src/Akka.Persistence.Hosting.Tests/SqlServer/SqlServerOptionsSpec.cs +++ b/src/Akka.Persistence.Hosting.Tests/SqlServer/SqlServerOptionsSpec.cs @@ -313,6 +313,8 @@ private static void AssertJournalConfig(Config underTest, Config reference) AssertString(underTest, reference, "metadata-table-name"); AssertBoolean(underTest, reference, "sequential-access"); AssertBoolean(underTest, reference, "use-constant-parameter-size"); + AssertString(underTest, reference, "read-isolation-level"); + AssertString(underTest, reference, "write-isolation-level"); } private static void AssertSnapshotConfig(Config underTest, Config reference) @@ -326,6 +328,8 @@ private static void AssertSnapshotConfig(Config underTest, Config reference) AssertBoolean(underTest, reference, "auto-initialize"); AssertBoolean(underTest, reference, "sequential-access"); AssertBoolean(underTest, reference, "use-constant-parameter-size"); + AssertString(underTest, reference, "read-isolation-level"); + AssertString(underTest, reference, "write-isolation-level"); } private static void AssertString(Config underTest, Config reference, string hoconPath) diff --git a/src/Akka.Persistence.Hosting/Extensions.cs b/src/Akka.Persistence.Hosting/Extensions.cs new file mode 100644 index 00000000..b0720080 --- /dev/null +++ b/src/Akka.Persistence.Hosting/Extensions.cs @@ -0,0 +1,41 @@ +// ----------------------------------------------------------------------- +// +// Copyright (C) 2013-2023 .NET Foundation +// +// ----------------------------------------------------------------------- + +using System; +using System.Data; +using System.Runtime.CompilerServices; +using Akka.Hosting; + +namespace Akka.Persistence.Hosting +{ + public static class Extensions + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string ToHocon(this IsolationLevel? level) + { + if (level is null) + throw new ArgumentNullException(nameof(level)); + return level.Value.ToHocon(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string ToHocon(this IsolationLevel level) + { + return level switch + { + IsolationLevel.Unspecified => "unspecified".ToHocon(), + IsolationLevel.ReadCommitted => "read-committed".ToHocon(), + IsolationLevel.ReadUncommitted => "read-uncommitted".ToHocon(), + IsolationLevel.RepeatableRead => "repeatable-read".ToHocon(), + IsolationLevel.Serializable => "serializable".ToHocon(), + IsolationLevel.Snapshot => "snapshot".ToHocon(), + IsolationLevel.Chaos => "chaos".ToHocon(), + _ => throw new IndexOutOfRangeException($"Unknown IsolationLevel value: {level}"), + }; + } + + } +} diff --git a/src/Akka.Persistence.Hosting/SqlJournalOptions.cs b/src/Akka.Persistence.Hosting/SqlJournalOptions.cs index fb1c5d05..63b93c77 100644 --- a/src/Akka.Persistence.Hosting/SqlJournalOptions.cs +++ b/src/Akka.Persistence.Hosting/SqlJournalOptions.cs @@ -5,6 +5,7 @@ // ----------------------------------------------------------------------- using System; +using System.Data; using System.Text; using Akka.Hosting; @@ -70,6 +71,32 @@ protected SqlJournalOptions(bool isDefault): base(isDefault) /// public abstract bool SequentialAccess { get; set; } + /// + /// + /// The of all database read query. + /// + /// + /// documentation can be read + /// here + /// + /// NOTE: This is used primarily for backward compatibility, + /// you leave this empty for greenfield projects. + /// + public abstract IsolationLevel ReadIsolationLevel { get; set; } + + /// + /// + /// The of all database write query. + /// + /// + /// documentation can be read + /// here + /// + /// NOTE: This is used primarily for backward compatibility, + /// you leave this empty for greenfield projects. + /// + public abstract IsolationLevel WriteIsolationLevel { get; set; } + protected override StringBuilder Build(StringBuilder sb) { sb.AppendLine($"connection-string = {ConnectionString.ToHocon()}"); @@ -78,6 +105,9 @@ protected override StringBuilder Build(StringBuilder sb) sb.AppendLine($"table-name = {TableName.ToHocon()}"); sb.AppendLine($"metadata-table-name = {MetadataTableName.ToHocon()}"); sb.AppendLine($"sequential-access = {SequentialAccess.ToHocon()}"); + + sb.AppendLine($"read-isolation-level = {ReadIsolationLevel.ToHocon()}"); + sb.AppendLine($"write-isolation-level = {WriteIsolationLevel.ToHocon()}"); return base.Build(sb); } diff --git a/src/Akka.Persistence.Hosting/SqlSnapshotOptions.cs b/src/Akka.Persistence.Hosting/SqlSnapshotOptions.cs index 64188666..0d56f5f2 100644 --- a/src/Akka.Persistence.Hosting/SqlSnapshotOptions.cs +++ b/src/Akka.Persistence.Hosting/SqlSnapshotOptions.cs @@ -5,6 +5,7 @@ // ----------------------------------------------------------------------- using System; +using System.Data; using System.Text; using Akka.Hosting; @@ -59,6 +60,32 @@ protected SqlSnapshotOptions(bool isDefault): base(isDefault) /// public abstract bool SequentialAccess { get; set; } + /// + /// + /// The of all database read query. + /// + /// + /// documentation can be read + /// here + /// + /// NOTE: This is used primarily for backward compatibility, + /// you leave this empty for greenfield projects. + /// + public abstract IsolationLevel ReadIsolationLevel { get; set; } + + /// + /// + /// The of all database write query. + /// + /// + /// documentation can be read + /// here + /// + /// NOTE: This is used primarily for backward compatibility, + /// you leave this empty for greenfield projects. + /// + public abstract IsolationLevel WriteIsolationLevel { get; set; } + protected override StringBuilder Build(StringBuilder sb) { sb.AppendLine($"connection-string = {ConnectionString.ToHocon()}"); @@ -66,6 +93,9 @@ protected override StringBuilder Build(StringBuilder sb) sb.AppendLine($"schema-name = {SchemaName.ToHocon()}"); sb.AppendLine($"table-name = {TableName.ToHocon()}"); sb.AppendLine($"sequential-access = {SequentialAccess.ToHocon()}"); + + sb.AppendLine($"read-isolation-level = {ReadIsolationLevel.ToHocon()}"); + sb.AppendLine($"write-isolation-level = {WriteIsolationLevel.ToHocon()}"); return base.Build(sb); } diff --git a/src/Akka.Persistence.PostgreSql.Hosting/PostgreSqlJournalOptions.cs b/src/Akka.Persistence.PostgreSql.Hosting/PostgreSqlJournalOptions.cs index fafe5928..1cf50452 100644 --- a/src/Akka.Persistence.PostgreSql.Hosting/PostgreSqlJournalOptions.cs +++ b/src/Akka.Persistence.PostgreSql.Hosting/PostgreSqlJournalOptions.cs @@ -5,6 +5,7 @@ // ----------------------------------------------------------------------- using System; +using System.Data; using System.Text; using Akka.Configuration; using Akka.Persistence.Hosting; @@ -95,6 +96,12 @@ public PostgreSqlJournalOptions(bool isDefaultPlugin, string identifier = "postg /// public bool UseBigIntIdentityForOrderingColumn { get; set; } = false; + /// + public override IsolationLevel ReadIsolationLevel { get; set; } = IsolationLevel.Unspecified; + + /// + public override IsolationLevel WriteIsolationLevel { get; set; } = IsolationLevel.Unspecified; + protected override Config InternalDefaultConfig => Default; protected override StringBuilder Build(StringBuilder sb) diff --git a/src/Akka.Persistence.PostgreSql.Hosting/PostgreSqlSnapshotOptions.cs b/src/Akka.Persistence.PostgreSql.Hosting/PostgreSqlSnapshotOptions.cs index 584f7d3f..ab2929ce 100644 --- a/src/Akka.Persistence.PostgreSql.Hosting/PostgreSqlSnapshotOptions.cs +++ b/src/Akka.Persistence.PostgreSql.Hosting/PostgreSqlSnapshotOptions.cs @@ -5,6 +5,7 @@ // ----------------------------------------------------------------------- using System; +using System.Data; using System.Text; using Akka.Configuration; using Akka.Persistence.Hosting; @@ -78,6 +79,12 @@ public PostgreSqlSnapshotOptions(bool isDefaultPlugin, string identifier = "post /// public StoredAsType StoredAs { get; set; } = StoredAsType.ByteA; + /// + public override IsolationLevel ReadIsolationLevel { get; set; } = IsolationLevel.Unspecified; + + /// + public override IsolationLevel WriteIsolationLevel { get; set; } = IsolationLevel.Unspecified; + protected override Config InternalDefaultConfig => Default; protected override StringBuilder Build(StringBuilder sb) diff --git a/src/Akka.Persistence.SqlServer.Hosting/SqlServerOptions.cs b/src/Akka.Persistence.SqlServer.Hosting/SqlServerOptions.cs index c3186e0d..885ffcf6 100644 --- a/src/Akka.Persistence.SqlServer.Hosting/SqlServerOptions.cs +++ b/src/Akka.Persistence.SqlServer.Hosting/SqlServerOptions.cs @@ -5,6 +5,7 @@ // ----------------------------------------------------------------------- using System; +using System.Data; using System.Text; using Akka.Configuration; using Akka.Hosting; @@ -104,6 +105,12 @@ public SqlServerJournalOptions(bool isDefaultPlugin, string identifier = "sql-se /// public TimeSpan QueryRefreshInterval { get; set; } = TimeSpan.FromSeconds(3); + /// + public override IsolationLevel ReadIsolationLevel { get; set; } = IsolationLevel.Unspecified; + + /// + public override IsolationLevel WriteIsolationLevel { get; set; } = IsolationLevel.Unspecified; + protected override Config InternalDefaultConfig => Default; protected override StringBuilder Build(StringBuilder sb) @@ -187,6 +194,12 @@ public SqlServerSnapshotOptions(bool isDefaultPlugin, string identifier = "sql-s /// public bool UseConstantParameterSize { get; set; } = false; + /// + public override IsolationLevel ReadIsolationLevel { get; set; } = IsolationLevel.Unspecified; + + /// + public override IsolationLevel WriteIsolationLevel { get; set; } = IsolationLevel.Unspecified; + protected override Config InternalDefaultConfig => Default; protected override StringBuilder Build(StringBuilder sb)