Skip to content

Releases: akkadotnet/Akka.Hosting

1.5.0-beta4

01 Mar 02:30
103f5da
Compare
Choose a tag to compare
1.5.0-beta4 Pre-release
Pre-release

Version 1.5.0-beta4 integrates Akka.NET v1.5 into Akka.Hosting
Update Akka.NET to 1.5.0-beta4

Upgrading From v1.4 To v1.5

As noted in the upgrade advisories%2C there was a major change in Akka.Cluster.Sharding state storage. These notes contains the same documentation%2C but tailored for Akka.Hosting users
The recommended settings for maximum ease-of-use for Akka.Cluster.Sharding in new applications going forward will be:

var options = new ShardOptions
{
    StateStoreMode = StateStoreMode.DData%2C
    RememberEntitiesStore = RememberEntitiesStore.Eventsourced
}

You will need to set these options manually because the default settings are set for backward compatibility.

Migrating to New Sharding Storage From Akka.Persistence

NOTE

This section applies only to users who were using StateStoreMode = StateStoreMode.Persistence.
Switching over to using RememberEntitiesStore = RememberEntitiesStore.Eventsourced will cause an initial migration of data from the ShardCoordinator's journal into separate event journals going forward.
Upgrading to Akka.NET v1.5 will *cause an irreversible migration of Akka.Cluster.Sharding data• for users who were previously running StateStoreMode = StateStoreMode.Persistence%2C so follow the steps below carefully:

Step 1 • Upgrade to Akka.NET v1.5 With New Options Setup

Update your Akka.Cluster.Sharding options to look like the following (adjust as necessary for your custom settings):

hostBuilder.Services.AddAkka("MyActorSystem"%2C builder =>
{
    var shardOptions = new ShardOptions
    {
        // If you don't run Akka.Cluster.Sharding with RememberEntities = true%2C
        // then set this to false
        RememberEntities = true%2C
        RememberEntitiesStore = RememberEntitiesStore.Eventsourced%2C
        StateStoreMode = StateStoreMode.Persistence%2C
        //fail if upgrade doesn't succeed
        FailOnInvalidEntityStateTransition = true
    }
    // Modify these two options to suit your application%2C SqlServer used
    // only as an illustration
    var journalOptions = new SqlServerJournalOptions()%3B
    var snapshotOptions = new SqlServerSnapshotOptions()%3B
    builder
        .WithClustering()
        .WithSqlServerPersistence(journalOptions%2C snapshotOptions)
        .WithShardRegion<UserActionsEntity>(
            "userActions"%2C 
            s => UserActionsEntity.Props(s)%2C
            new UserMessageExtractor()%2C
            // shardOptions is being used here
            shardOptions)%3B
    // Add the Akka.Cluster.Sharding migration journal event adapter
    builder.WithClusterShardingJournalMigrationAdapter(journalOptions)%3B
    // you can also declare the adapter by referencing the journal ID directly
    builder.WithClusterShardingJournalMigrationAdapter("akka.persistence.journal.sql-server")%3B
})
```

With these HOCON settings in-place the following will happen:
1. The old PersitentShardCoordinator state will be broken up • Remember entities data will be distributed to each of the PersistentShard actors%2C who will now use the new RememberEntitiesStore = RememberEntitiesStore.Eventsourced setting going forward%3B
2. Old Akka.Cluster.Sharding.ShardCoordinator.IDomainEvent events will be upgraded to a new storage format via the injected Akka.Persistence event adapter%3B and
3. The PersistentShardCoordinator will migrate its journal to the new format as well.

##### Step 2 • Migrating Away From Persistence to DData

Once your cluster has successfully booted up with these settings%2C you can now optionally move to using distributed data to store sharding state by changing StateStoreMode = StateStoreMode.DData and deploying a second time:

```csharp
hostBuilder.Services.AddAkka("MyActorSystem"%2C builder =>
{
    var shardOptions = new ShardOptions
    {
        RememberEntities = true%2C
        RememberEntitiesStore = RememberEntitiesStore.Eventsourced%2C
        // Change this line of code
        StateStoreMode = StateStoreMode.DData%2C
        FailOnInvalidEntityStateTransition = true
    }%3B
    var journalOptions = new SqlServerJournalOptions()%3B
    var snapshotOptions = new SqlServerSnapshotOptions()%3B
    builder
        .WithClustering()
        .WithSqlServerPersistence(journalOptions%2C snapshotOptions)
        .WithShardRegion<UserActionsEntity>(
            "userActions"%2C 
            s => UserActionsEntity.Props(s)%2C
            new UserMessageExtractor()%2C
            shardOptions)%3B
    builder.WithClusterShardingJournalMigrationAdapter(journalOptions)%3B
})```

Now you'll be running Akka.Cluster.Sharding with the recommended settings.
#### Migrating to New Sharding Storage From Akka.DistributedData
The migration process onto Akka.NET v1.5's new Cluster.Sharding storage system is less involved for users who were already using StateStoreMode = StateStoreMode.DData. All these users need to do is change the RememberEntitiesStore option to RememberEntitiesStore.Eventsourced
csharp
hostBuilder.Services.AddAkka("MyActorSystem"%2C builder =>
{
    var shardOptions = new ShardOptions
    {
        RememberEntities = true%2C
        // Use this option setting
        RememberEntitiesStore = RememberEntitiesStore.Eventsourced%2C
        StateStoreMode = StateStoreMode.DData%2C
        FailOnInvalidEntityStateTransition = true
    }%3B
    var journalOptions = new SqlServerJournalOptions()%3B
    var snapshotOptions = new SqlServerSnapshotOptions()%3B
    builder
        .WithClustering()
        .WithSqlServerPersistence(journalOptions%2C snapshotOptions)
        .WithShardRegion<UserActionsEntity>(
            "userActions"%2C 
            s => UserActionsEntity.Props(s)%2C
            new UserMessageExtractor()%2C
            shardOptions)%3B
    builder.WithClusterShardingJournalMigrationAdapter(journalOptions)%3B
})

1.5.0-beta3

28 Feb 01:52
2add0aa
Compare
Choose a tag to compare
1.5.0-beta3 Pre-release
Pre-release

Version 1.5.0-beta3 integrates Akka.NET v1.5 into Akka.Hosting
Update Akka.NET to 1.5.0-beta3

Upgrading From v1.4 To v1.5

As noted in the upgrade advisories%2C there was a major change in Akka.Cluster.Sharding state storage. These notes contains the same documentation%2C but tailored for Akka.Hosting users
The recommended settings for maximum ease-of-use for Akka.Cluster.Sharding in new applications going forward will be:
csharp
var options = new ShardOptions
{
StateStoreMode = StateStoreMode.DData%2C
RememberEntitiesStore = RememberEntitiesStore.Eventsourced
}%3B

You will need to set these options manually because the default settings are set for backward compatibility.

Migrating to New Sharding Storage From Akka.Persistence

NOTE

This section applies only to users who were using StateStoreMode = StateStoreMode.Persistence.
Switching over to using RememberEntitiesStore = RememberEntitiesStore.Eventsourced will cause an initial migration of data from the ShardCoordinator's journal into separate event journals going forward.
Upgrading to Akka.NET v1.5 will *cause an irreversible migration of Akka.Cluster.Sharding data• for users who were previously running StateStoreMode = StateStoreMode.Persistence%2C so follow the steps below carefully:

Step 1 • Upgrade to Akka.NET v1.5 With New Options Setup

Update your Akka.Cluster.Sharding options to look like the following (adjust as necessary for your custom settings):
csharp
hostBuilder.Services.AddAkka("MyActorSystem"%2C builder =>
{
var shardOptions = new ShardOptions
{
// If you don't run Akka.Cluster.Sharding with RememberEntities = true%2C
// then set this to false
RememberEntities = true%2C
RememberEntitiesStore = RememberEntitiesStore.Eventsourced%2C
StateStoreMode = StateStoreMode.Persistence%2C
//fail if upgrade doesn't succeed
FailOnInvalidEntityStateTransition = true
}%3B
// Modify these two options to suit your application%2C SqlServer used
// only as an illustration
var journalOptions = new SqlServerJournalOptions()%3B
var snapshotOptions = new SqlServerSnapshotOptions()%3B
builder
.WithClustering()
.WithSqlServerPersistence(journalOptions%2C snapshotOptions)
.WithShardRegion(
"userActions"%2C
s => UserActionsEntity.Props(s)%2C
new UserMessageExtractor()%2C
// shardOptions is being used here
shardOptions)%3B
// Add the Akka.Cluster.Sharding migration journal event adapter
builder.WithClusterShardingJournalMigrationAdapter(journalOptions)%3B
// you can also declare the adapter by referencing the journal ID directly
builder.WithClusterShardingJournalMigrationAdapter("akka.persistence.journal.sql-server")%3B
})

With these HOCON settings in-place the following will happen:

  1. The old PersitentShardCoordinator state will be broken up • Remember entities data will be distributed to each of the PersistentShard actors%2C who will now use the new RememberEntitiesStore = RememberEntitiesStore.Eventsourced setting going forward%3B
  2. Old Akka.Cluster.Sharding.ShardCoordinator.IDomainEvent events will be upgraded to a new storage format via the injected Akka.Persistence event adapter%3B and
  3. The PersistentShardCoordinator will migrate its journal to the new format as well.
Step 2 • Migrating Away From Persistence to DData

Once your cluster has successfully booted up with these settings%2C you can now optionally move to using distributed data to store sharding state by changing StateStoreMode = StateStoreMode.DData and deploying a second time:
csharp
hostBuilder.Services.AddAkka("MyActorSystem"%2C builder =>
{
var shardOptions = new ShardOptions
{
RememberEntities = true%2C
RememberEntitiesStore = RememberEntitiesStore.Eventsourced%2C
// Change this line of code
StateStoreMode = StateStoreMode.DData%2C
FailOnInvalidEntityStateTransition = true
}%3B
var journalOptions = new SqlServerJournalOptions()%3B
var snapshotOptions = new SqlServerSnapshotOptions()%3B
builder
.WithClustering()
.WithSqlServerPersistence(journalOptions%2C snapshotOptions)
.WithShardRegion(
"userActions"%2C
s => UserActionsEntity.Props(s)%2C
new UserMessageExtractor()%2C
shardOptions)%3B
builder.WithClusterShardingJournalMigrationAdapter(journalOptions)%3B
})

Now you'll be running Akka.Cluster.Sharding with the recommended settings.

Migrating to New Sharding Storage From Akka.DistributedData

The migration process onto Akka.NET v1.5's new Cluster.Sharding storage system is less involved for users who were already using StateStoreMode = StateStoreMode.DData. All these users need to do is change the RememberEntitiesStore option to RememberEntitiesStore.Eventsourced
csharp
hostBuilder.Services.AddAkka("MyActorSystem"%2C builder =>
{
var shardOptions = new ShardOptions
{
RememberEntities = true%2C
// Use this option setting
RememberEntitiesStore = RememberEntitiesStore.Eventsourced%2C
StateStoreMode = StateStoreMode.DData%2C
FailOnInvalidEntityStateTransition = true
}%3B
var journalOptions = new SqlServerJournalOptions()%3B
var snapshotOptions = new SqlServerSnapshotOptions()%3B
builder
.WithClustering()
.WithSqlServerPersistence(journalOptions%2C snapshotOptions)
.WithShardRegion(
"userActions"%2C
s => UserActionsEntity.Props(s)%2C
new UserMessageExtractor()%2C
shardOptions)%3B
builder.WithClusterShardingJournalMigrationAdapter(journalOptions)%3B
})

Akka.Hosting v1.5.0-alpha4

17 Feb 19:42
a354d4e
Compare
Choose a tag to compare
Pre-release

[1.5.0-alpha4] / 17 February 2023

Version 1.5.0-alpha4 integrates Akka.NET v1.5 into Akka.Hosting

Upgrading From v1.4 To v1.5

As noted in the upgrade advisories, there was a major change in Akka.Cluster.Sharding state storage. These notes contains the same documentation, but tailored for Akka.Hosting users

The recommended settings for maximum ease-of-use for Akka.Cluster.Sharding in new applications going forward will be:

var options = new ShardOptions
{
    StateStoreMode = StateStoreMode.DData,
    RememberEntitiesStore = RememberEntitiesStore.Eventsourced
};

You will need to set these options manually because the default settings are set for backward compatibility.

Migrating to New Sharding Storage From Akka.Persistence

NOTE

This section applies only to users who were using StateStoreMode = StateStoreMode.Persistence.

Switching over to using RememberEntitiesStore = RememberEntitiesStore.Eventsourced will cause an initial migration of data from the ShardCoordinator's journal into separate event journals going forward.

Upgrading to Akka.NET v1.5 will cause an irreversible migration of Akka.Cluster.Sharding data for users who were previously running StateStoreMode = StateStoreMode.Persistence, so follow the steps below carefully:

Step 1 - Upgrade to Akka.NET v1.5 With New Options Setup

Update your Akka.Cluster.Sharding options to look like the following (adjust as necessary for your custom settings):

hostBuilder.Services.AddAkka("MyActorSystem", builder =>
{
    var shardOptions = new ShardOptions
    {
        // If you don't run Akka.Cluster.Sharding with `RememberEntities = true`,
        // then set this to false
        RememberEntities = true,
        RememberEntitiesStore = RememberEntitiesStore.Eventsourced,
        StateStoreMode = StateStoreMode.Persistence,
    
        //fail if upgrade doesn't succeed
        FailOnInvalidEntityStateTransition = true
    };

    // Modify these two options to suit your application, SqlServer used
    // only as an illustration
    var journalOptions = new SqlServerJournalOptions();
    var snapshotOptions = new SqlServerSnapshotOptions();

    builder
        .WithClustering()
        .WithSqlServerPersistence(journalOptions, snapshotOptions)
        .WithShardRegion<UserActionsEntity>(
            "userActions", 
            s => UserActionsEntity.Props(s),
            new UserMessageExtractor(),
            // shardOptions is being used here
            shardOptions);
    
    // Add the Akka.Cluster.Sharding migration journal event adapter
    builder.WithClusterShardingJournalMigrationAdapter(journalOptions);
    
    // you can also declare the adapter by referencing the journal ID directly
    builder.WithClusterShardingJournalMigrationAdapter("akka.persistence.journal.sql-server");
})

With these HOCON settings in-place the following will happen:

  1. The old PersitentShardCoordinator state will be broken up - Remember entities data will be distributed to each of the PersistentShard actors, who will now use the new RememberEntitiesStore = RememberEntitiesStore.Eventsourced setting going forward;
  2. Old Akka.Cluster.Sharding.ShardCoordinator.IDomainEvent events will be upgraded to a new storage format via the injected Akka.Persistence event adapter; and
  3. The PersistentShardCoordinator will migrate its journal to the new format as well.
Step 2 - Migrating Away From Persistence to DData

Once your cluster has successfully booted up with these settings, you can now optionally move to using distributed data to store sharding state by changing StateStoreMode = StateStoreMode.DData and deploying a second time:

hostBuilder.Services.AddAkka("MyActorSystem", builder =>
{
    var shardOptions = new ShardOptions
    {
        RememberEntities = true,
        RememberEntitiesStore = RememberEntitiesStore.Eventsourced,
        // Change this line of code
        StateStoreMode = StateStoreMode.DData,
    
        FailOnInvalidEntityStateTransition = true
    };

    var journalOptions = new SqlServerJournalOptions();
    var snapshotOptions = new SqlServerSnapshotOptions();

    builder
        .WithClustering()
        .WithSqlServerPersistence(journalOptions, snapshotOptions)
        .WithShardRegion<UserActionsEntity>(
            "userActions", 
            s => UserActionsEntity.Props(s),
            new UserMessageExtractor(),
            shardOptions);
    
    builder.WithClusterShardingJournalMigrationAdapter(journalOptions);
})

Now you'll be running Akka.Cluster.Sharding with the recommended settings.

Migrating to New Sharding Storage From Akka.DistributedData

The migration process onto Akka.NET v1.5's new Cluster.Sharding storage system is less involved for users who were already using StateStoreMode = StateStoreMode.DData. All these users need to do is change the RememberEntitiesStore option to RememberEntitiesStore.Eventsourced

hostBuilder.Services.AddAkka("MyActorSystem", builder =>
{
    var shardOptions = new ShardOptions
    {
        RememberEntities = true,
        // Use this option setting
        RememberEntitiesStore = RememberEntitiesStore.Eventsourced,
        StateStoreMode = StateStoreMode.DData,
    
        FailOnInvalidEntityStateTransition = true
    };

    var journalOptions = new SqlServerJournalOptions();
    var snapshotOptions = new SqlServerSnapshotOptions();

    builder
        .WithClustering()
        .WithSqlServerPersistence(journalOptions, snapshotOptions)
        .WithShardRegion<UserActionsEntity>(
            "userActions", 
            s => UserActionsEntity.Props(s),
            new UserMessageExtractor(),
            shardOptions);
    
    builder.WithClusterShardingJournalMigrationAdapter(journalOptions);
})

1.0.3

08 Feb 16:03
57d534d
Compare
Choose a tag to compare

1.0.2

31 Jan 23:15
a140512
Compare
Choose a tag to compare

Version 1.0.2 introduces a new method to the ActorRegistry.GetAsync in order to allow users to force parts of their application to wait until a specific IActorRef has been started and added to the ActorRegistry.

// arrange
var registry = new ActorRegistry();

// act
var task = registry.GetAsync<Nobody>();
task.IsCompletedSuccessfully.Should().BeFalse();

registry.Register<Nobody>(Nobody.Instance);
var result = await task;

// assert
result.Should().Be(Nobody.Instance);

This method is designed to allow users to wait via async Task<IActorRef> for an actor to be registered in the event that a specific IRequiredActor<TKey> is needed before Akka.Hosting can start the ActorSystem inside its IHostedService.

Akka.Hosting 1.0.1

06 Jan 19:16
5d45e12
Compare
Choose a tag to compare

Akka.Hosting v1.0.0

28 Dec 00:22
906da90
Compare
Choose a tag to compare

[1.0.0] / 27 December 2022

This 1.0.0 release is the RTM release for Akka.Hosting and contains major API breaking changes with a lot of its API. All current API will be frozen for all future releases and will be backed with our backward compatibility promise.

Change List

General Changes

  • Almost all options properties are changed to value types to allow direct binding to Miscosoft.Extensions.Configuration IConfiguration instance.
  • Implements Nullable on all projects.

Changes To Akka.Hosting

  • The HoconAddMode argument in AddHocon() and AddHoconFile() extension methods are not optional anymore; you will need to declare that your HOCON will to append, prepend, or replace existing HOCON configuration. In almost all cases, unless you're adding a default configuration, you only need to use HoconAddMode.Prepend.

  • ActorRegistry.Get&lt;T&gt; will now throw an ActorRegistryException if no actor with key T has been registered with the ActorRegistry, this is done to make the API more consistent with all other .NET APIs. Use ActorRegistry.TryGet&lt;T&gt; if you do not want this behavior.

  • Better integration with Akka.DependencyInjection. Documentation can be read here

  • Added WithActorAskTimeout() extension method to configure the actor ask timeout settings.

  • Added extended debug logging support for dead letters and actor messages and events.

  • Adds a variation to AddHocon that can convert Microsoft.Extensions.Configuration IConfiguration into HOCON Config instance and adds it to the ActorSystem being configured.

    • All variable name are automatically converted to lower case.
    • All "." (period) in the IConfiguration key will be treated as a HOCON object key separator
    • For environment variable configuration provider:
      • "__" (double underline) will be converted to "." (period).
      • "_" (single underline) will be converted to "-" (dash).
      • If all keys are composed of integer parseable keys, the whole object is treated as an array

    Example:

    JSON configuration:

    {
       "akka.cluster": {
           "roles": [ "front-end", "back-end" ],
           "min-nr-of-members": 3,
           "log-info": true
       }
    }

    and environment variables:

    AKKA__CLUSTER__ROLES__0=front-end
    AKKA__CLUSTER__ROLES__1=back-end
    AKKA__CLUSTER__MIN_NR_OF_MEMBERS=3
    AKKA__CLUSTER__LOG_INFO=true

    is equivalent to HOCON configuration of:

    akka {
        cluster {
            roles: [ front-end, back-end ]
            min-nr-of-members: 3
            log-info: true
        }
    }

Changes to Akka.Persistence.Hosting

  • You can now use option classes to configure persistence. Currently, the persistence plugins that supports this are Akka.Persistence.PostgreSql.Hosting and Akka.Persistence.SqlServer.Hosting. Support for other Akka.Hosting enabled plugins will be rolled out after this release.
  • These option classes are modular:
    • Multiple options can be registered with the builder using different names
    • The same persistence plugin (e.g. PostgreSql) can be declared and registered multiple times using different names and configuration.
    • Options can be declared as the default persistence plugin and not.
    • Different or the same registered option can be used as the normal persistence options and Akka.Cluster.Hosting sharding extension methods.
    • There can only be one option declared as the default journal and one option declared as the default snapshot plugin. If multiple default plugin options are declared, only the last registered option will have an effect.
  • Journal event adapters can now be composed directly using the Adapters property inside the journal option class.
  • An example project can be seen here

Example code:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAkka("MyActorSystem", configurationBuilder =>
{
    // Grab connection strings from appsettings.json
    var localConn = builder.Configuration.GetConnectionString("sqlServerLocal");
    var shardingConn = builder.Configuration.GetConnectionString("sqlServerSharding");

    // Custom journal options with the id "sharding"
    // The absolute id will be "akka.persistence.journal.sharding"
    var shardingJournalOptions = new SqlServerJournalOptions(
        isDefaultPlugin: false)
    {
        Identifier = "sharding",
        ConnectionString = shardingConn,
        AutoInitialize = true
    };
    
    // Custom snapshots options with the id "sharding"
    // The absolute id will be "akka.persistence.snapshot-store.sharding"
    var shardingSnapshotOptions = new SqlServerSnapshotOptions(
        isDefaultPlugin: false)
    {
        Identifier = "sharding",
        ConnectionString = shardingConn,
        AutoInitialize = true
    };
    
    configurationBuilder
        // Standard way to create a default persistence 
        // journal and snapshot
        .WithSqlServerPersistence(localConn)
        // This is a custom persistence setup using the options 
        // instances we've set up earlier.
        // Note that we are calling WithSqlServerPersistence()
        // twice, these two calls registers two different
        // persistence options with two different identifier names.
        .WithSqlServerPersistence(shardingJournalOptions, shardingSnapshotOptions) 
        .WithShardRegion<UserActionsEntity>(
            "userActions", 
            s => UserActionsEntity.Props(s),
            new UserMessageExtractor(),
            new ShardOptions
            {
                StateStoreMode = StateStoreMode.Persistence, 
                Role = "myRole",
                // Supplying sharding with separate persistence plugin options
                JournalOptions = shardingJournalOptions,
                SnapshotOptions = shardingSnapshotOptions
                // NOTE: you can supply the plugin id instead
                // JournalPluginId = shardingJournalOptions.PluginId,
                // SnapshotPluginId = shardingSnapshotOptions.PluginId 
            });
})

Changes to Akka.Cluster.Hosting

  • ClusterOptions are expanded with more properties to make it more configurable. These new properties are:
    • MinimumNumberOfMembers: Allows you to set the minimum number of joined cluster members for a cluster to be considered to be in the Up state.
    • MinimumNumberOfMembersPerRole: Similar to ``MinimumNumberOfMembers`, but it is scoped to each cluster role.
    • AppVersion: Allows you to set the current cluster application version, useful for performing rolling update of the cluster members.
    • LogInfo: Enable info level logging of cluster events.
    • LogInfoVerbose: Enable a more verbose info level logging of cluster events, used for temporary troubleshooting.
    • SplitBrainResolver: The split brain resolver property is moved into the options class instead of being part of the extension method arguments.
  • ClusterSingletonOptions and ShardOptions now have a LeaseImplementation property that can be used to configure leasing for cluster singleton and sharding. Currently, two lease plugins are supported: Akka.Coordination.KubernetesApi and Akka.Coordination.Azure by assigning KubernetesLeaseOption.Instance or AzureLeaseOption.Instance respectively to the property.

0.5.2-beta1

28 Nov 19:43
4c04628
Compare
Choose a tag to compare

0.5.1

20 Oct 19:47
1030d84
Compare
Choose a tag to compare

0.5.0

04 Oct 18:11
d942b8e
Compare
Choose a tag to compare

Update Akka.NET from 1.4.41 to 1.4.43
Add full options support to Akka.Persistence.SqlServer.Hosting
Improved Akka.Remote.Hosting implementation
Add a standardized option code pattern for Akka.Hosting developer
Add Akka.Hosting.TestKit module for unit testing projects using Akka.Hosting

Full options support for Akka.Persistence.SqlServer.Hosting

You can now use an option class in Akka.Persistence.SqlServer.Hosting to replace HOCON configuration fully.

Add Akka.Hosting.TestKit module

The biggest difference between Akka.Hosting.TestKit and Akka.TestKit is that, since the test is started asynchronously, the TestKit properties and methods would not be available in the unit test class constructor anymore. Since the spec depends on Microsoft HostBuilder, configuration has to be broken down into steps. There are overridable methods that user can use to override virtually all of the setup process.

These are steps of what overridable methods gets called. Not all of the methods needs to be overriden, at the minimum, if you do not need a custom hosting environment, you need to override the ConfigureAkka method.

  1. ConfigureLogging(ILoggingBuilder)

    Add custom logger and filtering rules on the HostBuilder level.

  2. ConfigureHostConfiguration(IConfigurationBuilder)

    Inject any additional hosting environment configuration here, such as faking environment variables, in the HostBuilder level.

  3. ConfigureAppConfiguration(HostBuilderContext, IConfigurationBuilder)

    Inject the application configuration.

  4. ConfigureServices(HostBuilderContext, IServiceCollection)

    Add additional services needed by the test, such as mocked up services used inside the dependency injection.

  5. User defined HOCON configuration is injected by overriding the Config property, it is not passed as part of the constructor anymore.

  6. ConfigureAkka(AkkaConfigurationBuilder, IServiceProvider)

    This is called inside AddAkka, use this to configure the AkkaConfigurationBuilder

  7. BeforeTestStart()

    This method is called after the TestKit is initialized. Move all of the codes that used to belong in the constructor here.

Akka.Hosting.TestKit extends Akka.TestKit.TestKitBase directly, all testing methods are available out of the box.
All of the properties, such as Sys and TestActor will be available once the unit test class is invoked.

Add a standardized option code pattern for Akka.Hosting developer

This new feature is intended for Akka.Hosting module developer only, it is used to standardize how Akka.Hosting addresses a very common HOCON configuration pattern. This allows for a HOCON-less programmatic setup replacement for the HOCON path used to configure the HOCON property.

The pattern:

# This HOCON property references to a config block below
akka.discovery.method = akka.discovery.config

akka.discovery.config {
    class = "Akka.Discovery.Config.ConfigServiceDiscovery, Akka.Discovery"
    # other options goes here
}

Example implementation:

// The base class for the option, needs to implement the IHoconOption template interface
public abstract class DiscoveryOptionBase : IHoconOption
{ }

// The actual option implementation
public class ConfigOption : DiscoveryOptionBase
{
    // The path value in the akka.discovery.method property above
    public string ConfigPath => "akka.discovery.config";

    // The FQCN value in the akka.discovery.config.class property above
    public Type Class => typeof(ConfigServiceDiscovery);

    // Generate the same HOCON config as above
    public void Apply(AkkaConfigurationBuilder builder, Setup setup = null)
    {
        // Modifies Akka.NET configuration either via HOCON or setup class
        builder.AddHocon(
            $"akka.discovery.method = {ConfigPath.ToHocon()}",
            HoconAddMode.Prepend);
        builder.AddHocon($"akka.discovery.config.class = {
            Class.AssemblyQualifiedName.ToHocon()}",
            HoconAddMode.Prepend);

        // Rest of configuration goes here
    }
}

// Akka.Hosting extension implementation
public static AkkaConfigurationBuilder WithDiscovery(
    this AkkaConfigurationBuilder builder,
    DiscoveryOptionBase discOption)
{
    var setup = new DiscoverySetup();

    // gets called here
    discOption.Apply(builder, setup);
}