Releases: akkadotnet/Akka.Hosting
Akka.Hosting 1.0.1
Version 1.0.1 fixes options bug used in the cluster sharding Akka.Hosting extension method.
Akka.Hosting v1.0.0
[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
- Update Akka.NET from 1.4.45 to 1.4.47
- The
HoconAddMode
argument inAddHocon()
andAddHoconFile()
extension methods are not optional anymore ActorRegistry.Get<T>
will throw if no actor with key T has been registered with theActorRegistry
- Modularize and make Hosting.Persistence methods use the options pattern
- Add lease support to singleton and sharding extensions
- Fix bug in
AddActor
andAddStartup
to make sure that they're executed in order - Add IConfiguration to HOCON adapter
- Make
JournalOptions
andSnapshotOptions
IConfigurable bindable - Make
RemoteOptions
IConfiguration bindable - Better integration with Akka.DependencyInjection
- Add
WithActorAskTimeout
and extends debug logging options - Updated NuGet package versions:
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 inAddHocon()
andAddHoconFile()
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 useHoconAddMode.Prepend
. -
ActorRegistry.Get<T>
will now throw anActorRegistryException
if no actor with key T has been registered with theActorRegistry
, this is done to make the API more consistent with all other .NET APIs. UseActorRegistry.TryGet<T>
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 convertMicrosoft.Extensions.Configuration
IConfiguration
into HOCONConfig
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
andAkka.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 theUp
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
andShardOptions
now have aLeaseImplementation
property that can be used to configure leasing for cluster singleton and sharding. Currently, two lease plugins are supported:Akka.Coordination.KubernetesApi
andAkka.Coordination.Azure
by assigningKubernetesLeaseOption.Instance
orAzureLeaseOption.Instance
respectively to the property.
0.5.2-beta1
0.5.1
0.5.0
• 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.
-
ConfigureLogging(ILoggingBuilder)
Add custom logger and filtering rules on the
HostBuilder
level. -
ConfigureHostConfiguration(IConfigurationBuilder)
Inject any additional hosting environment configuration here, such as faking environment variables, in the
HostBuilder
level. -
ConfigureAppConfiguration(HostBuilderContext, IConfigurationBuilder)
Inject the application configuration.
-
ConfigureServices(HostBuilderContext, IServiceCollection)
Add additional services needed by the test, such as mocked up services used inside the dependency injection.
-
User defined HOCON configuration is injected by overriding the
Config
property, it is not passed as part of the constructor anymore. -
ConfigureAkka(AkkaConfigurationBuilder, IServiceProvider)
This is called inside
AddAkka
, use this to configure theAkkaConfigurationBuilder
-
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);
}
0.4.3
0.4.2
0.4.1
• Fix Microsoft.Extensions.Logging.ILoggerFactory logging support
• Add InMemory snapshot store and journal persistence support
Due to a bad API design, we're rolling back the Microsoft.Extensions.Logging.ILoggerFactory
logger support introduced in version 0.4.0, the 0.4.0 NuGet version is now considered as deprecated in support of the new API design introduced in version 0.4.1.
Logger Configuration Support
You can now use the new AkkaConfigurationBuilder
extension method called ConfigureLoggers(Action<LoggerConfigBuilder>)
to configure how Akka.NET logger behave.
Example:
builder.Services.AddAkka("MyActorSystem", configurationBuilder =>
{
configurationBuilder
.ConfigureLoggers(setup =>
{
// Example: This sets the minimum log level
setup.LogLevel = LogLevel.DebugLevel;
// Example: Clear all loggers
setup.ClearLoggers();
// Example: Add the default logger
// NOTE: You can also use setup.AddLogger<DefaultLogger>();
setup.AddDefaultLogger();
// Example: Add the ILoggerFactory logger
// NOTE:
// - You can also use setup.AddLogger<LoggerFactoryLogger>();
// - To use a specific ILoggerFactory instance, you can use setup.AddLoggerFactory(myILoggerFactory);
setup.AddLoggerFactory();
// Example: Adding a serilog logger
setup.AddLogger<SerilogLogger>();
})
.WithActors((system, registry) =>
{
var echo = system.ActorOf(act =>
{
act.ReceiveAny((o, context) =>
{
Logging.GetLogger(context.System, "echo").Info($"Actor received {o}");
context.Sender.Tell($"{context.Self} rcv {o}");
});
}, "echo");
registry.TryRegister<Echo>(echo); // register for DI
});
});
A complete code sample can be viewed here.
Exposed properties are:
LogLevel
: Configure the Akka.NET minimum log level filter, defaults toInfoLevel
LogConfigOnStart
: When set to true, Akka.NET will log the complete HOCON settings it is using at start up, this can then be used for debugging purposes.
Currently supported logger methods:
ClearLoggers()
: Clear all registered logger types.AddLogger<TLogger>()
: Add a logger type by providing its class type.AddDefaultLogger()
: Add the default Akka.NET console logger.AddLoggerFactory()
: Add the newILoggerFactory
logger.
Microsoft.Extensions.Logging.ILoggerFactory Logging Support
You can now use ILoggerFactory
from Microsoft.Extensions.Logging as one of the sinks for Akka.NET logger. This logger will use the ILoggerFactory
service set up inside the dependency injection ServiceProvider
as its sink.
Microsoft.Extensions.Logging Log Event Filtering
There will be two log event filters acting on the final log input, the Akka.NET akka.loglevel
setting and the Microsoft.Extensions.Logging
settings, make sure that both are set correctly or some log messages will be missing.
To set up the Microsoft.Extensions.Logging
log filtering, you will need to edit the appsettings.json
file. Note that we also set the Akka
namespace to be filtered at debug level in the example below.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information",
"Akka": "Debug"
}
}
}
InMemory Snapshot Store And Journal Support
You can now use these AkkaConfigurationBuilder
extension methods to enable InMemory
persistence back end:
WithInMemoryJournal()
: Sets theInMemory
journal as the default journal persistence pluginWithInMemorySnapshotStore()
: Sets theInMemory
snapshot store as the default snapshot-store persistence plugin.
0.4.0
• Add Microsoft.Extensions.Logging.ILoggerFactory logging support
You can now use ILoggerFactory
from Microsoft.Extensions.Logging as one of the sinks for Akka.NET logger. This logger will use the ILoggerFactory
service set up inside the dependency injection ServiceProvider
as its sink.
Example:
builder.Services.AddAkka("MyActorSystem", (configurationBuilder, serviceProvider) =>
{
configurationBuilder
.AddHocon("akka.loglevel = DEBUG")
.WithLoggerFactory()
.WithActors((system, registry) =>
{
var echo = system.ActorOf(act =>
{
act.ReceiveAny((o, context) =>
{
Logging.GetLogger(context.System, "echo").Info($"Actor received {o}");
context.Sender.Tell($"{context.Self} rcv {o}");
});
}, "echo");
registry.TryRegister<Echo>(echo); // register for DI
});
});
There are two Akka.Hosting
extension methods provided:
.WithLoggerFactory()
: Replaces all Akka.NET loggers with the newILoggerFactory
logger..AddLoggerFactory()
: Inserts the newILoggerFactory
logger into the Akka.NET logger list.
Log Event Filtering
There will be two log event filters acting on the final log input, the Akka.NET akka.loglevel
setting and the Microsoft.Extensions.Logging
settings, make sure that both are set correctly or some log messages will be missing.
To set up the Microsoft.Extensions.Logging
log filtering, you will need to edit the appsettings.json
file. Note that we also set the Akka
namespace to be filtered at debug level in the example below.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information",
"Akka": "Debug"
}
}
}