Reactive Mistakes: Flat Actor Hierarchies

Petr Zapletal
5 min readJul 25, 2017

Welcome in another topic I’d like to discuss. This time is not about what people do, it’s more about what they don’t do but I think they should. I’d like to make a brief motivation about supervision. Honestly, I have a feeling that supervision is one of the Akka’s fundamental ideas which is not used as it should.

The motto of this topic should probably be:

But before we get to it, let’s have a quick recap what Akka’s supervision is.

The Actor Hierarchy

In the picture below we can see two top level actors.

We create them by calling actor system.actorOf. They are called top-level because they are created by the actor system, not by another actor. One of the key points of actor’s supervisions is that very actor, or almost every actor as you’ll see in a minute, has a supervisor. So who supervises these?

As you guys probably know, these actors are implicitly supervised by the (User) Guardian actor (sometimes referenced just as the Root Actor).

The second key point of supervision is that every actor can also BE a supervisor and every actor supervises his children.

So when we start creating actors not by using actor system but using actor contexts, we can get something like this.

As you can see in the picture C1 and C2 are supervised by B1 and B1 is supervised by A2 and so on. So that was the hierarchy and now let’s talk about what is it good for. The point is, that every time an actor throws an unhandled exception his supervisor may decide what to do with that. He can tell the actor to ignore it, he can also stop the actor, restart it or escalate this up to his own supervisor and he can also apply this not just to the problematic actor but all its siblings. And that’s pretty much it.

So that were the user actors, but we also have system actors.

Their job is basically to take care of actor system features like actor logging for example and they are also responsible for actor system’s shut down and all these infrastructure features. This is not that important for us now but it’s good to know there is something like that. And also if you’re wondering what is the slash (“/”) actor on top. This actor is called TheRoot Guardian and it’s the only actor which is not supervised.

Two Different Battles to Win

So that was the quick recap what the supervision is but why do we want that. Basically, there are two battles we want to win. Firstly, we want to separate our business logic and our error handling for having a less complex code. And secondly, we want our application to able to get back to life after something bad happened. Supervision gives us a failure isolation and a system recovery and therefore no more midnight calls for us. Hopefully.

Obviously, I don’t want to push you into using supervision wherever possible. That’s probably not a good idea. You guys should always decide what makes more sense in your particular use case. I think a nice guideline how to decide is to split your exceptions into Errors and Failures. Errors are common events, like incorrect requests, problems during validation and so on, and they are communicated with the client or caller. On the other hand, a failure is an unexpected event within a service that prevents it from continuing to function normally. A failure will generally prevent responses to the current, and possibly all following, requests. Failures should be reported to the supervisor, the client can not do anything about that anyway. As an example, we can have database failures, network partitions or hardware malfunctions and so on. And btw this is not something I made up yesterday, this is taken from the reactive manifesto [1]. So the core idea is pretty old.

Let’s summarize that:

Error Kernel Pattern

Regarding supervision, we may have a problem — what to do with an actor’s state during restarts. There is this pattern for it. Basically, it is just a simple guideline you should try to follow stating that if an actor carries important internal state, then it should delegate dangerous tasks to its children to prevent the state-carrying actor from crashing. Sometimes, it might make sense to create a new child actor for each such task, but that’s not a necessity.

Summary

Akka provides supervision which allows us to create rich hierarchies to separate business logic and failure handling and if used properly, our applications might be self-healing and resilient. So try to take advantage of it.

That’s it for today, if you have any questions/comments don’t hesiate to let us know in the section below!

— Petr

References

[1] http://www.reactivemanifesto.org/

--

--