Giter Club home page Giter Club logo

akka.di.autofac's Introduction

Akka.DI.Autofac [Deprecated]

Please note that Akka.DI.Autofac and all other Akka.DI plugins are deprecated going forward. Please use Akka.DependencyInjection instead going forward.

Actor Producer Extension backed by the Autofac Dependency Injection Container for the Akka.NET framework.

What is it?

Akka.DI.Autofac is an ActorSystem extension for the Akka.NET framework that provides an alternative to the basic capabilities of Props when you have Actors with multiple dependencies.

If Autofac is your IoC container of choice and your actors have dependencies that make using the factory method provided by Props prohibitive and code maintenance is an important concern then this is the extension for you.

How to you use it?

The best way to understand how to use it is by example. If you are already considering this extension then we will assume that you know how how to use the Autofac container. This example is demonstrating a system using ConsistentHashing routing along with this extension.

Start by creating your builder, registering your actors and dependencies, and build your container.

// Setup Autofac
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<WorkerService>().As<IWorkerService>();
builder.RegisterType<TypedWorker>();
IContainer container = builder.Build();

Next you have to create your ActorSystem and inject that system reference along with the container reference into a new instance of the AutoFacDependencyResolver.

// Create the ActorSystem
using (var system = ActorSystem.Create("MySystem"))
{
    // Create the dependency resolver
    IDependencyResolver resolver = new AutoFacDependencyResolver(container, system);

    // we'll fill in the rest in the following steps
}

To register the actors with the system use method Akka.Actor.Props Create<TActor>() of the IDependencyResolver interface implemented by the AutoFacDependencyResolver.

// Register the actors with the system
system.ActorOf(resolver.Create<TypedWorker>(), "Worker1");
system.ActorOf(resolver.Create<TypedWorker>(), "Worker2");

Finally create your router, message and send the message to the router.

// Create the router
IActorRef router = system.ActorOf(Props.Empty.WithRouter(new ConsistentHashingGroup(config)));

// Create the message to send
TypedActorMessage message = new TypedActorMessage
{
   Id = 1,
   Name = Guid.NewGuid().ToString()
};

// Send the message to the router
router.Tell(message);

The resulting code should look similar to the the following:

// Setup Autofac
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<WorkerService>().As<IWorkerService>();
builder.RegisterType<TypedWorker>();
IContainer container = builder.Build();

// Create the ActorSystem
using (var system = ActorSystem.Create("MySystem"))
{
    // Create the dependency resolver
    IDependencyResolver resolver = new AutoFacDependencyResolver(container, system);

    // Register the actors with the system
    system.ActorOf(resolver.Create<TypedWorker>(), "Worker1");
    system.ActorOf(resolver.Create<TypedWorker>(), "Worker2");

    // Create the router
    IActorRef router = system.ActorOf(Props.Empty.WithRouter(new ConsistentHashingGroup(config)));

    // Create the message to send
    TypedActorMessage message = new TypedActorMessage
    {
       Id = 1,
       Name = Guid.NewGuid().ToString()
    };

    // Send the message to the router
    router.Tell(message);
}

akka.di.autofac's People

Contributors

aaronontheweb avatar alexvaluyskiy avatar arkatufus avatar augustoproiete avatar danthar avatar dependabot-preview[bot] avatar dependabot[bot] avatar egopingvina avatar marcpiechura avatar sean-gilliam avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

akka.di.autofac's Issues

With a bad dependency configuration, creating actors fails silently

I must be doing it wrong, so please point me to any form of documentation or sample.

I have a setup where I create some actors and services they use through DI using Akka.DI.AutoFac. Works fine. However as I try to create a test for their behavior, it doesn't quite work the same way.

I create a normal TestKit class. At the start of the test I initialize the container like so:

    private void setupDi()
    {
        var builder = new Autofac.ContainerBuilder();
        builder.RegisterType<MyActor>();
        var container = builder.Build();
        new AutoFacDependencyResolver(container, Sys);
    }

then when I do:

    var school = Sys.ActorOf(Sys.DI().Props<MyActor>());

It does not throw, I get an IActorRef, but when I sen messages, they do not arrive and also breakpoints in the constructor of MyActor, it never gets hit.

I must be missing something here...

Props created via DI cannot be passed between nodes.

This is something, I've detected when trying to use DI-ed Props in combination with cluster routers. Effect:

[23:35:06 ERR] AssociationError [akka.tcp://[email protected]:34161] <- akka.tcp://[email protected]:34163: Error [Value cannot be null.
Parameter name: system] [   at Akka.DI.AutoFac.AutoFacDependencyResolver..ctor(ILifetimeScope container, ActorSystem system)
   at Void .ctor(Autofac.ILifetimeScope, Akka.Actor.ActorSystem)(Object[] )
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, String id, Boolean& createdFromNonDefaultCreator)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
   at Akka.Serialization.NewtonSoftJsonSerializer.FromBinary(Byte[] bytes, Type type)
   at Akka.Serialization.Serialization.Deserialize(Byte[] bytes, Int32 serializerId, String manifest)
   at Akka.Remote.Serialization.DaemonMsgCreateSerializer.PropsFromProto(PropsData protoProps)
   at Akka.Remote.Serialization.DaemonMsgCreateSerializer.FromBinary(Byte[] bytes, Type type)
   at Akka.Serialization.Serialization.Deserialize(Byte[] bytes, Int32 serializerId, String manifest)
   at Akka.Remote.MessageSerializer.Deserialize(ActorSystem system, Payload messageProtocol)
   at Akka.Remote.DefaultMessageDispatcher.Dispatch(IInternalActorRef recipient, Address recipientAddress, Payload message, IActorRef senderOption)
   at Akka.Remote.EndpointReader.<Reading>b__11_1(InboundPayload inbound)
   at lambda_method(Closure , Object , Action`1 , Action`1 , Action`1 )
   at Akka.Tools.MatchHandler.PartialHandlerArgumentsCapture`4.Handle(T value)
   at Akka.Actor.ReceiveActor.ExecutePartialMessageHandler(Object message, PartialAction`1 partialAction)
   at Akka.Actor.ReceiveActor.OnReceive(Object message)
   at Akka.Actor.UntypedActor.Receive(Object message)
   at Akka.Actor.ActorBase.AroundReceive(Receive receive, Object message)
   at Akka.Actor.ActorCell.ReceiveMessage(Object message)
   at Akka.Actor.ActorCell.Invoke(Envelope envelope)]

I think, there's a hole in DI specs. This may be pretty bold statement, but Props serialization/deserialization is crucial part of Akka.NET and if some Props cannot be send over the wire, then they should not be called as such.

I think the reason likes in Akka.DI.Core ActorProducer which refers for IDependencyResolver and is serialized as part of the Props for some reason. If I'm right this problem may not be unique to Autofac, but actually it affects all DI plugins.

Quite possible that surrogates on either DIActorProducer or IDependencyResolver level could help here.

Autofac test suite crashes .NET Core test runner

Building for framework net452...
  Akka.DI.AutoFac -> D:\olympus\Akka.DI.AutoFac\src\Akka.DI.AutoFac\bin\Debug\net45\Akka.DI.AutoFac.dll
  Akka.DI.AutoFac.Tests -> D:\olympus\Akka.DI.AutoFac\src\Akka.DI.AutoFac.Tests\bin\Debug\net452\Akka.DI.AutoFac.Tests.dll
Running desktop CLR tests for framework net452...
xUnit.net Console Runner (64-bit Desktop .NET 4.0.30319.42000)
System.IO.DirectoryNotFoundException: Could not find a part of the path 'D:\olympus\Akka.DI.AutoFac\bin\tests\Akka.DI.AutoFac.Tests_xunit-net452.xml'.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
   at Xunit.ConsoleClient.TransformFactory.Handler_DirectWrite(XElement xml, String outputFileName)
   at System.Collections.Generic.List`1.ForEach(Action`1 action)
   at Xunit.ConsoleClient.Program.RunProject(XunitProject project, Boolean serialize, Nullable`1 parallelizeAssemblies, Nullable`1 parallelizeTestCollections, Nullable`1 maxThreadCount, Boolean diagnosticMessages, Boolean noColor, Boolean noAppDomain, Boolean failSkips, Boolean internalDiagnosticMessages)
   at Xunit.ConsoleClient.Program.EntryPoint(String[] args)
   at Xunit.ConsoleClient.Program.Main(String[] args)
Building for framework netcoreapp1.1...
  Akka.DI.AutoFac -> D:\olympus\Akka.DI.AutoFac\src\Akka.DI.AutoFac\bin\Debug\netstandard1.6\Akka.DI.AutoFac.dll
  Akka.DI.AutoFac.Tests -> D:\olympus\Akka.DI.AutoFac\src\Akka.DI.AutoFac.Tests\bin\Debug\netcoreapp1.1\Akka.DI.AutoFac.Tests.dll
Running .NET Core tests for framework netcoreapp1.1...
xUnit.net Console Runner (64-bit .NET Core 4.6.25211.01)
##teamcity[testSuiteStarted name='Test collection for Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec (1)' flowId='1665b691a5f14eadaa4a04dafb8b767a']
##teamcity[testStarted name='Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec.DependencyResolver_should_inject_into_BoundedStash_Actor' flowId='1665b691a5f14eadaa4a04dafb8b767a']
##teamcity[testFinished name='Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec.DependencyResolver_should_inject_into_BoundedStash_Actor' duration='762' flowId='1665b691a5f14eadaa4a04dafb8b767a']
##teamcity[testStarted name='Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec.DependencyResolver_should_inject_new_instances_into_DiPerRequestActor' flowId='1665b691a5f14eadaa4a04dafb8b767a']
##teamcity[testFinished name='Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec.DependencyResolver_should_inject_new_instances_into_DiPerRequestActor' duration='69' flowId='1665b691a5f14eadaa4a04dafb8b767a']
##teamcity[testStarted name='Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec.DependencyResolver_should_dispose_IDisposable_instances_on_Actor_Termination' flowId='1665b691a5f14eadaa4a04dafb8b767a']
##teamcity[testFinished name='Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec.DependencyResolver_should_dispose_IDisposable_instances_on_Actor_Termination' duration='61' flowId='1665b691a5f14eadaa4a04dafb8b767a']
##teamcity[testStarted name='Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec.DependencyResolver_should_inject_new_instances_on_Restart' flowId='1665b691a5f14eadaa4a04dafb8b767a']
[ERROR][8/15/2017 7:52:56 PM][Thread 0010][akka://test/user/$a] RESTART ME!
Cause: System.Exception: RESTART ME!
   at Akka.DI.TestKit.DiResolverSpec.DisposableActor.ForceRestart()
   at lambda_method(Closure , Object , Action`1 , Action`1 )
   at Akka.Tools.MatchHandler.PartialHandlerArgumentsCapture`3.Handle(T value)
   at Akka.Actor.ReceiveActor.ExecutePartialMessageHandler(Object message, PartialAction`1 partialAction)
   at Akka.Actor.ReceiveActor.OnReceive(Object message)
   at Akka.Actor.UntypedActor.Receive(Object message)
   at Akka.Actor.ActorBase.AroundReceive(Receive receive, Object message)
   at Akka.Actor.ActorCell.ReceiveMessage(Object message)
   at Akka.Actor.ActorCell.Invoke(Envelope envelope)
##teamcity[testFinished name='Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec.DependencyResolver_should_inject_new_instances_on_Restart' duration='65' flowId='1665b691a5f14eadaa4a04dafb8b767a']
##teamcity[testStarted name='Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec.DependencyResolver_should_inject_into_UnboundedStash_Actor' flowId='1665b691a5f14eadaa4a04dafb8b767a']
##teamcity[testFinished name='Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec.DependencyResolver_should_inject_into_UnboundedStash_Actor' duration='335' flowId='1665b691a5f14eadaa4a04dafb8b767a']
##teamcity[testStarted name='Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec.DependencyResolver_should_inject_into_normal_mailbox_Actor' flowId='1665b691a5f14eadaa4a04dafb8b767a']
##teamcity[testFinished name='Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec.DependencyResolver_should_inject_into_normal_mailbox_Actor' duration='48' flowId='1665b691a5f14eadaa4a04dafb8b767a']
##teamcity[testStarted name='Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec.DependencyResolver_should_inject_instances_into_DiChildActor' flowId='1665b691a5f14eadaa4a04dafb8b767a']
##teamcity[testFinished name='Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec.DependencyResolver_should_inject_instances_into_DiChildActor' duration='55' flowId='1665b691a5f14eadaa4a04dafb8b767a']
##teamcity[testStarted name='Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec.DependencyResolver_should_inject_same_instance_into_DiSingletonActor' flowId='1665b691a5f14eadaa4a04dafb8b767a']
##teamcity[testFinished name='Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec.DependencyResolver_should_inject_same_instance_into_DiSingletonActor' duration='45' flowId='1665b691a5f14eadaa4a04dafb8b767a']
##teamcity[testStarted name='Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec.DependencyResolver_should_dispose_IDisposable_instances_on_Actor_Restart' flowId='1665b691a5f14eadaa4a04dafb8b767a']
[ERROR][8/15/2017 7:52:57 PM][Thread 0012][akka://test/user/$a] RESTART ME!
Cause: System.Exception: RESTART ME!
   at Akka.DI.TestKit.DiResolverSpec.DisposableActor.ForceRestart()
   at lambda_method(Closure , Object , Action`1 , Action`1 )
   at Akka.Tools.MatchHandler.PartialHandlerArgumentsCapture`3.Handle(T value)
   at Akka.Actor.ReceiveActor.ExecutePartialMessageHandler(Object message, PartialAction`1 partialAction)
   at Akka.Actor.ReceiveActor.OnReceive(Object message)
   at Akka.Actor.UntypedActor.Receive(Object message)
   at Akka.Actor.ActorBase.AroundReceive(Receive receive, Object message)
   at Akka.Actor.ActorCell.ReceiveMessage(Object message)
   at Akka.Actor.ActorCell.Invoke(Envelope envelope)
##teamcity[testFinished name='Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec.DependencyResolver_should_dispose_IDisposable_instances_on_Actor_Restart' duration='91' flowId='1665b691a5f14eadaa4a04dafb8b767a']
##teamcity[testSuiteFinished name='Test collection for Akka.DI.AutoFac.Tests.AutoFacDependencyResolverSpec (1)' flowId='1665b691a5f14eadaa4a04dafb8b767a']

Unhandled Exception: System.IO.DirectoryNotFoundException: Could not find a part of the path 'D:\olympus\Akka.DI.AutoFac\bin\tests\Akka.DI.AutoFac.Tests_xunit-netcoreapp1.1.xml'.
   at System.IO.Win32FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, FileStream parent)
   at System.IO.Win32FileSystem.Open(String fullPath, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, FileStream parent)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
   at Xunit.ConsoleClient.TransformFactory.Handler_DirectWrite(XElement xml, String outputFileName)
   at System.Collections.Generic.List`1.ForEach(Action`1 action)
   at Xunit.ConsoleClient.Program.RunProject(XunitProject project, Boolean serialize, Nullable`1 parallelizeAssemblies, Nullable`1 parallelizeTestCollections, Nullable`1 maxThreadCount, Boolean diagnosticMessages, Boolean noColor, Boolean noAppDomain, Boolean failSkips, Boolean internalDiagnosticMessages)
   at Xunit.ConsoleClient.Program.EntryPoint(String[] args)
   at Xunit.ConsoleClient.Program.Main(String[] args)

Looks like an issue with the output being written to the wrong location following execution of the tests.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.