On Akka .NET Actor Creation

Abstract: this article is a bit of a rant about how actors are created in Akka .NET, and suggests a way of making it just a little bit more manageable. This is written based on my limited knowledge of Akka .NET, and I will be more than happy to stand corrected on the matters I write about.

Actors Need Props

Creating an ActorSystem and actors in Akka .NET is one of the most basic necessities, and it is something you’ll be doing all the time. Once you have an ActorSystem, you can create actors using an IActorRefFactory implementation (i.e. the ActorSystem itself, or an actor’s Context). This requires you to use Props.

            using (var actorSystem = ActorSystem.Create("MyActorSystem"))
            {
                var props = Props.Create<MyActor>();
                var actor = actorSystem.ActorOf(props);

                Console.ReadLine();
            }

What the hell are Props?

This is explained by Unit 1 Lesson 3 of the Petabridge Akka .NET Bootcamp. Basically, the answer is something like: it’s a recipe for creating actors, but don’t worry about it for now; we’ll use it later.

As a matter of fact, it’s needed mainly for advanced scenarios such as remote deployment and clustering. Most of the time as you’re learning to use Akka .NET, you don’t really care about them.

Creating Props

There are three ways to create Props, all involving some manner of a call to Props.Create().

The first way is to give it a Type.

var props = Props.Create(typeof(MyActor));

This is discouraged by Akka .NET, because it has no type safety and in fact lets you do stupid things like this:

akka-actorcreaton-typeof

The second way is to use a generic form:

var props = Props.Create<MyActor>();

While this is encouraged in the bootcamp, I personally discourage this. This is because while it gives you type safety over the actor type, it doesn’t give you any guarantees with the parameters:

akkanet-props-generic-2

The third way is to pass in a factory method. This is a great way to create Props because it’s the only one that lets you pass dependencies into the actor’s constructor in a type-safe manner (particularly important to use constructor injection if you’re thinking of writing tests against your actors).

var props = Props.Create(() => new MyActor());

Making It Better

In reality, most of the time I don’t care about Props. So why do I have to constantly bother about them? Actually, if we take a closer look at the third way of creating Props, we can wrap them into oblivion:

akkanet-props-expression

See that generic Expression over there? That’s what we need to avoid all this madness. Based on that, we can create a generic method to take care of everything:

    public static class IActorRefFactoryExtensionscs
    {
        /// <summary>
        /// Creates an actor, creating props based on the provided
        /// actor factory method.
        /// </summary>
        /// <typeparam name="T">The actor type.</typeparam>
        /// <param name="actorRefFactory">ActorSystem or actor Context.</param>
        /// <param name="actorFactory">Actor factory method.</param>
        public static IActorRef CreateActor<T>(this IActorRefFactory actorRefFactory,
            Expression<Func<T>> actorFactory) where T : ActorBase
        {
            var props = Props.Create(actorFactory);
            var actor = actorRefFactory.ActorOf(props);
            return actor;
        }
    }

To create an actor directly from the ActorSystem, we now only need to do this:

var actor = actorSystem.CreateActor(() => new MyActor());

…and to do it from inside an actor, it’s just as easy:

var actor = Context.CreateActor(() => new MyActor());

Weird Conventions

This is where the rant begins.

Apart from all the weirdness associated with having to deal with Props in the first place, Unit 1 Lesson 3 of the Petabridge Akka .NET Bootcamp has this little gem that makes my day brighter every time I read it:

How do I make Props?

“Before we tell you how to make Props, let me tell you what NOT to do.

DO NOT TRY TO MAKE PROPS BY CALLING new Props(...). Similar to trying to make an actor by calling new MyActorClass(), this is fighting the framework and not letting Akka’s ActorSystem do its work under the hood to provide safe guarantees about actor restarts and lifecycle management.”

Here’s a similar gem from Unit 1 Lesson 1:

NOTE: When creating Props, ActorSystem, or ActorRef you will very rarely see the new keyword. These objects must be created through the factory methods built into Akka.NET. If you’re using new you might be making a mistake.”

Wait, what? These guys are telling us to call static Create() methods rather than using constructors. These are the same people who told us that using async/await in actors is bad (which has since been corrected). I don’t know, but I bet if you ask anyone who has done OOP before, they’ll tell you that if there’s a mistake, it’s in Akka .NET’s design.

But to really top it all, check out the following comment from Aaron Standard (Petabridge CTO and Akka .NET co-founder) on the Reddit thread about one of his articles (emphasis mine):

Orleans is a piss-poor implementation of the Actor model and breaks a lot of the conventions that make it powerful, aside from having an overall hideous set of programming conventions. But because MSFT released it, people will flock to it like lemmings.

“We’re going to keep working on Akka.NET because there’s a community supporting it now and because we believe in TypeSafe’s vision for actor systems.”

A case of the pot calling the kettle black? Or quoting Confucius, “Don’t complain about the snow on your neighbor’s roof when your own doorstep is unclean.”

In any case, my goal is not to start a flame war but to understand why the Akka .NET API (and codebase) is such a mess. If you look at the source code for ActorSystem, for instance, it does not do anything so particularly complicated that would justify banning constructor calls. In fact, the call to ActorSystem.Create() ends up here:

        private static ActorSystem CreateAndStartSystem(string name, Config withFallback)
        {
            var system = new ActorSystemImpl(name, withFallback);
            system.Start();
            return system;
        }

In fact, although you shouldn’t do this, this code works just as well as what we had before:

            using (var actorSystem = new ActorSystemImpl("MyActorSystem"))
            {
                actorSystem.Start();

                var actor = actorSystem.CreateActor(() => new MyActor());

                Console.ReadLine();
            }

Why is this even public such that I can call it?

Conclusion

The API provided by Akka .NET, particular in ActorSystem and actor creation, is very strange indeed. We are discouraged to do something as trivial a calling a constructor, and have to deal with Props even though we won’t need them most of the time. It is hard to speculate on why this API was written this way without having the developers provide insight on it.

At the very least, aside from pointing out these obvious flaws, this article aims to suggest best practices on how to go about creating Props, and to provide an extension method to hide the existence of Props for the majority of cases where using them directly isn’t really necessary.

6 thoughts on “On Akka .NET Actor Creation”

  1. Interesting article. Have you used Orleans much? If so do you prefer Akka.net and why? If not why do you prefer Orleans πŸ˜€ Id be very interested to hear your thoughts.

  2. I haven’t really built anything with Orleans, but I’ve done a lot of research about it. My view is that the Orleans team went to great lengths to build an actor model that feels familiar for .NET developers, hides a lot of boilerplate, and makes a lot of hard distributed computing issues transparent. They also have very good documentation. I can’t say the same about Akka .NET.

    Akka .NET gives you more control, but you have to do a lot of extra boilerplate that you might not care about most of the time.

    There is a comparison between Akka .NET and Orleans you can look at.

    I did my own research to compare the two (since I was interested in the differences from a practical level). In a nutshell: Orleans handles a lot of things automatically (actor activation/deactivation, clustering, scaling). Orleans disguises actor messaging as simple async method calls so you don’t have to create extra message classes and worry about immutability like you do in Akka .NET. Actors have single-thread guarantees in both, but Orleans also supports reentrancy if you need it. Supervision hierarchies are unnecessary in Orleans; you simply handle exceptions as you would normally, and if an actor crashes for some reason, Orleans automatically handles fault tolerance by recreating it elsewhere. Actor persistence is supported by both. Unit testing is really easy in Orleans, a nightmare in Akka .NET. The only downside I’ve seen with Orleans is that ordering of messages as they arrive at an actor is not 100% guaranteed, but there are ways to do this yourself (e.g. discard messages with earlier timestamp, or use Orleans streams). Orleans has taken some flak in the past for not providing finite state machines out of the box, which are really trivial to do with an enum and a switch statement.

    Akka .NET is really powerful but I really don’t like its codebase and API design. Being a port of Akka from another language, it feels like a literal translation (which is often not a good thing in natural language). There are aspects that make working with it difficult e.g. many ways to do the same thing (e.g. props creation, consistent hashing key), and a lot of things (e.g. DI) that feel like a patched afterthought. The fact that they use statics everywhere makes it hard to build proper (and testable) software with it. Community support is okay but a bit limited, documentation is very lacking beyond basic scenarios and you often have to delve into the source code (which is a mess).

  3. Hi Gigi,

    Long time no see. I suspect the problems you are facing are due to the fact that Akka (at least to me) seem to be influenced by the way Java does things. I stand to be corrected though. We have used Akka (Java version) in a project, and I must say that it has a steep learning curve, especially since it has this dependency on Scala. I do see your point though re the use of Props. Great article!

    JB

    1. Hi! Thanks for reading and for your comment! Yes, you are spot on – to carry the Akka name, the Akka .NET API needs to be as close to the original Akka as possible. I think that’s a pretty bad deal. If you translate natural language literally, you’re typically not going to make a good impression. Same when you’re porting software. You can’t just shove a Java/Scala port down .NET developers’ throats without making an effort to fit into the ecosystem they’re used to. Case in point is QuickFix, which is one of the biggest messes of code I’ve ever seen.

  4. Thanks for your response Gigi. Just to let you know ive evaluated Orleans and will probably use that rather than Akka.net. I think because it better follows a .NET developers frame of mind for a lot of concepts. This makes it far easier for our team (a .NET team) to learn and get to grips with it.

    Plus, personally, I just feel it works really nicely πŸ™‚

Leave a Reply

Your email address will not be published. Required fields are marked *