Creating Persistent Actors in Akka.NET with Akka.Persistence

How to Create Akka.NET Actors with Durable State

One of the most frequently asked questions I get is about how to create stateful actors that are also durable by default, meaning that the actor can recover its state from some sort of storage engine in the event that the entire Akka.NET process needs to be restarted.

Enter Akka.Persistence - an entire framework built into Akka.NET that’s designed to allow you to create actors with durable state that can be persisted on any database or storage system you want.

In this post we’re going to explore the concepts behind Akka.Persistence, how it works, and what some of the available storage options are.

Not long ago in Akka.NET-land we had an issue occur where users noticed a dramatic drop in throughput in Akka.Remote’s message processing pipeline - and to make matters worse, this occurred in a production release of AKka.NET!

Yikes, how did that happen?

The answer is that although you can use unit tests and code reviews to detect functional problems with code changes and pull requests, using those same mechanisms to detect performance problems with code is utterly ineffective. Even skilled developers who have detailed knowledge about the internals of the .NET framework and CLR are unable to correctly predict how changes to code will impact its performance.

Hence why I developed NBench - a .NET performance-testing, stress-testing, and benchmarking framework for .NET applications that works and feels a lot like a unit test.

How to Unit Test Akka.NET Actors with Akka.TestKit

An Introduction to the Akka.TestKit

In this post we introduce the Akka.TestKit module - a library that makes it easy to unit test Akka.NET actors using all of the popular .NET unit testing frameworks.

A Brief End-to-End Akka.TestKit Example

Before going deep into the TestKit, here’s an end-to-end example of what a test usually looks like.

[TestFixture] //using NUnit
public class UserIdentityActorSpecs : TestKit{

    [Test]
    public void UserIdentityActor_should_confirm_user_creation_success()
    {
        var identity = Sys.ActorOf(Props.Create(() => new UserIdentityActor()));
        identity.Tell(new UserIdentityActor.CreateUserWithValidUserInfo());
        var result = ExpectMsg<UserIdentityActor.OperationResult>().Successful;
        Assert.True(result);
    }

}

80% of your tests will be this simple: create an actor, send it a message, and expect a response back. Let’s explore how to do it.