If you’ve have any experience with Akka, then you know that the Actor System represents a hierarchy of managed actors. This hierarchy is a supervisory hierarchy and allows for actor supervision much the way Erlang has supported process supervision for … I dunno, since the dinosaur age for sure.
Recently I’ve been writing some code for a non-blocking socket server that has all of its business logic encapsulated within an Akka Actor System. An actor system is a very heavy weight thing and most people recommend that you only keep one of these things around per process. You might feel tempted to create multiple systems to segment different purposes within your application but all of the information I’ve found discourages this practice. I haven’t had enough real-world experience to vouch for this but, people who are way smarter than I am say to only use one actor system per process, so that’s what I’ll do.
I had some trouble when it came time to reference my actor system. I had a companion object of an actor and, unfortunately, an actor’s companion object can’t see the context object that regular actor classes can see. In other words, my method couldn’t refer to the system via context.system, which is the recommended way for actors to refer to the system to which they belong.
So, I thought I would be clever and create a new instance of ActorSystem but re-use the same name that I used the last time. I thought maybe it would seek out and find the existing actor system and just create a new lightweight reference to it. This is wrong. Here’s the proof, create two vals:
val system = ActorSystem("foo") val system2 = ActorSystem("foo")
Now, create an actor within system via system.actorOf and maintain a reference to it. If the two actor systems are identical, then you should be able to obtain a reference to that actor with system.actorFor using system2 and it’ll be the same actor. This is not the case. Even though both systems have the same name, they are different instances, managing different actor hierarchies, with different state and potentially divergent configurations.
My solution, which may not be the best, is to do the following, in order of precedence:
- Refer to the actor system within an Actor class via context.system. This won’t work within actor companion objects, however.
- Refer to the actor system by getting it from a global object, e.g. ApplicationServer.system. This should only be done when #1 won’t work.
If someone else has a more clever way of managing and referring to the actor system, I’d love to hear it. So far, this is the only way I’ve been able to keep my code anywhere close to clean.