Akka.NET #6: Persisting actors state – snapshots

By | May 17, 2017

In the previous post, I’ve briefly described part of a process of persisting state of our actor. I’ve told you about storing events and I’ve mentioned things called snapshots. This post is entirely about them.

Snapshots are created for just on purpose, to improve the performance of recovering actor’s state during restoring it. It’s pretty straightforward, just imagine you have actor which represents single bank account that is live for last two years. Every single financial transaction is stored as an event. And let me ask you a question, how many times you’ve paid via card or wire for anything during the last month?

I’ve over 50 incoming and outcoming transactions on my account monthly. That would give 1200 stored events and this scale is really, really small because with throughput that is possible with Akka.NET it could be hundred or thousand times more. What would happen if you would just restore event one by one?

That’s why from time to time you should make a snapshot, it’s like CTRL + S for your actor’s state. How often should you make it? It depends, mostly on how much it’ll cost to restore single event inside of an actor if it involves some complex operations (it shouldn’t) you should make snapshot a little more often than situation while you’re storing/recovering “increment-this-counter-event”.

Creating a snapshot

Personally, I like to have entire actor’s state in single, private class that is nested inside of my actor’s instance. That’s really easy to persist and manage also I can expose some methods with events as input parameters to guarantee that state will change in the same way regardless of event origin (from an incoming command/restored).

So, how do we make a snapshot of that? I’ve enclosed handling that in a method in my base actor class.

It’s pretty simple construct with basic counter and interval made virtual so I can override this value in implementation. The most important method is SaveSnapshot with input parameter object so it’ll take anything. My entire method is invoked during persisting of any event, that means I’m storing snapshot once for every 100 persisted events.

Restoring snapshot

So saving snapshots is pretty easy. How about restoring them and indicating which events we should restore after that? I have good news for you, Akka.NET will handle that for you.

If you’ll take a look at storage you’re using you should see field or column named SequenceNr which is counter for your events (your actors also have this field named LastSequenceNr and you can use it with modulo to eliminate your counter from snapshot handling logic), this counter is used to indicate that you’ve just restored snapshot for actor state when its SequenceNr was n and we should recover any event with SequenceNr bigger than that.

How? Do you remember from the previous post how we’ve restored events with Recover method? We should use the same method but instead of passing event type as a generic parameter, we should pass SnapshotOffer there.

When snapshot will be found during actor restoration offer will be recovered, cast to our ActorState type and assign to a variable that stores it. It’s that simple.

Of course, persistence in Akka.NET have some advanced scenarios but storing events and snapshots should be enough for most cases. But we’ll go through some of the fun ones soon.