Akka.net: Should we adopt Microsoft.Extensions libraries?

Created on 30 Aug 2017  路  9Comments  路  Source: akkadotnet/akka.net

This is only an idea, but maybe it's worth discussing. At the present moment we can see, that there are several libraries (by convention called Microsoft.Extensions.*.Abstractions), that are meant to provide a .NET Standard wide API for common things like caching, configuration, logging or dependency injection.

We already were loosely talking about potential to improve some parts of the Akka.NET API. I'm not talking about supporting all of them or none, but at least some of those would give us potential gain. Want to hear your thoughts @akkadotnet/core .

1. Abstracting HOCON configuration into objects

Most (all?) of the current akka extensions are already parsing HOCON config directly into object notation. The idea was to get rid of the direct HOCON dependencies in the internals, relying totally on objects instead.

This is place where Microsoft.Extensions.Configuration.* libraries would be handy: they provide common abstractions like IConfiguration, IConfigurationSource, ConfigurationPath etc. Moreover there are already implementations that automatically will allow us to parse i.e. Json, Xml or even Command Line arguments into that notation.

We'd need to do several things:

  • Reimplement our XXXSettings.Create(Config hoconConfig) builders to XXXSetttings.Create(IConfiguration config).
  • Expose ActorSystem.Settings.Config as IConfigurationRoot rather than HOCON Config object.
  • Provide equivalent of Microsoft.Extensions.Configuration.Hocon library, that would keep backward compatibility with existing HOCON config. Outsource HOCON from akka itself.

Pros:

  • Ability to integrate akka configuration with any existing solution i.e. Asp.NET appsettings.json or web.config.
  • IDE support in place - right now HOCON is not supported by any .NET IDE. It's also dynamic: configuration cannot be verified and is often source of runtime errors.

2. Abstracting actor creation pipeline

As I've already proposed (#1675) and PRed (#2638) , we could replace current complex actor creation pipeline and abstract it together with dependency injection plugins. Some of the MS frameworks, like Orleans and ASP.NET Core, are already using Microsoft.Extensions.DependencyInjection.* libraries to provide a generic construction mechanism. We could adopt it on our side as well.

Pros:

  • A common creation mechanism, that could be used to give native DI support for:

    • actors

    • serializers

    • event adapters

    • Akka extensions (no need to differentiate between IExtension and ExtensionIdProvider<>, as extension itself would be created via dependency injection). This is the most serious change, to be considered.

  • No longer need to support and maintain hundreds of akka DI plugins.

3. Abstracting logging libraries

Microsoft.Extensions.Logging,* libaries give us primitives to abstract logging capability. This way we could outsource concrete implementations (NLog, log4net, Serilog) outside. However looking at nuget this is the most messy case of all.

Pros:

  • No longer need to support and maintain logging akka plugins.
akka-actor discussion

Most helpful comment

Mark Seeman has some fantastic articles and I've followed his work for years. A number of points in that specific article still hold true today. What doesn't ring true are his conclusions. DI has come a long way over the past 10 years. It's so paramount to extensible design that it's even now in practice in front-end javascript frameworks and functional paradigms.

The reality is, whether Mr. Seeman likes it or not, there is a common, stable intersection of baseline functionality that a DI container must be capable of. The community has helped shape this over the many revisions of frameworks. Microsoft.Extensions.DependencyInjection is not new ... it's been kicked around and refactored a hundred times over in various incarnations and names - taking best practices from the community.

Akka.net should absolutely adopt this going forward. The unification towards a generic host and these various extension addons has made dotnet core development a great experience. IMO

All 9 comments

My thoughts on this:

1: Abstracting HOCON configuration into objects

I am all for extracting the current version of Hocon from the akka.net core codebase. And bringing the existing separate Hocon repo up to date. And then having the core codebase depend on that instead. (I would refer to this as: "the initial legwork")

After that we can probably create a Microsoft.Extensions.Configuration.Hocon implementation.
I am not sure about the IDE support though.
I don't see how creating an implementation for Microsoft.Extensions.Configuration would magically give Hocon IDE support.
And by that I am talking about something more then just raw string editing. One could argue that configuring VS to treat Hocon files as JSON works just as well at the moment.

2. Abstracting actor creation pipeline

+1 on this. With a side remark that as of 1.3 we only officially support Autofac as a DI container.

3. Abstracting logging libraries

This is perhaps the most tricky one yet. But having a default logger which looks to the Microsoft.Extensions.Logging stuff to do the actual logging would make logging plugins virtually obsolete.

Any of the above must come with a migration path for current users.

Has any work been done on better integration with Microsoft.Extensions.Logging? It's quite the hazzle to set it up right now as you can't seem to be able pass a logger instance to akka directly currently. Passing parameters do not seem to be possible either.

@BlueManiac you can set your own logger and pass it using HOCON configuration:

akka.loggers = [ "MyNamespace.MyLogger, MyAssembly" ]

@Horusiath Yes, I know, i'm currently using the serilog logger adapter there. I would like to pass a custom logger there instead that isn't passed in some static variable somewhere that you seem to be required to use right now. (the serilog akka logger uses serilog's static Log.Logger property)

I'd advise against using Microsoft.Extensions.DependencyInjection. It is an implementation of the Conforming Container anti-pattern. Mark Seeman wrote about Microsoft.Extensions.DependencyInjection in Feedback on ASP.NET vNext Dependency Injection. While this is an old article, it is clear from pre-releases of his Dependency Injection in .NET, Second Edition that nothing in more recent releases has changed his views on this.

I agree with this position.

I'm more interested in using IConfiguration.

I'd advise against using Microsoft.Extensions.DependencyInjection. It is an implementation of the Conforming Container anti-pattern. Mark Seeman wrote about Microsoft.Extensions.DependencyInjection in Feedback on ASP.NET vNext Dependency Injection. While this is an old article, it is clear from pre-releases of his Dependency Injection in .NET, Second Edition that nothing in more recent releases has changed his views on this.

I agree with this position.

I do not agree with all of the points mentioned there. Also this left the point of code sharing capabilities, for example think about the Add* extensions available for ASP.net core. For me, Autofac integrates well with the ServiceCollections provided by the DI Extensions. The interface already proved well and not the interface ist responsible for protecting from applying bad patterns around it. So you can go to dark side with specific containers, too.

And there is more than DI. I would like to see integration with Microsoft.Extensions.Configuration. And this is not an all or nothing.

Mark Seeman has some fantastic articles and I've followed his work for years. A number of points in that specific article still hold true today. What doesn't ring true are his conclusions. DI has come a long way over the past 10 years. It's so paramount to extensible design that it's even now in practice in front-end javascript frameworks and functional paradigms.

The reality is, whether Mr. Seeman likes it or not, there is a common, stable intersection of baseline functionality that a DI container must be capable of. The community has helped shape this over the many revisions of frameworks. Microsoft.Extensions.DependencyInjection is not new ... it's been kicked around and refactored a hundred times over in various incarnations and names - taking best practices from the community.

Akka.net should absolutely adopt this going forward. The unification towards a generic host and these various extension addons has made dotnet core development a great experience. IMO

The more I think about it, I think there might be some value in porting something similar to ActorSystemStartup.

Directly supporting DI inside actors - probably not something we're going to do. Introduces unpredictably expensive third party components into an extremely concurrent area of the system for minimal value. Pass in a reference to the IServiceCollection into your actor's constructor and don't ask us to lard up the guts of the framework for a use case that isn't common and not that hard to solve in user code.

Passing in DI and IConfiguration for enabling settings like tracing, serialization, and so on - yeah I could see that. The configuration hit for all of those items occurs exactly once at ActorSystem creation and that's it. Due to the concurrent nature of actors we'd never support something like configuration reloading - realistically you have to restart the ActorSystem to do that.

Was this page helpful?
0 / 5 - 0 ratings