From 0db6e6fcfe901b36e60a0ea502f2c8d310ca1386 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Aug 2022 13:09:05 -0500 Subject: [PATCH 01/11] Bump AkkaVersion from 1.4.39 to 1.4.40 (#229) Bumps `AkkaVersion` from 1.4.39 to 1.4.40. Updates `Akka.Persistence.Query` from 1.4.39 to 1.4.40 - [Release notes](https://github.com/akkadotnet/akka.net/releases) - [Changelog](https://github.com/akkadotnet/akka.net/blob/1.4.40/RELEASE_NOTES.md) - [Commits](https://github.com/akkadotnet/akka.net/compare/1.4.39...1.4.40) Updates `Akka.Persistence.TCK` from 1.4.39 to 1.4.40 - [Release notes](https://github.com/akkadotnet/akka.net/releases) - [Changelog](https://github.com/akkadotnet/akka.net/blob/1.4.40/RELEASE_NOTES.md) - [Commits](https://github.com/akkadotnet/akka.net/compare/1.4.39...1.4.40) --- updated-dependencies: - dependency-name: Akka.Persistence.Query dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: Akka.Persistence.TCK dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/common.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common.props b/src/common.props index 35f12cfc..1b92743a 100644 --- a/src/common.props +++ b/src/common.props @@ -17,7 +17,7 @@ 2.4.1 - 1.4.39 + 1.4.40 5.10.3 17.2.0 netcoreapp3.1 From da2cbfe57d9db7288e7c418637ecb33fd2df5b91 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Aug 2022 18:14:43 +0000 Subject: [PATCH 02/11] Bump Akka.Persistence.Hosting from 0.4.1 to 0.4.2 (#233) Bumps [Akka.Persistence.Hosting](https://github.com/akkadotnet/Akka.Hosting) from 0.4.1 to 0.4.2. - [Release notes](https://github.com/akkadotnet/Akka.Hosting/releases) - [Changelog](https://github.com/akkadotnet/Akka.Hosting/blob/dev/RELEASE_NOTES.md) - [Commits](https://github.com/akkadotnet/Akka.Hosting/compare/0.4.1...0.4.2) --- updated-dependencies: - dependency-name: Akka.Persistence.Hosting dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../Akka.Persistence.Azure.Hosting.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Akka.Persistence.Azure.Hosting/Akka.Persistence.Azure.Hosting.csproj b/src/Akka.Persistence.Azure.Hosting/Akka.Persistence.Azure.Hosting.csproj index abb7b339..254cfcfa 100644 --- a/src/Akka.Persistence.Azure.Hosting/Akka.Persistence.Azure.Hosting.csproj +++ b/src/Akka.Persistence.Azure.Hosting/Akka.Persistence.Azure.Hosting.csproj @@ -11,7 +11,7 @@ - + From db7ee2fa9d1744da74b431f48acb9f7660893b32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Aug 2022 18:19:46 +0000 Subject: [PATCH 03/11] Bump Microsoft.NET.Test.Sdk from 17.2.0 to 17.3.0 (#232) Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.2.0 to 17.3.0. - [Release notes](https://github.com/microsoft/vstest/releases) - [Commits](https://github.com/microsoft/vstest/compare/v17.2.0...v17.3.0) --- updated-dependencies: - dependency-name: Microsoft.NET.Test.Sdk dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/common.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common.props b/src/common.props index 1b92743a..91b9d9ab 100644 --- a/src/common.props +++ b/src/common.props @@ -19,7 +19,7 @@ 2.4.1 1.4.40 5.10.3 - 17.2.0 + 17.3.0 netcoreapp3.1 net461 netstandard2.0 From a648a40bf681b8bae22e26a57e95f00f53be0ed9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Aug 2022 19:02:51 +0000 Subject: [PATCH 04/11] Bump Azure.Storage.Blobs from 12.12.0 to 12.13.0 (#219) Bumps [Azure.Storage.Blobs](https://github.com/Azure/azure-sdk-for-net) from 12.12.0 to 12.13.0. - [Release notes](https://github.com/Azure/azure-sdk-for-net/releases) - [Commits](https://github.com/Azure/azure-sdk-for-net/compare/Azure.Storage.Blobs_12.12.0...Azure.Storage.Blobs_12.13.0) --- updated-dependencies: - dependency-name: Azure.Storage.Blobs dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build-system/azure-pipeline.template.yaml | 4 ++-- .../Hosting/AzurePersistenceHostingSanityCheck.cs | 3 ++- src/Akka.Persistence.Azure/Akka.Persistence.Azure.csproj | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/build-system/azure-pipeline.template.yaml b/build-system/azure-pipeline.template.yaml index 696095d8..1e0ced17 100644 --- a/build-system/azure-pipeline.template.yaml +++ b/build-system/azure-pipeline.template.yaml @@ -17,7 +17,7 @@ jobs: persistCredentials: true # Linux or macOS - bash: | - sudo npm install -g azurite@3.17.1 + sudo npm install -g azurite@3.18.0 sudo mkdir azurite sudo azurite --silent --location azurite --debug azirute/debug.log & displayName: 'Install and Run Azurite (Linux)' @@ -33,7 +33,7 @@ jobs: AZURE_CONNECTION_STR: UseDevelopmentStorage=true # Windows - powershell: | - npm install -g azurite@3.17.1 + npm install -g azurite@3.18.0 mkdir azurite Start-Process azurite.cmd -PassThru displayName: 'Install and Run Azurite (Windows)' diff --git a/src/Akka.Persistence.Azure.Tests/Hosting/AzurePersistenceHostingSanityCheck.cs b/src/Akka.Persistence.Azure.Tests/Hosting/AzurePersistenceHostingSanityCheck.cs index 289ea86f..7ed2e8e8 100644 --- a/src/Akka.Persistence.Azure.Tests/Hosting/AzurePersistenceHostingSanityCheck.cs +++ b/src/Akka.Persistence.Azure.Tests/Hosting/AzurePersistenceHostingSanityCheck.cs @@ -14,11 +14,12 @@ namespace Akka.Persistence.Azure.Tests.Hosting { + [Collection("AzureSpecs")] public class AzurePersistenceHostingSanityCheck { public static async Task StartHost(Action testSetup) { - var conn = Environment.GetEnvironmentVariable("AZURE_CONNECTION_STR"); + var conn = Environment.GetEnvironmentVariable("AZURE_CONNECTION_STR") ?? "UseDevelopmentStorage=true"; var host = new HostBuilder() .ConfigureServices(collection => { diff --git a/src/Akka.Persistence.Azure/Akka.Persistence.Azure.csproj b/src/Akka.Persistence.Azure/Akka.Persistence.Azure.csproj index 46446b59..61690f68 100644 --- a/src/Akka.Persistence.Azure/Akka.Persistence.Azure.csproj +++ b/src/Akka.Persistence.Azure/Akka.Persistence.Azure.csproj @@ -17,7 +17,7 @@ - + From 592ab6c8cad27f9428c1813ddc07e06200edbba2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Aug 2022 19:08:55 +0000 Subject: [PATCH 05/11] Bump xunit from 2.4.1 to 2.4.2 (#230) Bumps [xunit](https://github.com/xunit/xunit) from 2.4.1 to 2.4.2. - [Release notes](https://github.com/xunit/xunit/releases) - [Commits](https://github.com/xunit/xunit/compare/2.4.1...2.4.2) --- updated-dependencies: - dependency-name: xunit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../Akka.Persistence.Azure.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Akka.Persistence.Azure.Tests/Akka.Persistence.Azure.Tests.csproj b/src/Akka.Persistence.Azure.Tests/Akka.Persistence.Azure.Tests.csproj index 82c3a989..0f79459a 100644 --- a/src/Akka.Persistence.Azure.Tests/Akka.Persistence.Azure.Tests.csproj +++ b/src/Akka.Persistence.Azure.Tests/Akka.Persistence.Azure.Tests.csproj @@ -8,7 +8,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 2e9a2eede2d0e09fec0c7a00226da20bea430724 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Aug 2022 19:15:10 +0000 Subject: [PATCH 06/11] Bump Azure.Identity from 1.6.0 to 1.6.1 (#231) Bumps [Azure.Identity](https://github.com/Azure/azure-sdk-for-net) from 1.6.0 to 1.6.1. - [Release notes](https://github.com/Azure/azure-sdk-for-net/releases) - [Commits](https://github.com/Azure/azure-sdk-for-net/compare/Azure.Identity_1.6.0...Azure.Identity_1.6.1) --- updated-dependencies: - dependency-name: Azure.Identity dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/Akka.Persistence.Azure/Akka.Persistence.Azure.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Akka.Persistence.Azure/Akka.Persistence.Azure.csproj b/src/Akka.Persistence.Azure/Akka.Persistence.Azure.csproj index 61690f68..083ac6b2 100644 --- a/src/Akka.Persistence.Azure/Akka.Persistence.Azure.csproj +++ b/src/Akka.Persistence.Azure/Akka.Persistence.Azure.csproj @@ -16,7 +16,7 @@ - + From 48046bff3d269f4552aaa5a67a2b23f424ef752a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Aug 2022 12:06:02 -0500 Subject: [PATCH 07/11] Bump Azure.Storage.Blobs from 12.13.0 to 12.13.1 (#234) Bumps [Azure.Storage.Blobs](https://github.com/Azure/azure-sdk-for-net) from 12.13.0 to 12.13.1. - [Release notes](https://github.com/Azure/azure-sdk-for-net/releases) - [Commits](https://github.com/Azure/azure-sdk-for-net/compare/Azure.Storage.Blobs_12.13.0...Azure.Storage.Blobs_12.13.1) --- updated-dependencies: - dependency-name: Azure.Storage.Blobs dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/Akka.Persistence.Azure/Akka.Persistence.Azure.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Akka.Persistence.Azure/Akka.Persistence.Azure.csproj b/src/Akka.Persistence.Azure/Akka.Persistence.Azure.csproj index 083ac6b2..5a8e62a3 100644 --- a/src/Akka.Persistence.Azure/Akka.Persistence.Azure.csproj +++ b/src/Akka.Persistence.Azure/Akka.Persistence.Azure.csproj @@ -17,7 +17,7 @@ - + From 2e7bfd2f2b3c85c6b8b8051527206b53e0d2947f Mon Sep 17 00:00:00 2001 From: Gregorius Soedharmo Date: Fri, 26 Aug 2022 21:08:47 +0700 Subject: [PATCH 08/11] Add/update Setup classes (#235) --- .../AzurePersistenceConfigSpec.cs | 207 ++++++++++++++---- .../AzurePersistence.cs | 2 +- .../Journal/AzureTableStorageJournal.cs | 20 +- .../AzureTableStorageJournalSettings.cs | 138 +++++++++++- .../Journal/AzureTableStorageJournalSetup.cs | 92 ++++++++ .../Query/AzureTableStorageReadJournal.cs | 23 +- .../AzureTableStorageReadJournalSetup.cs | 35 +++ .../Snapshot/AzureBlobSnapshotSetup.cs | 113 ++++++++-- .../Snapshot/AzureBlobSnapshotStore.cs | 24 +- .../AzureBlobSnapshotStoreSettings.cs | 130 +++++++++++ 10 files changed, 694 insertions(+), 90 deletions(-) create mode 100644 src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSetup.cs create mode 100644 src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournalSetup.cs diff --git a/src/Akka.Persistence.Azure.Tests/AzurePersistenceConfigSpec.cs b/src/Akka.Persistence.Azure.Tests/AzurePersistenceConfigSpec.cs index 2bdc59b4..3ff209c7 100644 --- a/src/Akka.Persistence.Azure.Tests/AzurePersistenceConfigSpec.cs +++ b/src/Akka.Persistence.Azure.Tests/AzurePersistenceConfigSpec.cs @@ -9,84 +9,199 @@ using Akka.Persistence.Azure.Journal; using Akka.Persistence.Azure.Query; using Akka.Persistence.Azure.Snapshot; +using Azure.Data.Tables; +using Azure.Identity; +using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; using FluentAssertions; +using FluentAssertions.Extensions; using Xunit; namespace Akka.Persistence.Azure.Tests { public class AzurePersistenceConfigSpec { + private const string SnapshotStorePath = "akka.persistence.snapshot-store.azure-blob-store"; + private const string JournalPath = "akka.persistence.journal.azure-table"; + + private static readonly AzureBlobSnapshotStoreSettings DefaultSnapshotSettings = + AzureBlobSnapshotStoreSettings.Create(AzurePersistence.DefaultConfig.GetConfig(SnapshotStorePath)); + + private static readonly AzureTableStorageJournalSettings DefaultJournalSettings = + AzureTableStorageJournalSettings.Create(AzurePersistence.DefaultConfig.GetConfig(JournalPath)); + [Fact] public void ShouldLoadDefaultConfig() { - var defaultConfig = AzurePersistence.DefaultConfig; - defaultConfig.HasPath("akka.persistence.journal.azure-table").Should().BeTrue(); - defaultConfig.HasPath("akka.persistence.snapshot-store.azure-blob-store").Should().BeTrue(); + AzurePersistence.DefaultConfig.HasPath(SnapshotStorePath).Should().BeTrue(); + AzurePersistence.DefaultConfig.HasPath(JournalPath).Should().BeTrue(); + AzurePersistence.DefaultConfig.HasPath(AzureTableStorageReadJournal.Identifier).Should().BeTrue(); } [Fact] public void ShouldParseDefaultSnapshotConfig() { - var blobSettings = - AzureBlobSnapshotStoreSettings.Create( - ConfigurationFactory.ParseString(@"akka.persistence.snapshot-store.azure-blob-store{ - connection-string = foo - container-name = bar - }").WithFallback(AzurePersistence.DefaultConfig) - .GetConfig("akka.persistence.snapshot-store.azure-blob-store")); + var settings = + AzureBlobSnapshotStoreSettings.Create(AzurePersistence.DefaultConfig.GetConfig(SnapshotStorePath)); - blobSettings.ContainerName.Should().Be("bar"); - blobSettings.ConnectionString.Should().Be("foo"); - blobSettings.ConnectTimeout.Should().Be(TimeSpan.FromSeconds(3)); - blobSettings.RequestTimeout.Should().Be(TimeSpan.FromSeconds(3)); - blobSettings.VerboseLogging.Should().BeFalse(); - blobSettings.ContainerPublicAccessType.Should().Be(PublicAccessType.None); + settings.ConnectionString.Should().BeEmpty(); + settings.ContainerName.Should().Be("akka-persistence-default-container"); + settings.ConnectTimeout.Should().Be(3.Seconds()); + settings.RequestTimeout.Should().Be(3.Seconds()); + settings.VerboseLogging.Should().BeFalse(); + settings.Development.Should().BeFalse(); + settings.AutoInitialize.Should().BeTrue(); + settings.ContainerPublicAccessType.Should().Be(PublicAccessType.None); + settings.ServiceUri.Should().BeNull(); + settings.DefaultAzureCredential.Should().BeNull(); + settings.BlobClientOptions.Should().BeNull(); } - [Fact] - public void ShouldProvideDefaultContainerNameValue() + [Fact(DisplayName = "AzureBlobSnapshotStoreSettings With overrides should override default values")] + public void SnapshotSettingsWithMethodsTest() { - var blobSettings = - AzureBlobSnapshotStoreSettings.Create( - ConfigurationFactory.ParseString(@"akka.persistence.snapshot-store.azure-blob-store{ - connection-string = foo - }").WithFallback(AzurePersistence.DefaultConfig) - .GetConfig("akka.persistence.snapshot-store.azure-blob-store")); + var uri = new Uri("https://whatever.com"); + var credentials = new DefaultAzureCredential(); + var options = new BlobClientOptions(); + var settings = DefaultSnapshotSettings + .WithConnectionString("abc") + .WithContainerName("bcd") + .WithConnectTimeout(1.Seconds()) + .WithRequestTimeout(2.Seconds()) + .WithVerboseLogging(true) + .WithDevelopment(true) + .WithAutoInitialize(false) + .WithContainerPublicAccessType(PublicAccessType.Blob) + .WithAzureCredential(uri, credentials, options); + + settings.ConnectionString.Should().Be("abc"); + settings.ContainerName.Should().Be("bcd"); + settings.ConnectTimeout.Should().Be(1.Seconds()); + settings.RequestTimeout.Should().Be(2.Seconds()); + settings.VerboseLogging.Should().BeTrue(); + settings.Development.Should().BeTrue(); + settings.AutoInitialize.Should().BeFalse(); + settings.ContainerPublicAccessType.Should().Be(PublicAccessType.Blob); + settings.ServiceUri.Should().Be(uri); + settings.DefaultAzureCredential.Should().Be(credentials); + settings.BlobClientOptions.Should().Be(options); + } - blobSettings.ContainerName.Should().Be("akka-persistence-default-container"); + [Fact(DisplayName = "AzureBlobSnapshotStoreSetup should override settings values")] + public void SnapshotSetupTest() + { + var uri = new Uri("https://whatever.com"); + var credentials = new DefaultAzureCredential(); + var options = new BlobClientOptions(); + var setup = new AzureBlobSnapshotSetup + { + ConnectionString = "abc", + ContainerName = "bcd", + ConnectTimeout = 1.Seconds(), + RequestTimeout = 2.Seconds(), + VerboseLogging = true, + Development = true, + AutoInitialize = false, + ContainerPublicAccessType = PublicAccessType.Blob, + ServiceUri = uri, + DefaultAzureCredential = credentials, + BlobClientOptions = options + }; + + var settings = setup.Apply(DefaultSnapshotSettings); + + settings.ConnectionString.Should().Be("abc"); + settings.ContainerName.Should().Be("bcd"); + settings.ConnectTimeout.Should().Be(1.Seconds()); + settings.RequestTimeout.Should().Be(2.Seconds()); + settings.VerboseLogging.Should().BeTrue(); + settings.Development.Should().BeTrue(); + settings.AutoInitialize.Should().BeFalse(); + settings.ContainerPublicAccessType.Should().Be(PublicAccessType.Blob); + settings.ServiceUri.Should().Be(uri); + settings.DefaultAzureCredential.Should().Be(credentials); + settings.BlobClientOptions.Should().Be(options); } [Fact] public void ShouldParseTableConfig() { - var tableSettings = - AzureTableStorageJournalSettings.Create( - ConfigurationFactory.ParseString(@"akka.persistence.journal.azure-table{ - connection-string = foo - table-name = bar - }").WithFallback(AzurePersistence.DefaultConfig) - .GetConfig("akka.persistence.journal.azure-table")); + var settings = DefaultJournalSettings; - tableSettings.TableName.Should().Be("bar"); - tableSettings.ConnectionString.Should().Be("foo"); - tableSettings.ConnectTimeout.Should().Be(TimeSpan.FromSeconds(3)); - tableSettings.RequestTimeout.Should().Be(TimeSpan.FromSeconds(3)); - tableSettings.VerboseLogging.Should().BeFalse(); + settings.ConnectionString.Should().BeEmpty(); + settings.TableName.Should().Be("AkkaPersistenceDefaultTable"); + settings.ConnectTimeout.Should().Be(3.Seconds()); + settings.RequestTimeout.Should().Be(3.Seconds()); + settings.VerboseLogging.Should().BeFalse(); + settings.Development.Should().BeFalse(); + settings.AutoInitialize.Should().BeTrue(); + settings.ServiceUri.Should().BeNull(); + settings.DefaultAzureCredential.Should().BeNull(); + settings.TableClientOptions.Should().BeNull(); } - [Fact] - public void ShouldProvideDefaultTableNameValue() + [Fact(DisplayName = "AzureTableStorageJournalSettings With overrides should override default values")] + public void JournalSettingsWithMethodsTest() { - var tableSettings = - AzureTableStorageJournalSettings.Create( - ConfigurationFactory.ParseString(@"akka.persistence.journal.azure-table{ - connection-string = foo - }").WithFallback(AzurePersistence.DefaultConfig) - .GetConfig("akka.persistence.journal.azure-table")); - tableSettings.TableName.Should().Be("AkkaPersistenceDefaultTable"); + var uri = new Uri("https://whatever.com"); + var credentials = new DefaultAzureCredential(); + var options = new TableClientOptions(); + var settings = DefaultJournalSettings + .WithConnectionString("abc") + .WithTableName("bcd") + .WithConnectTimeout(1.Seconds()) + .WithRequestTimeout(2.Seconds()) + .WithVerboseLogging(true) + .WithDevelopment(true) + .WithAutoInitialize(false) + .WithAzureCredential(uri, credentials, options); + + settings.ConnectionString.Should().Be("abc"); + settings.TableName.Should().Be("bcd"); + settings.ConnectTimeout.Should().Be(1.Seconds()); + settings.RequestTimeout.Should().Be(2.Seconds()); + settings.VerboseLogging.Should().BeTrue(); + settings.Development.Should().BeTrue(); + settings.AutoInitialize.Should().BeFalse(); + settings.ServiceUri.Should().Be(uri); + settings.DefaultAzureCredential.Should().Be(credentials); + settings.TableClientOptions.Should().Be(options); } + [Fact(DisplayName = "AzureTableStorageJournalSetup should override settings values")] + public void JournalSetupTest() + { + var uri = new Uri("https://whatever.com"); + var credentials = new DefaultAzureCredential(); + var options = new TableClientOptions(); + var setup = new AzureTableStorageJournalSetup + { + ConnectionString = "abc", + TableName = "bcd", + ConnectTimeout = 1.Seconds(), + RequestTimeout = 2.Seconds(), + VerboseLogging = true, + Development = true, + AutoInitialize = false, + ServiceUri = uri, + DefaultAzureCredential = credentials, + TableClientOptions = options + }; + + var settings = setup.Apply(DefaultJournalSettings); + + settings.ConnectionString.Should().Be("abc"); + settings.TableName.Should().Be("bcd"); + settings.ConnectTimeout.Should().Be(1.Seconds()); + settings.RequestTimeout.Should().Be(2.Seconds()); + settings.VerboseLogging.Should().BeTrue(); + settings.Development.Should().BeTrue(); + settings.AutoInitialize.Should().BeFalse(); + settings.ServiceUri.Should().Be(uri); + settings.DefaultAzureCredential.Should().Be(credentials); + settings.TableClientOptions.Should().Be(options); + } + [Theory] [InlineData("fo", "Invalid table name length")] [InlineData("1foo", "Invalid table name")] diff --git a/src/Akka.Persistence.Azure/AzurePersistence.cs b/src/Akka.Persistence.Azure/AzurePersistence.cs index 478f8a57..7abeb4bb 100644 --- a/src/Akka.Persistence.Azure/AzurePersistence.cs +++ b/src/Akka.Persistence.Azure/AzurePersistence.cs @@ -34,7 +34,7 @@ public AzurePersistence(ActorSystem system, AzureTableStorageJournalSettings tab /// /// The default HOCON configuration for . /// - public static Config DefaultConfig => + public static readonly Config DefaultConfig = ConfigurationFactory.FromResource("Akka.Persistence.Azure.reference.conf"); /// diff --git a/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournal.cs b/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournal.cs index 18915695..3b925498 100644 --- a/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournal.cs +++ b/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournal.cs @@ -61,8 +61,26 @@ public AzureTableStorageJournal(Config config = null) AzurePersistence.Get(Context.System).TableSettings : AzureTableStorageJournalSettings.Create(config); + var setup = Context.System.Settings.Setup.Get(); + if (setup.HasValue) + _settings = setup.Value.Apply(_settings); + _serialization = new SerializationHelper(Context.System); - _tableServiceClient = new TableServiceClient(_settings.ConnectionString); + + if (_settings.Development) + { + _tableServiceClient = new TableServiceClient(connectionString: "UseDevelopmentStorage=true"); + } + else + { + // Use DefaultAzureCredential if both ServiceUri and DefaultAzureCredential are populated in the settings + _tableServiceClient = _settings.ServiceUri != null && _settings.DefaultAzureCredential != null + ? new TableServiceClient( + endpoint: _settings.ServiceUri, + tokenCredential: _settings.DefaultAzureCredential, + options: _settings.TableClientOptions) + : new TableServiceClient(connectionString: _settings.ConnectionString); + } } public TableClient Table diff --git a/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSettings.cs b/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSettings.cs index 8ac6f0ba..95ed994e 100644 --- a/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSettings.cs +++ b/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSettings.cs @@ -6,8 +6,11 @@ using System; using System.Linq; +using Akka.Actor; using Akka.Configuration; using Akka.Persistence.Azure.Util; +using Azure.Data.Tables; +using Azure.Identity; namespace Akka.Persistence.Azure.Journal { @@ -18,6 +21,7 @@ public sealed class AzureTableStorageJournalSettings { private static readonly string[] ReservedTableNames = {"tables"}; + [Obsolete] public AzureTableStorageJournalSettings( string connectionString, string tableName, @@ -26,6 +30,30 @@ public AzureTableStorageJournalSettings( bool verboseLogging, bool development, bool autoInitialize) + : this( + connectionString: connectionString, + tableName: tableName, + connectTimeout: connectTimeout, + requestTimeout: requestTimeout, + verboseLogging: verboseLogging, + development: development, + autoInitialize: autoInitialize, + serviceUri: null, + defaultAzureCredential: null, + tableClientOptions: null) + { } + + public AzureTableStorageJournalSettings( + string connectionString, + string tableName, + TimeSpan connectTimeout, + TimeSpan requestTimeout, + bool verboseLogging, + bool development, + bool autoInitialize, + Uri serviceUri, + DefaultAzureCredential defaultAzureCredential, + TableClientOptions tableClientOptions) { if(string.IsNullOrWhiteSpace(tableName)) throw new ConfigurationException("[AzureTableStorageJournal] Table name is null or empty."); @@ -45,6 +73,9 @@ public AzureTableStorageJournalSettings( VerboseLogging = verboseLogging; Development = development; AutoInitialize = autoInitialize; + ServiceUri = serviceUri; + DefaultAzureCredential = defaultAzureCredential; + TableClientOptions = tableClientOptions; } /// @@ -72,10 +103,97 @@ public AzureTableStorageJournalSettings( /// public bool VerboseLogging { get; } + /// + /// Flag that we're running in development mode. When this is set, and + /// will be ignored, replaced with "UseDevelopmentStorage=true" for local + /// connection to Azurite. + /// public bool Development { get; } + /// + /// Automatically create the Table Storage table if no existing table is found + /// public bool AutoInitialize { get; } + /// + /// A referencing the blob service. + /// This is likely to be similar to "https://{account_name}.table.core.windows.net". + /// + public Uri ServiceUri { get; } + + /// + /// The used to sign API requests. + /// + public DefaultAzureCredential DefaultAzureCredential { get; } + + /// + /// Optional client options that define the transport pipeline policies for authentication, + /// retries, etc., that are applied to every request. + /// + public TableClientOptions TableClientOptions { get; } + + public AzureTableStorageJournalSettings WithConnectionString(string connectionString) + => Copy(connectionString: connectionString); + public AzureTableStorageJournalSettings WithTableName(string tableName) + => Copy(tableName: tableName); + public AzureTableStorageJournalSettings WithConnectTimeout(TimeSpan connectTimeout) + => Copy(connectTimeout: connectTimeout); + public AzureTableStorageJournalSettings WithRequestTimeout(TimeSpan requestTimeout) + => Copy(requestTimeout: requestTimeout); + public AzureTableStorageJournalSettings WithVerboseLogging(bool verboseLogging) + => Copy(verboseLogging: verboseLogging); + public AzureTableStorageJournalSettings WithDevelopment(bool development) + => Copy(development: development); + public AzureTableStorageJournalSettings WithAutoInitialize(bool autoInitialize) + => Copy(autoInitialize: autoInitialize); + public AzureTableStorageJournalSettings WithAzureCredential( + Uri serviceUri, + DefaultAzureCredential defaultAzureCredential, + TableClientOptions tableClientOptions = null) + => Copy( + serviceUri: serviceUri, + defaultAzureCredential: defaultAzureCredential, + tableClientOptions: tableClientOptions); + + private AzureTableStorageJournalSettings Copy( + string connectionString = null, + string tableName = null, + TimeSpan? connectTimeout = null, + TimeSpan? requestTimeout = null, + bool? verboseLogging = null, + bool? development = null, + bool? autoInitialize = null, + Uri serviceUri = null, + DefaultAzureCredential defaultAzureCredential = null, + TableClientOptions tableClientOptions = null) + => new AzureTableStorageJournalSettings( + connectionString: connectionString ?? ConnectionString, + tableName: tableName ?? TableName, + connectTimeout: connectTimeout ?? ConnectTimeout, + requestTimeout: requestTimeout ?? RequestTimeout, + verboseLogging: verboseLogging ?? VerboseLogging, + development: development ?? Development, + autoInitialize: autoInitialize ?? AutoInitialize, + serviceUri: serviceUri ?? ServiceUri, + defaultAzureCredential: defaultAzureCredential ?? DefaultAzureCredential, + tableClientOptions: tableClientOptions ?? TableClientOptions); + + /// + /// Creates an instance using the + /// `akka.persistence.journal.azure-table` HOCON configuration section inside + /// the settings. + /// + /// The to extract the configuration from + /// A new settings instance. + public static AzureTableStorageJournalSettings Create(ActorSystem system) + { + var config = system.Settings.Config.GetConfig("akka.persistence.journal.azure-table"); + if (config is null) + throw new ConfigurationException( + "Could not find HOCON config at path 'akka.persistence.journal.azure-table'"); + return Create(config); + } + /// /// Creates an instance using the /// `akka.persistence.journal.azure-table` HOCON configuration section. @@ -84,6 +202,9 @@ public AzureTableStorageJournalSettings( /// A new settings instance. public static AzureTableStorageJournalSettings Create(Config config) { + if (config is null) + throw new ArgumentNullException(nameof(config)); + var connectionString = config.GetString("connection-string"); var tableName = config.GetString("table-name"); var connectTimeout = config.GetTimeSpan("connect-timeout", TimeSpan.FromSeconds(3)); @@ -93,13 +214,16 @@ public static AzureTableStorageJournalSettings Create(Config config) var autoInitialize = config.GetBoolean("auto-initialize", true); return new AzureTableStorageJournalSettings( - connectionString, - tableName, - connectTimeout, - requestTimeout, - verbose, - development, - autoInitialize); + connectionString: connectionString, + tableName: tableName, + connectTimeout: connectTimeout, + requestTimeout: requestTimeout, + verboseLogging: verbose, + development: development, + autoInitialize: autoInitialize, + serviceUri: null, + defaultAzureCredential: null, + tableClientOptions: null); } } } \ No newline at end of file diff --git a/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSetup.cs b/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSetup.cs new file mode 100644 index 00000000..3e42ad35 --- /dev/null +++ b/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSetup.cs @@ -0,0 +1,92 @@ +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2018 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using System; +using Akka.Actor.Setup; +using Azure.Data.Tables; +using Azure.Identity; + +namespace Akka.Persistence.Azure.Journal +{ + public class AzureTableStorageJournalSetup : Setup + { + /// + /// The connection string for connecting to Windows Azure table storage. + /// + public string ConnectionString { get; set; } + + /// + /// The table of the table we'll be connecting to. + /// + public string TableName { get; set; } + + /// + /// Initial timeout to use when connecting to Azure Table Storage for the first time. + /// + public TimeSpan? ConnectTimeout { get; set; } + + /// + /// Timeouts for individual read, write, and delete requests to Azure Table Storage. + /// + public TimeSpan? RequestTimeout { get; set; } + + /// + /// For debugging purposes only. Logs every individual operation to Azure table storage. + /// + public bool? VerboseLogging { get; set; } + + /// + /// Flag that we're running in development mode. When this is set, and + /// will be ignored, replaced with "UseDevelopmentStorage=true" for local + /// connection to Azurite. + /// + public bool? Development { get; set; } + + /// + /// Automatically create the Table Storage table if no existing table is found + /// + public bool? AutoInitialize { get; set; } + + /// + /// A referencing the blob service. + /// This is likely to be similar to "https://{account_name}.table.core.windows.net". + /// + public Uri ServiceUri { get; set; } + + /// + /// The used to sign API requests. + /// + public DefaultAzureCredential DefaultAzureCredential { get; set; } + + /// + /// Optional client options that define the transport pipeline policies for authentication, + /// retries, etc., that are applied to every request. + /// + public TableClientOptions TableClientOptions { get; set; } + + internal AzureTableStorageJournalSettings Apply(AzureTableStorageJournalSettings settings) + { + if (ConnectionString != null) + settings = settings.WithConnectionString(ConnectionString); + if (TableName != null) + settings = settings.WithTableName(TableName); + if (ConnectTimeout != null) + settings = settings.WithConnectTimeout(ConnectTimeout.Value); + if (RequestTimeout != null) + settings = settings.WithRequestTimeout(RequestTimeout.Value); + if (VerboseLogging != null) + settings = settings.WithVerboseLogging(VerboseLogging.Value); + if (Development != null) + settings = settings.WithDevelopment(Development.Value); + if (AutoInitialize != null) + settings = settings.WithAutoInitialize(AutoInitialize.Value); + if (ServiceUri != null && DefaultAzureCredential != null) + settings = settings.WithAzureCredential(ServiceUri, DefaultAzureCredential, TableClientOptions); + + return settings; + } + } +} \ No newline at end of file diff --git a/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournal.cs b/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournal.cs index ac619942..aaa35d23 100644 --- a/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournal.cs +++ b/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournal.cs @@ -17,26 +17,37 @@ public class AzureTableStorageReadJournal : IReadJournal, IEventsByTagQuery, ICurrentEventsByTagQuery { - public static string Identifier = "akka.persistence.query.journal.azure-table"; + public const string Identifier = "akka.persistence.query.journal.azure-table"; private readonly int _maxBufferSize; private readonly TimeSpan _refreshInterval; private readonly string _writeJournalPluginId; /// - /// Returns a default query configuration for akka persistence SQLite-based journals and snapshot stores. + /// Returns a default query configuration for akka persistence Azure-based journals and snapshot stores. /// /// - public static Config DefaultConfiguration() - { - return ConfigurationFactory.FromResource("Akka.Persistence.Azure.reference.conf"); - } + // NOTE: Do NOT remove this method, this is being called through reflection magic code + // in Akka.Persistence.Query.PersistenceQuery.GetDefaultConfig() + public static Config DefaultConfiguration() => AzurePersistence.DefaultConfig; public AzureTableStorageReadJournal(ExtendedActorSystem system, Config config) { _maxBufferSize = config.GetInt("max-buffer-size"); _refreshInterval = config.GetTimeSpan("refresh-interval"); _writeJournalPluginId = config.GetString("write-plugin"); + + var setupOption = system.Settings.Setup.Get(); + if (setupOption.HasValue) + { + var setup = setupOption.Value; + if (setup.MaxBufferSize != null) + _maxBufferSize = setup.MaxBufferSize.Value; + if (setup.RefreshInterval != null) + _refreshInterval = setup.RefreshInterval.Value; + if (!string.IsNullOrWhiteSpace(setup.WritePluginId)) + _writeJournalPluginId = setup.WritePluginId; + } } /// diff --git a/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournalSetup.cs b/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournalSetup.cs new file mode 100644 index 00000000..733a07f8 --- /dev/null +++ b/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournalSetup.cs @@ -0,0 +1,35 @@ +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2018 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using System; +using Akka.Actor.Setup; + +namespace Akka.Persistence.Azure.Query +{ + public class AzureTableStorageReadJournalSetup: Setup + { + /// + /// How many events to fetch in one query (replay) and keep buffered until they + /// are delivered downstream. + /// + public int? MaxBufferSize { get; set; } + + /// + /// The Azure Table write journal is notifying the query side as soon as things + /// are persisted, but for efficiency reasons the query side retrieves the events + /// in batches that sometimes can be delayed up to the configured . + /// + public TimeSpan? RefreshInterval { get; set; } + + /// + /// Absolute path to the write journal plugin configuration entry that this + /// query journal will connect to. + /// If undefined (or "") it will connect to the default journal as specified by the + /// akka.persistence.journal.plugin property. + /// + public string WritePluginId { get; set; } + } +} \ No newline at end of file diff --git a/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotSetup.cs b/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotSetup.cs index c7c26a9e..f6d10054 100644 --- a/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotSetup.cs +++ b/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotSetup.cs @@ -1,12 +1,21 @@ -using System; -using System.Collections.Generic; -using System.Text; +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2018 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using System; using Akka.Actor.Setup; using Azure.Identity; using Azure.Storage.Blobs; +using Azure.Storage.Blobs.Models; namespace Akka.Persistence.Azure.Snapshot { + /// + /// Setup class for . + /// Any populated properties will override its respective HOCON setting. + /// public class AzureBlobSnapshotSetup : Setup { /// @@ -28,22 +37,94 @@ public static AzureBlobSnapshotSetup Create( Uri serviceUri, DefaultAzureCredential defaultAzureCredential, BlobClientOptions blobClientOptions = default) - => new AzureBlobSnapshotSetup(serviceUri, defaultAzureCredential, blobClientOptions); + => new AzureBlobSnapshotSetup + { + ServiceUri = serviceUri, + DefaultAzureCredential = defaultAzureCredential, + BlobClientOptions = blobClientOptions + }; - private AzureBlobSnapshotSetup( - Uri serviceUri, - DefaultAzureCredential azureCredential, - BlobClientOptions blobClientOptions) - { - ServiceUri = serviceUri; - DefaultAzureCredential = azureCredential; - BlobClientOptions = blobClientOptions; - } + /// + /// The connection string for connecting to Windows Azure blob storage account. + /// + public string ConnectionString { get; set; } + + /// + /// The table of the container we'll be using to serialize these blobs. + /// + public string ContainerName { get; set; } + + /// + /// Initial timeout to use when connecting to Azure Container Storage for the first time. + /// + public TimeSpan? ConnectTimeout { get; set; } + + /// + /// Timeouts for individual read, write, and delete requests to Azure Container Storage. + /// + public TimeSpan? RequestTimeout { get; set; } + + /// + /// For debugging purposes only. Logs every individual operation to Azure table storage. + /// + public bool? VerboseLogging { get; set; } + + /// + /// Flag that we're running in development mode. When this is set, and + /// will be ignored, replaced with "UseDevelopmentStorage=true" for local + /// connection to Azurite. + /// + public bool? Development { get; set; } + + /// + /// Automatically create the Blog Storage container if no existing Blob container is found + /// + public bool? AutoInitialize { get; set; } + + /// + /// The public access type of the auto-initialized Blob Storage container + /// + public PublicAccessType? ContainerPublicAccessType { get; set; } + + /// + /// A referencing the blob service. + /// This is likely to be similar to "https://{account_name}.blob.core.windows.net". + /// + public Uri ServiceUri { get; set; } - public Uri ServiceUri { get; } + /// + /// The used to sign API requests. + /// + public DefaultAzureCredential DefaultAzureCredential { get; set; } + + /// + /// Optional client options that define the transport pipeline policies for authentication, + /// retries, etc., that are applied to every request. + /// + public BlobClientOptions BlobClientOptions { get; set; } - public DefaultAzureCredential DefaultAzureCredential { get; } + internal AzureBlobSnapshotStoreSettings Apply(AzureBlobSnapshotStoreSettings settings) + { + if (ConnectionString != null) + settings = settings.WithConnectionString(ConnectionString); + if (ContainerName != null) + settings = settings.WithContainerName(ContainerName); + if (ConnectTimeout != null) + settings = settings.WithConnectTimeout(ConnectTimeout.Value); + if (RequestTimeout != null) + settings = settings.WithRequestTimeout(RequestTimeout.Value); + if (VerboseLogging != null) + settings = settings.WithVerboseLogging(VerboseLogging.Value); + if (Development != null) + settings = settings.WithDevelopment(Development.Value); + if (AutoInitialize != null) + settings = settings.WithAutoInitialize(AutoInitialize.Value); + if (ContainerPublicAccessType != null) + settings = settings.WithContainerPublicAccessType(ContainerPublicAccessType.Value); + if (ServiceUri != null && DefaultAzureCredential != null) + settings = settings.WithAzureCredential(ServiceUri, DefaultAzureCredential, BlobClientOptions); - public BlobClientOptions BlobClientOptions { get; } + return settings; + } } } diff --git a/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStore.cs b/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStore.cs index 2afe505b..488b04f8 100644 --- a/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStore.cs +++ b/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStore.cs @@ -54,24 +54,22 @@ public AzureBlobSnapshotStore(Config config = null) ? AzurePersistence.Get(Context.System).BlobSettings : AzureBlobSnapshotStoreSettings.Create(config); + var setup = Context.System.Settings.Setup.Get(); + if (setup.HasValue) + _settings = setup.Value.Apply(_settings); + if (_settings.Development) { - _serviceClient = new BlobServiceClient("UseDevelopmentStorage=true"); + _serviceClient = new BlobServiceClient(connectionString: "UseDevelopmentStorage=true"); } else { - var credentialSetup = Context.System.Settings.Setup.Get(); - if (credentialSetup.HasValue) - { - _serviceClient = new BlobServiceClient( - credentialSetup.Value.ServiceUri, - credentialSetup.Value.DefaultAzureCredential, - credentialSetup.Value.BlobClientOptions); - } - else - { - _serviceClient = new BlobServiceClient(_settings.ConnectionString); - } + _serviceClient = _settings.ServiceUri != null && _settings.DefaultAzureCredential != null + ? _serviceClient = new BlobServiceClient( + serviceUri: _settings.ServiceUri, + credential: _settings.DefaultAzureCredential, + options: _settings.BlobClientOptions) + : _serviceClient = new BlobServiceClient(connectionString: _settings.ConnectionString); } _containerClient = new Lazy(() => InitCloudStorage(5).Result); diff --git a/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStoreSettings.cs b/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStoreSettings.cs index f7c5aa26..25ca31e2 100644 --- a/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStoreSettings.cs +++ b/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStoreSettings.cs @@ -5,8 +5,11 @@ // ----------------------------------------------------------------------- using System; +using Akka.Actor; using Akka.Configuration; using Akka.Persistence.Azure.Util; +using Azure.Identity; +using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; namespace Akka.Persistence.Azure.Snapshot @@ -29,6 +32,7 @@ public AzureBlobSnapshotStoreSettings( : this(connectionString, containerName, connectTimeout, requestTimeout, verboseLogging, development, autoInitialize, PublicAccessType.BlobContainer) { } + [Obsolete] public AzureBlobSnapshotStoreSettings( string connectionString, string containerName, @@ -38,6 +42,32 @@ public AzureBlobSnapshotStoreSettings( bool development, bool autoInitialize, PublicAccessType containerPublicAccessType) + : this( + connectionString: connectionString, + containerName: containerName, + connectTimeout: connectTimeout, + requestTimeout: requestTimeout, + verboseLogging: verboseLogging, + development: development, + autoInitialize: autoInitialize, + containerPublicAccessType: containerPublicAccessType, + serviceUri: null, + defaultAzureCredential: null, + blobClientOption: null) + { } + + public AzureBlobSnapshotStoreSettings( + string connectionString, + string containerName, + TimeSpan connectTimeout, + TimeSpan requestTimeout, + bool verboseLogging, + bool development, + bool autoInitialize, + PublicAccessType containerPublicAccessType, + Uri serviceUri, + DefaultAzureCredential defaultAzureCredential, + BlobClientOptions blobClientOption) { if (string.IsNullOrWhiteSpace(containerName)) throw new ConfigurationException("[AzureBlobSnapshotStore] Container name is null or empty."); @@ -51,6 +81,9 @@ public AzureBlobSnapshotStoreSettings( Development = development; AutoInitialize = autoInitialize; ContainerPublicAccessType = containerPublicAccessType; + ServiceUri = serviceUri; + DefaultAzureCredential = defaultAzureCredential; + BlobClientOptions = blobClientOption; } /// @@ -78,12 +111,106 @@ public AzureBlobSnapshotStoreSettings( /// public bool VerboseLogging { get; } + /// + /// Flag that we're running in development mode. When this is set, and + /// will be ignored, replaced with "UseDevelopmentStorage=true" for local + /// connection to Azurite. + /// public bool Development { get; } + /// + /// Automatically create the Blog Storage container if no existing Blob container is found + /// public bool AutoInitialize { get; } + /// + /// The public access type of the auto-initialized Blob Storage container + /// public PublicAccessType ContainerPublicAccessType { get; } + /// + /// A referencing the blob service. + /// This is likely to be similar to "https://{account_name}.blob.core.windows.net". + /// + public Uri ServiceUri { get; } + + /// + /// The used to sign API requests. + /// + public DefaultAzureCredential DefaultAzureCredential { get; } + + /// + /// Optional client options that define the transport pipeline policies for authentication, + /// retries, etc., that are applied to every request. + /// + public BlobClientOptions BlobClientOptions { get; } + + public AzureBlobSnapshotStoreSettings WithConnectionString(string connectionString) + => Copy(connectionString: connectionString); + public AzureBlobSnapshotStoreSettings WithContainerName(string containerName) + => Copy(containerName: containerName); + public AzureBlobSnapshotStoreSettings WithConnectTimeout(TimeSpan connectTimeout) + => Copy(connectTimeout: connectTimeout); + public AzureBlobSnapshotStoreSettings WithRequestTimeout(TimeSpan requestTimeout) + => Copy(requestTimeout: requestTimeout); + public AzureBlobSnapshotStoreSettings WithVerboseLogging(bool verboseLogging) + => Copy(verboseLogging: verboseLogging); + public AzureBlobSnapshotStoreSettings WithDevelopment(bool development) + => Copy(development: development); + public AzureBlobSnapshotStoreSettings WithAutoInitialize(bool autoInitialize) + => Copy(autoInitialize: autoInitialize); + public AzureBlobSnapshotStoreSettings WithContainerPublicAccessType(PublicAccessType containerPublicAccessType) + => Copy(containerPublicAccessType: containerPublicAccessType); + public AzureBlobSnapshotStoreSettings WithAzureCredential( + Uri serviceUri, + DefaultAzureCredential defaultAzureCredential, + BlobClientOptions blobClientOption = null) + => Copy( + serviceUri: serviceUri, + defaultAzureCredential: defaultAzureCredential, + blobClientOption: blobClientOption); + + private AzureBlobSnapshotStoreSettings Copy( + string connectionString = null, + string containerName = null, + TimeSpan? connectTimeout = null, + TimeSpan? requestTimeout = null, + bool? verboseLogging = null, + bool? development = null, + bool? autoInitialize = null, + PublicAccessType? containerPublicAccessType = null, + Uri serviceUri = null, + DefaultAzureCredential defaultAzureCredential = null, + BlobClientOptions blobClientOption = null) + => new AzureBlobSnapshotStoreSettings( + connectionString ?? ConnectionString, + containerName ?? ContainerName, + connectTimeout ?? ConnectTimeout, + requestTimeout ?? RequestTimeout, + verboseLogging ?? VerboseLogging, + development ?? Development, + autoInitialize ?? AutoInitialize, + containerPublicAccessType ?? ContainerPublicAccessType, + serviceUri ?? ServiceUri, + defaultAzureCredential ?? DefaultAzureCredential, + blobClientOption ?? BlobClientOptions); + + /// + /// Creates an instance using the + /// `akka.persistence.snapshot-store.azure-blob-store` HOCON configuration section inside + /// the settings. + /// + /// The to extract the configuration from + /// A new settings instance. + public static AzureBlobSnapshotStoreSettings Create(ActorSystem system) + { + var config = system.Settings.Config.GetConfig("akka.persistence.snapshot-store.azure-blob-store"); + if (config is null) + throw new ConfigurationException( + "Could not find HOCON config at path 'akka.persistence.snapshot-store.azure-blob-store'"); + return Create(config); + } + /// /// Creates an instance using the /// `akka.persistence.snapshot-store.azure-blob-store` HOCON configuration section. @@ -92,6 +219,9 @@ public AzureBlobSnapshotStoreSettings( /// A new settings instance. public static AzureBlobSnapshotStoreSettings Create(Config config) { + if (config is null) + throw new ArgumentNullException(nameof(config)); + var connectionString = config.GetString("connection-string"); var containerName = config.GetString("container-name"); var connectTimeout = config.GetTimeSpan("connect-timeout", TimeSpan.FromSeconds(3)); From 27e71216851645db0d1b233f502ba6107686ade7 Mon Sep 17 00:00:00 2001 From: Gregorius Soedharmo Date: Sat, 27 Aug 2022 00:36:24 +0700 Subject: [PATCH 09/11] Update copyright headers (#238) --- .../AzurePersistenceExtensions.cs | 6 ++++++ .../AzureJournalPerfSpecs.cs | 2 +- .../AzureBlobSnapshotStoreSpec.cs | 2 +- .../AzurePersistenceConfigSpec.cs | 2 +- src/Akka.Persistence.Azure.Tests/AzureTableJournalSpec.cs | 2 +- src/Akka.Persistence.Azure/AzurePersistence.cs | 2 +- src/Akka.Persistence.Azure/CloudTableExtensions.cs | 6 ++++++ .../Journal/AzureTableStorageJournal.cs | 2 +- .../Journal/AzureTableStorageJournalSettings.cs | 2 +- .../Journal/AzureTableStorageJournalSetup.cs | 2 +- src/Akka.Persistence.Azure/ListExtensions.cs | 6 ++++++ .../Query/AzureTableStorageReadJournal.cs | 8 +++++++- .../Query/AzureTableStorageReadJournalProvider.cs | 8 +++++++- .../Query/AzureTableStorageReadJournalSetup.cs | 2 +- src/Akka.Persistence.Azure/Query/DeliveryBuffer.cs | 8 +++++++- src/Akka.Persistence.Azure/Query/Messages.cs | 8 +++++++- .../Publishers/AbstractEventsByPersistenceIdPublisher.cs | 8 +++++++- .../Query/Publishers/AbstractEventsByTagPublisher.cs | 8 +++++++- .../Query/Publishers/AllPersistenceIdsPublisher.cs | 8 +++++++- .../Publishers/CurrentEventsByPersistenceIdPublisher.cs | 8 +++++++- .../Query/Publishers/CurrentEventsByTagPublisher.cs | 8 +++++++- .../Query/Publishers/EventsByPersistenceIdPublisher.cs | 8 +++++++- .../Query/Publishers/EventsByTagPublisher.cs | 8 +++++++- .../Publishers/LiveEventsByPersistenceIdPublisher.cs | 8 +++++++- .../Query/Publishers/LiveEventsByTagPublisher.cs | 8 +++++++- src/Akka.Persistence.Azure/SerializationHelper.cs | 2 +- .../Snapshot/AzureBlobSnapshotSetup.cs | 2 +- .../Snapshot/AzureBlobSnapshotStore.cs | 2 +- .../Snapshot/AzureBlobSnapshotStoreSettings.cs | 2 +- .../TableEntities/AllPersistenceIdsEntry.cs | 8 +++++++- src/Akka.Persistence.Azure/TableEntities/EventTagEntry.cs | 8 +++++++- .../TableEntities/HighestSequenceNrEntry.cs | 8 +++++++- .../TableEntities/PersistentJournalEntry.cs | 2 +- .../Util/PartitionKeyEscapeHelper.cs | 6 ++++++ src/Akka.Persistence.Azure/Util/SeqNoHelper.cs | 8 +++++++- 35 files changed, 157 insertions(+), 31 deletions(-) diff --git a/src/Akka.Persistence.Azure.Hosting/AzurePersistenceExtensions.cs b/src/Akka.Persistence.Azure.Hosting/AzurePersistenceExtensions.cs index a9fd2aa1..72590e9a 100644 --- a/src/Akka.Persistence.Azure.Hosting/AzurePersistenceExtensions.cs +++ b/src/Akka.Persistence.Azure.Hosting/AzurePersistenceExtensions.cs @@ -1,3 +1,9 @@ +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + using System; using Akka.Actor; using Akka.Configuration; diff --git a/src/Akka.Persistence.Azure.Tests.Performance/AzureJournalPerfSpecs.cs b/src/Akka.Persistence.Azure.Tests.Performance/AzureJournalPerfSpecs.cs index d02aab1c..a1a4d474 100644 --- a/src/Akka.Persistence.Azure.Tests.Performance/AzureJournalPerfSpecs.cs +++ b/src/Akka.Persistence.Azure.Tests.Performance/AzureJournalPerfSpecs.cs @@ -1,6 +1,6 @@ // ----------------------------------------------------------------------- // -// Copyright (C) 2015 - 2018 Petabridge, LLC +// Copyright (C) 2015 - 2022 Petabridge, LLC // // ----------------------------------------------------------------------- diff --git a/src/Akka.Persistence.Azure.Tests/AzureBlobSnapshotStoreSpec.cs b/src/Akka.Persistence.Azure.Tests/AzureBlobSnapshotStoreSpec.cs index a94842ff..bb548412 100644 --- a/src/Akka.Persistence.Azure.Tests/AzureBlobSnapshotStoreSpec.cs +++ b/src/Akka.Persistence.Azure.Tests/AzureBlobSnapshotStoreSpec.cs @@ -1,6 +1,6 @@ // ----------------------------------------------------------------------- // -// Copyright (C) 2015 - 2018 Petabridge, LLC +// Copyright (C) 2015 - 2022 Petabridge, LLC // // ----------------------------------------------------------------------- diff --git a/src/Akka.Persistence.Azure.Tests/AzurePersistenceConfigSpec.cs b/src/Akka.Persistence.Azure.Tests/AzurePersistenceConfigSpec.cs index 3ff209c7..050d189d 100644 --- a/src/Akka.Persistence.Azure.Tests/AzurePersistenceConfigSpec.cs +++ b/src/Akka.Persistence.Azure.Tests/AzurePersistenceConfigSpec.cs @@ -1,6 +1,6 @@ // ----------------------------------------------------------------------- // -// Copyright (C) 2015 - 2018 Petabridge, LLC +// Copyright (C) 2015 - 2022 Petabridge, LLC // // ----------------------------------------------------------------------- diff --git a/src/Akka.Persistence.Azure.Tests/AzureTableJournalSpec.cs b/src/Akka.Persistence.Azure.Tests/AzureTableJournalSpec.cs index c28cc743..2a003eeb 100644 --- a/src/Akka.Persistence.Azure.Tests/AzureTableJournalSpec.cs +++ b/src/Akka.Persistence.Azure.Tests/AzureTableJournalSpec.cs @@ -1,6 +1,6 @@ // ----------------------------------------------------------------------- // -// Copyright (C) 2015 - 2018 Petabridge, LLC +// Copyright (C) 2015 - 2022 Petabridge, LLC // // ----------------------------------------------------------------------- diff --git a/src/Akka.Persistence.Azure/AzurePersistence.cs b/src/Akka.Persistence.Azure/AzurePersistence.cs index 7abeb4bb..a753382f 100644 --- a/src/Akka.Persistence.Azure/AzurePersistence.cs +++ b/src/Akka.Persistence.Azure/AzurePersistence.cs @@ -1,6 +1,6 @@ // ----------------------------------------------------------------------- // -// Copyright (C) 2015 - 2018 Petabridge, LLC +// Copyright (C) 2015 - 2022 Petabridge, LLC // // ----------------------------------------------------------------------- diff --git a/src/Akka.Persistence.Azure/CloudTableExtensions.cs b/src/Akka.Persistence.Azure/CloudTableExtensions.cs index b4e83bb2..d8fca593 100644 --- a/src/Akka.Persistence.Azure/CloudTableExtensions.cs +++ b/src/Akka.Persistence.Azure/CloudTableExtensions.cs @@ -1,3 +1,9 @@ +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + using System.Collections.Generic; using System.Collections.Immutable; using System.Threading.Tasks; diff --git a/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournal.cs b/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournal.cs index 3b925498..8b42f7b2 100644 --- a/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournal.cs +++ b/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournal.cs @@ -1,6 +1,6 @@ // ----------------------------------------------------------------------- // -// Copyright (C) 2015 - 2018 Petabridge, LLC +// Copyright (C) 2015 - 2022 Petabridge, LLC // // ----------------------------------------------------------------------- diff --git a/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSettings.cs b/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSettings.cs index 95ed994e..20c67dd2 100644 --- a/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSettings.cs +++ b/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSettings.cs @@ -1,6 +1,6 @@ // ----------------------------------------------------------------------- // -// Copyright (C) 2015 - 2018 Petabridge, LLC +// Copyright (C) 2015 - 2022 Petabridge, LLC // // ----------------------------------------------------------------------- diff --git a/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSetup.cs b/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSetup.cs index 3e42ad35..760f4ff9 100644 --- a/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSetup.cs +++ b/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSetup.cs @@ -1,6 +1,6 @@ // ----------------------------------------------------------------------- // -// Copyright (C) 2015 - 2018 Petabridge, LLC +// Copyright (C) 2015 - 2022 Petabridge, LLC // // ----------------------------------------------------------------------- diff --git a/src/Akka.Persistence.Azure/ListExtensions.cs b/src/Akka.Persistence.Azure/ListExtensions.cs index 50807ca4..ad849bca 100644 --- a/src/Akka.Persistence.Azure/ListExtensions.cs +++ b/src/Akka.Persistence.Azure/ListExtensions.cs @@ -1,3 +1,9 @@ +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; diff --git a/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournal.cs b/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournal.cs index aaa35d23..c7f06aed 100644 --- a/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournal.cs +++ b/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournal.cs @@ -1,4 +1,10 @@ -using System; +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using System; using Akka.Actor; using Akka.Configuration; using Akka.Persistence.Azure.Query.Publishers; diff --git a/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournalProvider.cs b/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournalProvider.cs index b2e309d3..9efd1403 100644 --- a/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournalProvider.cs +++ b/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournalProvider.cs @@ -1,4 +1,10 @@ -using Akka.Actor; +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using Akka.Actor; using Akka.Configuration; using Akka.Persistence.Query; diff --git a/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournalSetup.cs b/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournalSetup.cs index 733a07f8..8096d975 100644 --- a/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournalSetup.cs +++ b/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournalSetup.cs @@ -1,6 +1,6 @@ // ----------------------------------------------------------------------- // -// Copyright (C) 2015 - 2018 Petabridge, LLC +// Copyright (C) 2015 - 2022 Petabridge, LLC // // ----------------------------------------------------------------------- diff --git a/src/Akka.Persistence.Azure/Query/DeliveryBuffer.cs b/src/Akka.Persistence.Azure/Query/DeliveryBuffer.cs index 3f55f3ec..7b5ebcf9 100644 --- a/src/Akka.Persistence.Azure/Query/DeliveryBuffer.cs +++ b/src/Akka.Persistence.Azure/Query/DeliveryBuffer.cs @@ -1,4 +1,10 @@ -using System; +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using System; using System.Collections.Generic; using System.Collections.Immutable; diff --git a/src/Akka.Persistence.Azure/Query/Messages.cs b/src/Akka.Persistence.Azure/Query/Messages.cs index 4fb9c420..c83ab0d8 100644 --- a/src/Akka.Persistence.Azure/Query/Messages.cs +++ b/src/Akka.Persistence.Azure/Query/Messages.cs @@ -1,4 +1,10 @@ -using Akka.Actor; +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using Akka.Actor; using Akka.Event; using System; using System.Collections.Generic; diff --git a/src/Akka.Persistence.Azure/Query/Publishers/AbstractEventsByPersistenceIdPublisher.cs b/src/Akka.Persistence.Azure/Query/Publishers/AbstractEventsByPersistenceIdPublisher.cs index ee6e29e2..6b9221cf 100644 --- a/src/Akka.Persistence.Azure/Query/Publishers/AbstractEventsByPersistenceIdPublisher.cs +++ b/src/Akka.Persistence.Azure/Query/Publishers/AbstractEventsByPersistenceIdPublisher.cs @@ -1,4 +1,10 @@ -using Akka.Actor; +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using Akka.Actor; using Akka.Event; using Akka.Persistence.Query; using Akka.Streams.Actors; diff --git a/src/Akka.Persistence.Azure/Query/Publishers/AbstractEventsByTagPublisher.cs b/src/Akka.Persistence.Azure/Query/Publishers/AbstractEventsByTagPublisher.cs index 4b0dcf34..bd9fe9dc 100644 --- a/src/Akka.Persistence.Azure/Query/Publishers/AbstractEventsByTagPublisher.cs +++ b/src/Akka.Persistence.Azure/Query/Publishers/AbstractEventsByTagPublisher.cs @@ -1,4 +1,10 @@ -using Akka.Actor; +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using Akka.Actor; using Akka.Event; using Akka.Persistence.Query; using Akka.Streams.Actors; diff --git a/src/Akka.Persistence.Azure/Query/Publishers/AllPersistenceIdsPublisher.cs b/src/Akka.Persistence.Azure/Query/Publishers/AllPersistenceIdsPublisher.cs index 5f149b01..00597c13 100644 --- a/src/Akka.Persistence.Azure/Query/Publishers/AllPersistenceIdsPublisher.cs +++ b/src/Akka.Persistence.Azure/Query/Publishers/AllPersistenceIdsPublisher.cs @@ -1,4 +1,10 @@ -using Akka.Actor; +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using Akka.Actor; using Akka.Streams.Actors; namespace Akka.Persistence.Azure.Query.Publishers diff --git a/src/Akka.Persistence.Azure/Query/Publishers/CurrentEventsByPersistenceIdPublisher.cs b/src/Akka.Persistence.Azure/Query/Publishers/CurrentEventsByPersistenceIdPublisher.cs index 65beaff0..8b1ae906 100644 --- a/src/Akka.Persistence.Azure/Query/Publishers/CurrentEventsByPersistenceIdPublisher.cs +++ b/src/Akka.Persistence.Azure/Query/Publishers/CurrentEventsByPersistenceIdPublisher.cs @@ -1,4 +1,10 @@ -using Akka.Actor; +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using Akka.Actor; namespace Akka.Persistence.Azure.Query.Publishers { diff --git a/src/Akka.Persistence.Azure/Query/Publishers/CurrentEventsByTagPublisher.cs b/src/Akka.Persistence.Azure/Query/Publishers/CurrentEventsByTagPublisher.cs index 67f9a9ea..06badbc5 100644 --- a/src/Akka.Persistence.Azure/Query/Publishers/CurrentEventsByTagPublisher.cs +++ b/src/Akka.Persistence.Azure/Query/Publishers/CurrentEventsByTagPublisher.cs @@ -1,4 +1,10 @@ -using Akka.Actor; +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using Akka.Actor; namespace Akka.Persistence.Azure.Query.Publishers { diff --git a/src/Akka.Persistence.Azure/Query/Publishers/EventsByPersistenceIdPublisher.cs b/src/Akka.Persistence.Azure/Query/Publishers/EventsByPersistenceIdPublisher.cs index 41008de8..33166e9e 100644 --- a/src/Akka.Persistence.Azure/Query/Publishers/EventsByPersistenceIdPublisher.cs +++ b/src/Akka.Persistence.Azure/Query/Publishers/EventsByPersistenceIdPublisher.cs @@ -1,4 +1,10 @@ -using System; +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using System; using Akka.Actor; namespace Akka.Persistence.Azure.Query.Publishers diff --git a/src/Akka.Persistence.Azure/Query/Publishers/EventsByTagPublisher.cs b/src/Akka.Persistence.Azure/Query/Publishers/EventsByTagPublisher.cs index 6e79fcad..940e565a 100644 --- a/src/Akka.Persistence.Azure/Query/Publishers/EventsByTagPublisher.cs +++ b/src/Akka.Persistence.Azure/Query/Publishers/EventsByTagPublisher.cs @@ -1,4 +1,10 @@ -using System; +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using System; using Akka.Actor; namespace Akka.Persistence.Azure.Query.Publishers diff --git a/src/Akka.Persistence.Azure/Query/Publishers/LiveEventsByPersistenceIdPublisher.cs b/src/Akka.Persistence.Azure/Query/Publishers/LiveEventsByPersistenceIdPublisher.cs index ff63ef7b..4ff7cdde 100644 --- a/src/Akka.Persistence.Azure/Query/Publishers/LiveEventsByPersistenceIdPublisher.cs +++ b/src/Akka.Persistence.Azure/Query/Publishers/LiveEventsByPersistenceIdPublisher.cs @@ -1,4 +1,10 @@ -using System; +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using System; using Akka.Actor; namespace Akka.Persistence.Azure.Query.Publishers diff --git a/src/Akka.Persistence.Azure/Query/Publishers/LiveEventsByTagPublisher.cs b/src/Akka.Persistence.Azure/Query/Publishers/LiveEventsByTagPublisher.cs index f39a8026..8e3df20c 100644 --- a/src/Akka.Persistence.Azure/Query/Publishers/LiveEventsByTagPublisher.cs +++ b/src/Akka.Persistence.Azure/Query/Publishers/LiveEventsByTagPublisher.cs @@ -1,4 +1,10 @@ -using System; +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using System; using Akka.Actor; namespace Akka.Persistence.Azure.Query.Publishers diff --git a/src/Akka.Persistence.Azure/SerializationHelper.cs b/src/Akka.Persistence.Azure/SerializationHelper.cs index 6b785432..8d4126ad 100644 --- a/src/Akka.Persistence.Azure/SerializationHelper.cs +++ b/src/Akka.Persistence.Azure/SerializationHelper.cs @@ -1,6 +1,6 @@ // ----------------------------------------------------------------------- // -// Copyright (C) 2015 - 2018 Petabridge, LLC +// Copyright (C) 2015 - 2022 Petabridge, LLC // // ----------------------------------------------------------------------- diff --git a/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotSetup.cs b/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotSetup.cs index f6d10054..f9f66acf 100644 --- a/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotSetup.cs +++ b/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotSetup.cs @@ -1,6 +1,6 @@ // ----------------------------------------------------------------------- // -// Copyright (C) 2015 - 2018 Petabridge, LLC +// Copyright (C) 2015 - 2022 Petabridge, LLC // // ----------------------------------------------------------------------- diff --git a/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStore.cs b/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStore.cs index 488b04f8..94bf06b3 100644 --- a/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStore.cs +++ b/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStore.cs @@ -1,6 +1,6 @@ // ----------------------------------------------------------------------- // -// Copyright (C) 2015 - 2018 Petabridge, LLC +// Copyright (C) 2015 - 2022 Petabridge, LLC // // ----------------------------------------------------------------------- diff --git a/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStoreSettings.cs b/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStoreSettings.cs index 25ca31e2..50c0fcd6 100644 --- a/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStoreSettings.cs +++ b/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStoreSettings.cs @@ -1,6 +1,6 @@ // ----------------------------------------------------------------------- // -// Copyright (C) 2015 - 2018 Petabridge, LLC +// Copyright (C) 2015 - 2022 Petabridge, LLC // // ----------------------------------------------------------------------- diff --git a/src/Akka.Persistence.Azure/TableEntities/AllPersistenceIdsEntry.cs b/src/Akka.Persistence.Azure/TableEntities/AllPersistenceIdsEntry.cs index 5bb2dfd3..8e415605 100644 --- a/src/Akka.Persistence.Azure/TableEntities/AllPersistenceIdsEntry.cs +++ b/src/Akka.Persistence.Azure/TableEntities/AllPersistenceIdsEntry.cs @@ -1,4 +1,10 @@ -using System; +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using System; using Azure; using Azure.Data.Tables; diff --git a/src/Akka.Persistence.Azure/TableEntities/EventTagEntry.cs b/src/Akka.Persistence.Azure/TableEntities/EventTagEntry.cs index 9bb5df15..dd688936 100644 --- a/src/Akka.Persistence.Azure/TableEntities/EventTagEntry.cs +++ b/src/Akka.Persistence.Azure/TableEntities/EventTagEntry.cs @@ -1,4 +1,10 @@ -using System; +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using System; using System.Linq; using Akka.Persistence.Azure.Util; using Azure; diff --git a/src/Akka.Persistence.Azure/TableEntities/HighestSequenceNrEntry.cs b/src/Akka.Persistence.Azure/TableEntities/HighestSequenceNrEntry.cs index e4c34f03..e53981d8 100644 --- a/src/Akka.Persistence.Azure/TableEntities/HighestSequenceNrEntry.cs +++ b/src/Akka.Persistence.Azure/TableEntities/HighestSequenceNrEntry.cs @@ -1,4 +1,10 @@ -using System; +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using System; using Azure; using Azure.Data.Tables; diff --git a/src/Akka.Persistence.Azure/TableEntities/PersistentJournalEntry.cs b/src/Akka.Persistence.Azure/TableEntities/PersistentJournalEntry.cs index 7e64b913..a56d2523 100644 --- a/src/Akka.Persistence.Azure/TableEntities/PersistentJournalEntry.cs +++ b/src/Akka.Persistence.Azure/TableEntities/PersistentJournalEntry.cs @@ -1,6 +1,6 @@ // ----------------------------------------------------------------------- // -// Copyright (C) 2015 - 2018 Petabridge, LLC +// Copyright (C) 2015 - 2022 Petabridge, LLC // // ----------------------------------------------------------------------- diff --git a/src/Akka.Persistence.Azure/Util/PartitionKeyEscapeHelper.cs b/src/Akka.Persistence.Azure/Util/PartitionKeyEscapeHelper.cs index 4e026419..1ef75e9d 100644 --- a/src/Akka.Persistence.Azure/Util/PartitionKeyEscapeHelper.cs +++ b/src/Akka.Persistence.Azure/Util/PartitionKeyEscapeHelper.cs @@ -1,3 +1,9 @@ +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + using System; using System.Collections.Generic; diff --git a/src/Akka.Persistence.Azure/Util/SeqNoHelper.cs b/src/Akka.Persistence.Azure/Util/SeqNoHelper.cs index 7ae05a2c..b1df616c 100644 --- a/src/Akka.Persistence.Azure/Util/SeqNoHelper.cs +++ b/src/Akka.Persistence.Azure/Util/SeqNoHelper.cs @@ -1,4 +1,10 @@ -using System; +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015 - 2022 Petabridge, LLC +// +// ----------------------------------------------------------------------- + +using System; using System.Collections.Generic; using System.Text; From cdf3a41679f2906ea527a77c5ec36ccdf14de154 Mon Sep 17 00:00:00 2001 From: Gregorius Soedharmo Date: Mon, 29 Aug 2022 18:37:14 +0700 Subject: [PATCH 10/11] Update Akka.Hosting extension methods to support DefaultAzureCredential (#237) * Update Akka.Hosting extension methods to support DefaultAzureCredential (cherry picked from commit b37c9dba61b678e2bb98bc4cad394696c4e098a8) * Make setup classes sealed * Fix missing HOCON settings * Revert const back to public Co-authored-by: Aaron Stannard --- .../AzurePersistenceExtensions.cs | 445 +++++++++++++++--- .../AzurePersistenceHostingSanityCheck.cs | 2 + .../AzureTableStorageJournalSettings.cs | 10 +- .../Journal/AzureTableStorageJournalSetup.cs | 12 +- .../AzureTableStorageReadJournalSetup.cs | 2 +- .../Snapshot/AzureBlobSnapshotSetup.cs | 28 +- .../AzureBlobSnapshotStoreSettings.cs | 10 +- 7 files changed, 423 insertions(+), 86 deletions(-) diff --git a/src/Akka.Persistence.Azure.Hosting/AzurePersistenceExtensions.cs b/src/Akka.Persistence.Azure.Hosting/AzurePersistenceExtensions.cs index 72590e9a..821459eb 100644 --- a/src/Akka.Persistence.Azure.Hosting/AzurePersistenceExtensions.cs +++ b/src/Akka.Persistence.Azure.Hosting/AzurePersistenceExtensions.cs @@ -6,10 +6,13 @@ using System; using Akka.Actor; -using Akka.Configuration; using Akka.Hosting; -using Akka.Persistence.Azure.Query; +using Akka.Persistence.Azure.Journal; +using Akka.Persistence.Azure.Snapshot; using Akka.Persistence.Hosting; +using Azure.Data.Tables; +using Azure.Identity; +using Azure.Storage.Blobs; namespace Akka.Persistence.Azure.Hosting { @@ -21,62 +24,315 @@ public static class AzurePersistenceExtensions public const string DefaultTableName = "AkkaPersistenceDefaultTable"; public const string DefaultBlobContainerName = "akka-persistence-default-container"; - private static string ToHocon(bool b) + /// + /// Add an AzureTableStorage journal as the default Akka.Persistence + /// implementations for a given . + /// + /// + /// The builder instance being configured. + /// + /// + /// A referencing the Azure Storage Table service. + /// This is likely to be similar to "https://{account_name}.table.core.windows.net". + /// + /// + /// The used to sign API requests. + /// + /// + /// Optional client options that define the transport pipeline policies for authentication, + /// retries, etc., that are applied to every request. + /// + /// + /// Automatically create the Table Storage table and Storage blob if no existing table is found + /// + /// + /// The Azure table we'll be connecting to. + /// + /// + /// A delegate that can be used to configure an instance + /// to set up event adapters. + /// + /// + /// The same instance originally passed in. + /// + public static AkkaConfigurationBuilder WithAzureTableJournal(this AkkaConfigurationBuilder builder, + Uri serviceUri, + DefaultAzureCredential defaultAzureCredential, + TableClientOptions tableClientOptions = null, + bool autoInitialize = true, + string tableName = DefaultTableName, + Action eventAdapterConfigurator = null) { - return b ? "on" : "off"; + if (serviceUri is null) + throw new ArgumentNullException(nameof(serviceUri)); + + if (defaultAzureCredential is null) + throw new ArgumentNullException(nameof(defaultAzureCredential)); + + var setup = new AzureTableStorageJournalSetup + { + ServiceUri = serviceUri, + DefaultAzureCredential = defaultAzureCredential, + TableClientOptions = tableClientOptions, + AutoInitialize = autoInitialize, + TableName = tableName + }; + return WithAzureTableJournal(builder, setup, eventAdapterConfigurator); } - + /// + /// Add an AzureTableStorage journal as the default Akka.Persistence + /// implementations for a given . + /// + /// + /// The builder instance being configured. + /// + /// + /// The connection string for connecting to Windows Azure table storage. + /// + /// + /// Automatically create the Table Storage table and Storage blob if no existing table is found + /// + /// + /// The Azure table we'll be connecting to. + /// + /// + /// A delegate that can be used to configure an instance + /// to set up event adapters. + /// + /// + /// The same instance originally passed in. + /// public static AkkaConfigurationBuilder WithAzureTableJournal(this AkkaConfigurationBuilder builder, - string connectionString, bool autoInitialize = true, string tableName = DefaultTableName, Action configurator = null) + string connectionString, + bool autoInitialize = true, + string tableName = DefaultTableName, + Action eventAdapterConfigurator = null) { - Config journalConfiguration = @$" - akka.persistence {{ - journal {{ - plugin = ""akka.persistence.journal.azure-table"" - azure-table {{ - class = ""Akka.Persistence.Azure.Journal.AzureTableStorageJournal, Akka.Persistence.Azure"" - connection-string = ""{connectionString}"" - # the name of the Windows Azure Table used to persist journal events - table-name = ""{tableName}"" - auto-initialize = {ToHocon(autoInitialize)} - }} - }} - }}"; - - var finalConfig = journalConfiguration; - builder.AddHocon(finalConfig, HoconAddMode.Prepend); + if (string.IsNullOrWhiteSpace(connectionString)) + throw new ArgumentNullException(nameof(connectionString)); + + var setup = new AzureTableStorageJournalSetup + { + ConnectionString = connectionString, + AutoInitialize = autoInitialize, + TableName = tableName + }; + return WithAzureTableJournal(builder, setup, eventAdapterConfigurator); + } + + /// + /// Add an AzureTableStorage journal as the default Akka.Persistence + /// implementations for a given . + /// + /// + /// The builder instance being configured. + /// + /// + /// A delegate that can be used to configure an instance + /// to set up the AzureTableStorage journal. + /// + /// + /// A delegate that can be used to configure an instance + /// to set up event adapters. + /// + /// + /// The same instance originally passed in. + /// + public static AkkaConfigurationBuilder WithAzureTableJournal( + this AkkaConfigurationBuilder builder, + Action configure, + Action eventAdapterConfigurator = null) + { + if (configure is null) + throw new ArgumentNullException(nameof(configure)); + + var setup = new AzureTableStorageJournalSetup(); + configure(setup); + return WithAzureTableJournal(builder, setup, eventAdapterConfigurator); + } + + /// + /// Add an AzureTableStorage journal as the default Akka.Persistence + /// implementations for a given . + /// + /// + /// The builder instance being configured. + /// + /// + /// An instance that will be used to set up + /// the AzureTableStorage journal. + /// + /// + /// A delegate that can be used to configure an instance + /// to set up event adapters. + /// + /// + /// The same instance originally passed in. + /// + public static AkkaConfigurationBuilder WithAzureTableJournal( + this AkkaConfigurationBuilder builder, + AzureTableStorageJournalSetup setup, + Action eventAdapterConfigurator = null) + { + if (setup is null) + throw new ArgumentNullException(nameof(setup)); + + builder.AddHocon("akka.persistence.journal.plugin = \"akka.persistence.journal.azure-table\"", HoconAddMode.Prepend); + builder.AddSetup(setup); // PUSH DEFAULT CONFIG TO END builder.AddHocon(AzurePersistence.DefaultConfig, HoconAddMode.Append); - if (configurator != null) // configure event adapters + if (eventAdapterConfigurator != null) // configure event adapters { - builder.WithJournal("azure-table", configurator); + builder.WithJournal("azure-table", eventAdapterConfigurator); } return builder; } - public static AkkaConfigurationBuilder WithAzureBlobsSnapshotStore(this AkkaConfigurationBuilder builder, - string connectionString, bool autoInitialize = true, string containerName = DefaultBlobContainerName) + /// + /// Add an AzureBlobStorage snapshot-store as the default Akka.Persistence + /// implementations for a given . + /// + /// + /// The builder instance being configured. + /// + /// + /// A referencing the Azure Storage blob service. + /// This is likely to be similar to "https://{account_name}.blob.core.windows.net". + /// + /// + /// The used to sign API requests. + /// + /// + /// Optional client options that define the transport pipeline policies for authentication, + /// retries, etc., that are applied to every request. + /// + /// + /// Automatically create the Table Storage table and Storage blob if no existing table is found + /// + /// + /// The table of the container we'll be using to serialize these blobs. + /// + /// + /// The same instance originally passed in. + /// + public static AkkaConfigurationBuilder WithAzureBlobsSnapshotStore( + this AkkaConfigurationBuilder builder, + Uri serviceUri, + DefaultAzureCredential defaultAzureCredential, + BlobClientOptions blobClientOptions, + bool autoInitialize = true, + string containerName = DefaultBlobContainerName) { - Config journalConfiguration = @$" - akka.persistence {{ - snapshot-store {{ - plugin = ""akka.persistence.snapshot-store.azure-blob-store"" - azure-blob-store {{ - class = ""Akka.Persistence.Azure.Snapshot.AzureBlobSnapshotStore, Akka.Persistence.Azure"" - connection-string = ""{connectionString}"" - # the name of the Windows Azure Table used to persist journal events - container-name = ""{containerName}"" - auto-initialize = {ToHocon(autoInitialize)} - }} - }} - }}"; - - var finalConfig = journalConfiguration; - builder.AddHocon(finalConfig, HoconAddMode.Prepend); + if (serviceUri is null) + throw new ArgumentNullException(nameof(serviceUri)); + + if (defaultAzureCredential is null) + throw new ArgumentNullException(nameof(defaultAzureCredential)); + + var setup = new AzureBlobSnapshotSetup + { + ServiceUri = serviceUri, + DefaultAzureCredential = defaultAzureCredential, + BlobClientOptions = blobClientOptions, + AutoInitialize = autoInitialize, + ContainerName = containerName + }; + + return WithAzureBlobsSnapshotStore(builder, setup); + } + + /// + /// Add an AzureBlobStorage snapshot-store as the default Akka.Persistence + /// implementations for a given . + /// + /// + /// The builder instance being configured. + /// + /// + /// The connection string for connecting to Windows Azure table storage. + /// + /// + /// Automatically create the Table Storage table and Storage blob if no existing table is found + /// + /// + /// The table of the container we'll be using to serialize these blobs. + /// + /// + /// The same instance originally passed in. + /// + public static AkkaConfigurationBuilder WithAzureBlobsSnapshotStore( + this AkkaConfigurationBuilder builder, + string connectionString, + bool autoInitialize = true, + string containerName = DefaultBlobContainerName) + { + if (string.IsNullOrWhiteSpace(connectionString)) + throw new ArgumentNullException(nameof(connectionString)); + + var setup = new AzureBlobSnapshotSetup + { + ConnectionString = connectionString, + AutoInitialize = autoInitialize, + ContainerName = containerName + }; + + return WithAzureBlobsSnapshotStore(builder, setup); + } + + /// + /// Add an AzureBlobStorage snapshot-store as the default Akka.Persistence + /// implementations for a given . + /// + /// + /// The builder instance being configured. + /// + /// + /// A delegate that can be used to configure an instance + /// to set up the AzureBlobStorage snapshot-store. + /// + /// + /// The same instance originally passed in. + /// + public static AkkaConfigurationBuilder WithAzureBlobsSnapshotStore( + this AkkaConfigurationBuilder builder, + Action configure) + { + if (configure is null) + throw new ArgumentNullException(nameof(configure)); + + var setup = new AzureBlobSnapshotSetup(); + configure(setup); + + return WithAzureBlobsSnapshotStore(builder, setup); + } + + /// + /// Add an AzureBlobStorage snapshot-store as the default Akka.Persistence + /// implementations for a given . + /// + /// + /// The builder instance being configured. + /// + /// + /// An instance that will be used to set up + /// the AzureBlobStorage snapshot-store. + /// + /// + /// The same instance originally passed in. + /// + public static AkkaConfigurationBuilder WithAzureBlobsSnapshotStore( + this AkkaConfigurationBuilder builder, + AzureBlobSnapshotSetup setup) + { + if (setup is null) + throw new ArgumentNullException(nameof(setup)); + + builder.AddHocon("akka.persistence.snapshot-store.plugin = \"akka.persistence.snapshot-store.azure-blob-store\"", HoconAddMode.Prepend); + builder.AddSetup(setup); // PUSH DEFAULT CONFIG TO END builder.AddHocon(AzurePersistence.DefaultConfig, HoconAddMode.Append); @@ -85,24 +341,103 @@ class = ""Akka.Persistence.Azure.Snapshot.AzureBlobSnapshotStore, Akka.Persisten } /// - /// Adds both AzureTableStorage journal and AzureBlobStorage snapshot-store as the default Akka.Persistence - /// implementations for a given . + /// Adds both AzureTableStorage journal and AzureBlobStorage snapshot-store as the default Akka.Persistence + /// implementations for a given . /// - /// - /// - /// - /// - /// - /// - /// - public static AkkaConfigurationBuilder WithAzurePersistence(this AkkaConfigurationBuilder builder, - string connectionString, bool autoInitialize = true, string containerName = DefaultBlobContainerName, - string tableName = DefaultTableName, Action configurator = null) + /// + /// The builder instance being configured. + /// + /// + /// The connection string for connecting to Windows Azure table storage. + /// + /// + /// Automatically create the Table Storage table and Storage blob if no existing table is found + /// + /// + /// The table of the container we'll be using to serialize these blobs. + /// + /// + /// The Azure table we'll be connecting to. + /// + /// + /// A delegate that can be used to configure an instance + /// to set up event adapters. + /// + /// + /// The same instance originally passed in. + /// + public static AkkaConfigurationBuilder WithAzurePersistence( + this AkkaConfigurationBuilder builder, + string connectionString, + bool autoInitialize = true, + string containerName = DefaultBlobContainerName, + string tableName = DefaultTableName, + Action eventAdapterConfigurator = null) { - builder.WithAzureTableJournal(connectionString, autoInitialize, tableName, configurator); + builder.WithAzureTableJournal(connectionString, autoInitialize, tableName, eventAdapterConfigurator); builder.WithAzureBlobsSnapshotStore(connectionString, autoInitialize, containerName); return builder; } + + /// + /// Adds both AzureTableStorage journal and AzureBlobStorage snapshot-store as the default Akka.Persistence + /// implementations for a given . + /// + /// + /// The builder instance being configured. + /// + /// + /// A referencing the Azure Storage blob service. + /// This is likely to be similar to "https://{account_name}.blob.core.windows.net". + /// + /// + /// A referencing the Azure Storage Table service. + /// This is likely to be similar to "https://{account_name}.table.core.windows.net". + /// + /// + /// The used to sign API requests. + /// + /// + /// Optional client options that define the transport pipeline policies for authentication, + /// retries, etc., that are applied to every request. + /// + /// + /// Optional client options that define the transport pipeline policies for authentication, + /// retries, etc., that are applied to every request. + /// + /// + /// Automatically create the Table Storage table and Storage blob if no existing table is found + /// + /// + /// The table of the container we'll be using to serialize these blobs. + /// + /// + /// The Azure table we'll be connecting to. + /// + /// + /// A delegate that can be used to configure an instance + /// to set up event adapters. + /// + /// + /// The same instance originally passed in. + /// + public static AkkaConfigurationBuilder WithAzurePersistence( + this AkkaConfigurationBuilder builder, + Uri blobStorageServiceUri, + Uri tableStorageServiceUri, + DefaultAzureCredential defaultAzureCredential, + BlobClientOptions blobClientOptions = null, + TableClientOptions tableClientOptions = null, + bool autoInitialize = true, + string containerName = DefaultBlobContainerName, + string tableName = DefaultTableName, + Action eventAdapterConfigurator = null) + { + builder.WithAzureTableJournal(tableStorageServiceUri, defaultAzureCredential, tableClientOptions, autoInitialize, tableName, eventAdapterConfigurator); + builder.WithAzureBlobsSnapshotStore(blobStorageServiceUri, defaultAzureCredential, blobClientOptions, autoInitialize, containerName); + + return builder; + } } } diff --git a/src/Akka.Persistence.Azure.Tests/Hosting/AzurePersistenceHostingSanityCheck.cs b/src/Akka.Persistence.Azure.Tests/Hosting/AzurePersistenceHostingSanityCheck.cs index 7ed2e8e8..3c455d6b 100644 --- a/src/Akka.Persistence.Azure.Tests/Hosting/AzurePersistenceHostingSanityCheck.cs +++ b/src/Akka.Persistence.Azure.Tests/Hosting/AzurePersistenceHostingSanityCheck.cs @@ -5,6 +5,7 @@ using Akka.Event; using Akka.Hosting; using Akka.Persistence.Azure.Hosting; +using Akka.Persistence.Azure.Tests.Helper; using Akka.TestKit.Xunit2.Internals; using FluentAssertions; using Microsoft.Extensions.DependencyInjection; @@ -20,6 +21,7 @@ public class AzurePersistenceHostingSanityCheck public static async Task StartHost(Action testSetup) { var conn = Environment.GetEnvironmentVariable("AZURE_CONNECTION_STR") ?? "UseDevelopmentStorage=true"; + await DbUtils.CleanupCloudTable(conn); var host = new HostBuilder() .ConfigureServices(collection => { diff --git a/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSettings.cs b/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSettings.cs index 20c67dd2..4af08ef2 100644 --- a/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSettings.cs +++ b/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSettings.cs @@ -116,19 +116,19 @@ public AzureTableStorageJournalSettings( public bool AutoInitialize { get; } /// - /// A referencing the blob service. - /// This is likely to be similar to "https://{account_name}.table.core.windows.net". + /// A referencing the Azure Table Storage service. + /// This is likely to be similar to "https://{account_name}.table.core.windows.net". /// public Uri ServiceUri { get; } /// - /// The used to sign API requests. + /// The used to sign API requests. /// public DefaultAzureCredential DefaultAzureCredential { get; } /// - /// Optional client options that define the transport pipeline policies for authentication, - /// retries, etc., that are applied to every request. + /// Optional client options that define the transport pipeline policies for authentication, + /// retries, etc., that are applied to every request. /// public TableClientOptions TableClientOptions { get; } diff --git a/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSetup.cs b/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSetup.cs index 760f4ff9..2f85881b 100644 --- a/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSetup.cs +++ b/src/Akka.Persistence.Azure/Journal/AzureTableStorageJournalSetup.cs @@ -11,7 +11,7 @@ namespace Akka.Persistence.Azure.Journal { - public class AzureTableStorageJournalSetup : Setup + public sealed class AzureTableStorageJournalSetup : Setup { /// /// The connection string for connecting to Windows Azure table storage. @@ -51,19 +51,19 @@ public class AzureTableStorageJournalSetup : Setup public bool? AutoInitialize { get; set; } /// - /// A referencing the blob service. - /// This is likely to be similar to "https://{account_name}.table.core.windows.net". + /// A referencing the Azure Storage Table service. + /// This is likely to be similar to "https://{account_name}.table.core.windows.net". /// public Uri ServiceUri { get; set; } /// - /// The used to sign API requests. + /// The used to sign API requests. /// public DefaultAzureCredential DefaultAzureCredential { get; set; } /// - /// Optional client options that define the transport pipeline policies for authentication, - /// retries, etc., that are applied to every request. + /// Optional client options that define the transport pipeline policies for authentication, + /// retries, etc., that are applied to every request. /// public TableClientOptions TableClientOptions { get; set; } diff --git a/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournalSetup.cs b/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournalSetup.cs index 8096d975..2ab550e0 100644 --- a/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournalSetup.cs +++ b/src/Akka.Persistence.Azure/Query/AzureTableStorageReadJournalSetup.cs @@ -9,7 +9,7 @@ namespace Akka.Persistence.Azure.Query { - public class AzureTableStorageReadJournalSetup: Setup + public sealed class AzureTableStorageReadJournalSetup: Setup { /// /// How many events to fetch in one query (replay) and keep buffered until they diff --git a/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotSetup.cs b/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotSetup.cs index f9f66acf..d9d18b3a 100644 --- a/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotSetup.cs +++ b/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotSetup.cs @@ -13,24 +13,24 @@ namespace Akka.Persistence.Azure.Snapshot { /// - /// Setup class for . - /// Any populated properties will override its respective HOCON setting. + /// Setup class for . + /// Any populated properties will override its respective HOCON setting. /// - public class AzureBlobSnapshotSetup : Setup + public sealed class AzureBlobSnapshotSetup : Setup { /// - /// Create a new + /// Create a new /// /// - /// A referencing the blob service. - /// This is likely to be similar to "https://{account_name}.blob.core.windows.net". + /// A referencing the blob service. + /// This is likely to be similar to "https://{account_name}.blob.core.windows.net". /// /// - /// The used to sign requests. + /// The used to sign requests. /// /// - /// Optional client options that define the transport pipeline policies for authentication, - /// retries, etc., that are applied to every request. + /// Optional client options that define the transport pipeline policies for authentication, + /// retries, etc., that are applied to every request. /// /// A new instance public static AzureBlobSnapshotSetup Create( @@ -87,19 +87,19 @@ public static AzureBlobSnapshotSetup Create( public PublicAccessType? ContainerPublicAccessType { get; set; } /// - /// A referencing the blob service. - /// This is likely to be similar to "https://{account_name}.blob.core.windows.net". + /// A referencing the blob service. + /// This is likely to be similar to "https://{account_name}.blob.core.windows.net". /// public Uri ServiceUri { get; set; } /// - /// The used to sign API requests. + /// The used to sign API requests. /// public DefaultAzureCredential DefaultAzureCredential { get; set; } /// - /// Optional client options that define the transport pipeline policies for authentication, - /// retries, etc., that are applied to every request. + /// Optional client options that define the transport pipeline policies for authentication, + /// retries, etc., that are applied to every request. /// public BlobClientOptions BlobClientOptions { get; set; } diff --git a/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStoreSettings.cs b/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStoreSettings.cs index 50c0fcd6..11d1c5fc 100644 --- a/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStoreSettings.cs +++ b/src/Akka.Persistence.Azure/Snapshot/AzureBlobSnapshotStoreSettings.cs @@ -129,19 +129,19 @@ public AzureBlobSnapshotStoreSettings( public PublicAccessType ContainerPublicAccessType { get; } /// - /// A referencing the blob service. - /// This is likely to be similar to "https://{account_name}.blob.core.windows.net". + /// A referencing the blob service. + /// This is likely to be similar to "https://{account_name}.blob.core.windows.net". /// public Uri ServiceUri { get; } /// - /// The used to sign API requests. + /// The used to sign API requests. /// public DefaultAzureCredential DefaultAzureCredential { get; } /// - /// Optional client options that define the transport pipeline policies for authentication, - /// retries, etc., that are applied to every request. + /// Optional client options that define the transport pipeline policies for authentication, + /// retries, etc., that are applied to every request. /// public BlobClientOptions BlobClientOptions { get; } From b96d8a97ddd47a53674a2dc0f5d4f8fb9972f0cb Mon Sep 17 00:00:00 2001 From: Gregorius Soedharmo Date: Mon, 29 Aug 2022 22:40:02 +0700 Subject: [PATCH 11/11] Update RELEASE_NOTES.md for v0.9.1 release (#239) --- RELEASE_NOTES.md | 74 +++++++++++++++++++ .../AzurePersistenceExtensions.cs | 2 +- 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 8a5428ba..c12814bd 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,77 @@ +#### 0.9.1 August 29 2022 #### + +* [Bump Akka.NET version from 1.4.39 to 1.4.40](https://github.com/akkadotnet/akka.net/releases/tag/1.4.40) +* [Bump Akka.Persistence.Hosting version from 0.4.1 to 0.4.2](https://github.com/petabridge/Akka.Persistence.Azure/pull/233) +* [Bump Azure.Storage.Blobs version from 12.12.0 to 12.13.1](https://github.com/petabridge/Akka.Persistence.Azure/pull/234) +* [Bump Azure.Identity version from 1.6.0 to 1.6.1](https://github.com/petabridge/Akka.Persistence.Azure/pull/231) +* [Added programmatic Setup classes](https://github.com/petabridge/Akka.Persistence.Azure/pull/235) +* [Update Akka.Hosting support to support `DefaultAzureCredential`](https://github.com/petabridge/Akka.Persistence.Azure/pull/237) + +New Setup classes are added to allow programmatic setup of the journal table and snapshot-store blog storage; these setup classes supports `DefaultAzureCredential`. Note that to use `DefaultAzureCredential` from the `Azure.Identity` package, you need to provide both service URI and credential. + +```csharp +var host = new HostBuilder() + .ConfigureServices(collection => + { + collection.AddAkka("MyActorSys", builder => + { + var credentials = new DefaultAzureCredential(); + + // Programatically setup the journal table + builder.WithAzureTableJournal(setup => { + setup.TableName = "myazuretable"; + setup.ServiceUri = new Uri("https://{account_name}.table.core.windows.net"); + setup.DefaultAzureCredential = credentials; + // Optional TableClientOptions + setup.TableClientOptions = new TableClientOptions(); + }); + + // Programatically setup the snapshot-store blob container + builder.WithAzureBlobsSnapshotStore(setup => { + setup.ContainerName = "myAzureBlobContainer"; + setup.ServiceUri = new Uri("https://{account_name}.blob.core.windows.net"); + setup.DefaultAzureCredential = credentials; + // Optional BlobClientOptions + setup.BlobClientOptions = new BlobClientOptions(); + }); + + builder.StartActors((system, registry) => + { + var myActor = system.ActorOf(Props.Create(() => new MyPersistenceActor("ac1")), "actor1"); + registry.Register(myActor); + }); + }); + }).Build(); +``` + +A few convenience `Akka.Hosting` extension methods are also added as a shortcut: +```csharp +var host = new HostBuilder() + .ConfigureServices(collection => + { + collection.AddAkka("MyActorSys", builder => + { + var credentials = new DefaultAzureCredential(); + + // Add the journal table + builder.WithAzureTableJournal( + serviceUri: new Uri("https://{account_name}.table.core.windows.net"), + defaultAzureCredential: credentials); + + // Add the snapshot-store blob container + builder.WithAzureBlobsSnapshotStore( + serviceUri: new Uri("https://{account_name}.blob.core.windows.net"), + defaultAzureCredential: credentials); + + builder.StartActors((system, registry) => + { + var myActor = system.ActorOf(Props.Create(() => new MyPersistenceActor("ac1")), "actor1"); + registry.Register(myActor); + }); + }); + }).Build(); +``` + #### 0.9.0 July 21 2022 #### Added [Akka.Hosting](https://github.com/akkadotnet/Akka.Hosting) support to Akka.Persistence.Azure, which you can activate via the following: diff --git a/src/Akka.Persistence.Azure.Hosting/AzurePersistenceExtensions.cs b/src/Akka.Persistence.Azure.Hosting/AzurePersistenceExtensions.cs index 821459eb..c796ecc8 100644 --- a/src/Akka.Persistence.Azure.Hosting/AzurePersistenceExtensions.cs +++ b/src/Akka.Persistence.Azure.Hosting/AzurePersistenceExtensions.cs @@ -223,7 +223,7 @@ public static AkkaConfigurationBuilder WithAzureBlobsSnapshotStore( this AkkaConfigurationBuilder builder, Uri serviceUri, DefaultAzureCredential defaultAzureCredential, - BlobClientOptions blobClientOptions, + BlobClientOptions blobClientOptions = null, bool autoInitialize = true, string containerName = DefaultBlobContainerName) {