Skip to content

Commit

Permalink
Move Hosting project from Akka.Hosting repo to this repo (#308)
Browse files Browse the repository at this point in the history
* Move Hosting project from Akka.Hosting repo to this repo

* Bump build script .NET SDK to 7.x

* Add .NET 6 to build script

* Add README.md location in csproj file
  • Loading branch information
Arkatufus authored May 4, 2023
1 parent 2360e2d commit 76fea78
Show file tree
Hide file tree
Showing 49 changed files with 2,174 additions and 13 deletions.
24 changes: 24 additions & 0 deletions Akka.Persistence.SqlServer.sln
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Persistence.SqlServer.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.SqlServer.Performance.Tests", "src\Akka.Persistence.SqlServer.Performance.Tests\Akka.Persistence.SqlServer.Performance.Tests.csproj", "{5B792D05-2CCE-4513-BAAD-100394E9E161}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.SqlServer.Hosting", "src\Akka.Persistence.SqlServer.Hosting\Akka.Persistence.SqlServer.Hosting.csproj", "{8E47A245-3F92-421A-90CC-D49A6162486A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{E5A4FE07-0354-472F-9DF0-458F68FDE2DE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Hosting.CustomJournalIdDemo", "src\Examples\Akka.Hosting.CustomJournalIdDemo\Akka.Hosting.CustomJournalIdDemo.csproj", "{EE293645-8486-4D81-8387-DDD5F617FCE5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Hosting.SqlSharding", "src\Examples\Akka.Hosting.SqlSharding\Akka.Hosting.SqlSharding.csproj", "{06734F4B-5995-4A08-92CA-0177C0DFD512}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -44,11 +52,27 @@ Global
{5B792D05-2CCE-4513-BAAD-100394E9E161}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B792D05-2CCE-4513-BAAD-100394E9E161}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B792D05-2CCE-4513-BAAD-100394E9E161}.Release|Any CPU.Build.0 = Release|Any CPU
{8E47A245-3F92-421A-90CC-D49A6162486A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8E47A245-3F92-421A-90CC-D49A6162486A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8E47A245-3F92-421A-90CC-D49A6162486A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8E47A245-3F92-421A-90CC-D49A6162486A}.Release|Any CPU.Build.0 = Release|Any CPU
{EE293645-8486-4D81-8387-DDD5F617FCE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EE293645-8486-4D81-8387-DDD5F617FCE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EE293645-8486-4D81-8387-DDD5F617FCE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EE293645-8486-4D81-8387-DDD5F617FCE5}.Release|Any CPU.Build.0 = Release|Any CPU
{06734F4B-5995-4A08-92CA-0177C0DFD512}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{06734F4B-5995-4A08-92CA-0177C0DFD512}.Debug|Any CPU.Build.0 = Debug|Any CPU
{06734F4B-5995-4A08-92CA-0177C0DFD512}.Release|Any CPU.ActiveCfg = Release|Any CPU
{06734F4B-5995-4A08-92CA-0177C0DFD512}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F5B10DE4-8703-405E-B6ED-DDFE0D20198D}
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{EE293645-8486-4D81-8387-DDD5F617FCE5} = {E5A4FE07-0354-472F-9DF0-458F68FDE2DE}
{06734F4B-5995-4A08-92CA-0177C0DFD512} = {E5A4FE07-0354-472F-9DF0-458F68FDE2DE}
EndGlobalSection
EndGlobal
4 changes: 4 additions & 0 deletions build-system/azure-pipeline.template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ jobs:
submodules: recursive # set to 'true' for a single level of submodules or 'recursive' to get submodules of submodules
persistCredentials: true
# Linux or macOS
- task: UseDotNet@2
displayName: 'Use .NET 7'
inputs:
version: '7.x'
- task: UseDotNet@2
displayName: 'Use .NET 6'
inputs:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>$(NetStandardLibVersion)</TargetFramework>
<PackageReadmeFile>README.md</PackageReadmeFile>
<Description>Akka.Persistence.SqlServer Microsoft.Extensions.Hosting support.</Description>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Akka.Persistence.Query.Sql" />
<PackageReference Include="Akka.Persistence.Hosting" />
<PackageReference Include="Akka.Hosting" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Akka.Persistence.SqlServer\Akka.Persistence.SqlServer.csproj" />
</ItemGroup>

<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="\"/>
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
using System;
using Akka.Actor;
using Akka.Hosting;
using Akka.Persistence.Hosting;

#nullable enable
namespace Akka.Persistence.SqlServer.Hosting
{
/// <summary>
/// Extension methods for Akka.Persistence.SqlServer
/// </summary>
public static class AkkaPersistenceSqlServerHostingExtensions
{
/// <summary>
/// Adds Akka.Persistence.SqlServer support to this <see cref="ActorSystem"/>.
/// </summary>
/// <param name="builder">
/// The builder instance being configured.
/// </param>
/// <param name="connectionString">
/// Connection string used for database access.
/// </param>
/// <param name="autoInitialize">
/// <para>
/// Should the SQL store table be initialized automatically.
/// </para>
/// <i>Default</i>: <c>false</c>
/// </param>
/// <param name="mode">
/// <para>
/// Determines which settings should be added by this method call.
/// </para>
/// <i>Default</i>: <see cref="PersistenceMode.Both"/>
/// </param>
/// <param name="journalBuilder">
/// <para>
/// An <see cref="Action{T}"/> used to configure an <see cref="AkkaPersistenceJournalBuilder"/> instance.
/// </para>
/// <i>Default</i>: <c>null</c>
/// </param>
/// <param name="pluginIdentifier">
/// <para>
/// The configuration identifier for the plugins
/// </para>
/// <i>Default</i>: <c>"sql-server"</c>
/// </param>
/// <param name="isDefaultPlugin">
/// <para>
/// A <c>bool</c> flag to set the plugin as the default persistence plugin for the <see cref="ActorSystem"/>
/// </para>
/// <b>Default</b>: <c>true</c>
/// </param>
/// <returns>
/// The same <see cref="AkkaConfigurationBuilder"/> instance originally passed in.
/// </returns>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown when <see cref="journalBuilder"/> is set and <see cref="mode"/> is set to
/// <see cref="PersistenceMode.SnapshotStore"/>
/// </exception>
public static AkkaConfigurationBuilder WithSqlServerPersistence(
this AkkaConfigurationBuilder builder,
string connectionString,
PersistenceMode mode = PersistenceMode.Both,
Action<AkkaPersistenceJournalBuilder>? journalBuilder = null,
bool autoInitialize = true,
string pluginIdentifier = "sql-server",
bool isDefaultPlugin = true)
{
if (mode == PersistenceMode.SnapshotStore && journalBuilder is { })
throw new Exception($"{nameof(journalBuilder)} can only be set when {nameof(mode)} is set to either {PersistenceMode.Both} or {PersistenceMode.Journal}");

var journalOpt = new SqlServerJournalOptions(isDefaultPlugin, pluginIdentifier)
{
ConnectionString = connectionString,
AutoInitialize = autoInitialize,
QueryRefreshInterval = TimeSpan.FromSeconds(1),
};

var adapters = new AkkaPersistenceJournalBuilder(journalOpt.Identifier, builder);
journalBuilder?.Invoke(adapters);
journalOpt.Adapters = adapters;

var snapshotOpt = new SqlServerSnapshotOptions(isDefaultPlugin, pluginIdentifier)
{
ConnectionString = connectionString,
AutoInitialize = autoInitialize,
};

return mode switch
{
PersistenceMode.Journal => builder.WithSqlServerPersistence(journalOpt, null),
PersistenceMode.SnapshotStore => builder.WithSqlServerPersistence(null, snapshotOpt),
PersistenceMode.Both => builder.WithSqlServerPersistence(journalOpt, snapshotOpt),
_ => throw new ArgumentOutOfRangeException(nameof(mode), mode, "Invalid PersistenceMode defined.")
};
}

/// <summary>
/// Adds Akka.Persistence.SqlServer support to this <see cref="ActorSystem"/>. At least one of the
/// configurator delegate needs to be populated else this method will throw an exception.
/// </summary>
/// <param name="builder">
/// The builder instance being configured.
/// </param>
/// <param name="journalOptionConfigurator">
/// <para>
/// An <see cref="Action{T}"/> that modifies an instance of <see cref="SqlServerJournalOptions"/>,
/// used to configure the journal plugin
/// </para>
/// <i>Default</i>: <c>null</c>
/// </param>
/// <param name="snapshotOptionConfigurator">
/// <para>
/// An <see cref="Action{T}"/> that modifies an instance of <see cref="SqlServerSnapshotOptions"/>,
/// used to configure the snapshot store plugin
/// </para>
/// <i>Default</i>: <c>null</c>
/// </param>
/// <param name="isDefaultPlugin">
/// <para>
/// A <c>bool</c> flag to set the plugin as the default persistence plugin for the <see cref="ActorSystem"/>
/// </para>
/// <b>Default</b>: <c>true</c>
/// </param>
/// <returns>
/// The same <see cref="AkkaConfigurationBuilder"/> instance originally passed in.
/// </returns>
/// <exception cref="ArgumentException">
/// Thrown when both <paramref name="journalOptionConfigurator"/> and <paramref name="snapshotOptionConfigurator"/> are null.
/// </exception>
public static AkkaConfigurationBuilder WithSqlServerPersistence(
this AkkaConfigurationBuilder builder,
Action<SqlServerJournalOptions>? journalOptionConfigurator = null,
Action<SqlServerSnapshotOptions>? snapshotOptionConfigurator = null,
bool isDefaultPlugin = true)
{
if (journalOptionConfigurator is null && snapshotOptionConfigurator is null)
throw new ArgumentException($"{nameof(journalOptionConfigurator)} and {nameof(snapshotOptionConfigurator)} could not both be null");

SqlServerJournalOptions? journalOptions = null;
if (journalOptionConfigurator is { })
{
journalOptions = new SqlServerJournalOptions(isDefaultPlugin);
journalOptionConfigurator(journalOptions);
}

SqlServerSnapshotOptions? snapshotOptions = null;
if (snapshotOptionConfigurator is { })
{
snapshotOptions = new SqlServerSnapshotOptions(isDefaultPlugin);
snapshotOptionConfigurator(snapshotOptions);
}

return builder.WithSqlServerPersistence(journalOptions, snapshotOptions);
}

/// <summary>
/// Adds Akka.Persistence.SqlServer support to this <see cref="ActorSystem"/>. At least one of the options
/// have to be populated else this method will throw an exception.
/// </summary>
/// <param name="builder">
/// The builder instance being configured.
/// </param>
/// <param name="journalOptions">
/// <para>
/// An instance of <see cref="SqlServerJournalOptions"/>, used to configure the journal plugin
/// </para>
/// <i>Default</i>: <c>null</c>
/// </param>
/// <param name="snapshotOptions">
/// <para>
/// An instance of <see cref="SqlServerSnapshotOptions"/>, used to configure the snapshot store plugin
/// </para>
/// <i>Default</i>: <c>null</c>
/// </param>
/// <returns>
/// The same <see cref="AkkaConfigurationBuilder"/> instance originally passed in.
/// </returns>
/// <exception cref="ArgumentException">
/// Thrown when both <paramref name="journalOptions"/> and <paramref name="snapshotOptions"/> are null.
/// </exception>
public static AkkaConfigurationBuilder WithSqlServerPersistence(
this AkkaConfigurationBuilder builder,
SqlServerJournalOptions? journalOptions = null,
SqlServerSnapshotOptions? snapshotOptions = null)
{
if (journalOptions is null && snapshotOptions is null)
throw new ArgumentException($"{nameof(journalOptions)} and {nameof(snapshotOptions)} could not both be null");

return (journalOptions, snapshotOptions) switch
{
(null, null) =>
throw new ArgumentException($"{nameof(journalOptions)} and {nameof(snapshotOptions)} could not both be null"),

(_, null) =>
builder
.AddHocon(journalOptions.ToConfig(), HoconAddMode.Prepend)
.AddHocon(journalOptions.DefaultConfig, HoconAddMode.Append),

(null, _) =>
builder
.AddHocon(snapshotOptions.ToConfig(), HoconAddMode.Prepend)
.AddHocon(snapshotOptions.DefaultConfig, HoconAddMode.Append),

(_, _) =>
builder
.AddHocon(journalOptions.ToConfig(), HoconAddMode.Prepend)
.AddHocon(snapshotOptions.ToConfig(), HoconAddMode.Prepend)
.AddHocon(journalOptions.DefaultConfig, HoconAddMode.Append)
.AddHocon(snapshotOptions.DefaultConfig, HoconAddMode.Append),
};
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("Akka.Persistence.Hosting.Tests")]
84 changes: 84 additions & 0 deletions src/Akka.Persistence.SqlServer.Hosting/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Akka.Persistence.SqlServer.Hosting

Akka.Hosting extension methods to add Akka.Persistence.SqlServer to an ActorSystem

# Akka.Persistence.SqlServer Extension Methods

## WithSqlServerPersistence() Method

```csharp
public static AkkaConfigurationBuilder WithSqlServerPersistence(
this AkkaConfigurationBuilder builder,
string connectionString,
PersistenceMode mode = PersistenceMode.Both,
Action<AkkaPersistenceJournalBuilder>? configurator = null,
bool autoInitialize = true);
```

```csharp
public static AkkaConfigurationBuilder WithSqlServerPersistence(
this AkkaConfigurationBuilder builder,
Action<SqlServerJournalOptions>? journalConfigurator = null,
Action<SqlServerSnapshotOptions>? snapshotConfigurator = null,
Action<AkkaPersistenceJournalBuilder>? configurator = null);
```

```csharp
public static AkkaConfigurationBuilder WithSqlServerPersistence(
this AkkaConfigurationBuilder builder,
SqlServerJournalOptions? journalOptions = null,
SqlServerSnapshotOptions? snapshotOptions = null,
Action<AkkaPersistenceJournalBuilder>? configurator = null);
```

### Parameters

* `connectionString` __string__

Connection string used for database access.

* `mode` __PersistenceMode__

Determines which settings should be added by this method call.

* `PersistenceMode.Journal`: Only add the journal settings
* `PersistenceMode.SnapshotStore`: Only add the snapshot store settings
* `PersistenceMode.Both`: Add both journal and snapshot store settings

* `configurator` __Action\<AkkaPersistenceJournalBuilder\>__

An Action delegate used to configure an `AkkaPersistenceJournalBuilder` instance. Used to configure [Event Adapters](https://getakka.net/articles/persistence/event-adapters.html)

* `journalConfigurator` __Action\<SqlServerJournalOptions\>__

An Action delegate to configure a `SqlServerJournalOptions` instance.

* `snapshotConfigurator` __Action\<SqlServerSnapshotOptions\>__

An Action delegate to configure a `SqlServerSnapshotOptions` instance.

* `journalOptions` __SqlServerJournalOptions__

An `SqlServerJournalOptions` instance to configure the SqlServer journal.

* `snapshotOptions` __SqlServerSnapshotOptions__

An `SqlServerSnapshotOptions` instance to configure the SqlServer snapshot store.

## Example

```csharp
using var host = new HostBuilder()
.ConfigureServices((context, services) =>
{
services.AddAkka("ecsBootstrapDemo", (builder, provider) =>
{
builder
.WithRemoting("localhost", 8110)
.WithClustering()
.WithSqlServerPersistence("your-sqlserver-connection-string");
});
}).Build();

await host.RunAsync();
```
Loading

0 comments on commit 76fea78

Please sign in to comment.