Home Best Practices Typed actors with routing

Typed actors with routing

Author

Date

Category

This is a blog post of our Code Reading Wednesdays from Codacy (http://www.codacy.com): we make code reviews easier and automatic.

A few weeks ago we wrote about typed actors and how we built our architecture around them. This week we are going to explain how we use them with routing to scale our system.

With Typed Actors, like with normal Actors, you have an external API that will delegate method calls asynchronously to a private instance of the implementation. The advantage is that Typed Actors have a static contract and you don’t need to define your own messages, although there are some limitations on what you can do, i.e. you cannot use routing as in normal actors.

With our architecture using typed actors, and rolling back to untyped actors not being an acceptable solution, we decided to invest some time researching for a proper way to achieve typed actors with routing.

Research

After a lot of documentation reading and trial/error we could not find any working solution that could meet our needs, so we started searching for other similar cases on the web.

The problem was already common within the Akka community and we found a lot of suggestions but not a fully working solution.

A common solution was to create a sequence of actors and let them be routed by an untyped actor. As you may think, that would break our main goal of having typed actors and would throw as back to the traditional Akka message system.

This solution is not useless because it solves part of the problem, so we decided to work with it to meet out needs. The next step was to start looking for a way to connect one of our typed actor with the list of actors to route and we found that, even thought a typed actor can’t have routing, it could receive a untyped router.

Solution

The solution is a pretty simple composition of the two options I explained before.

To start we need a group of typed actors, a sequence of the actors you want to route. These are the actors that’ll do the actual work.

To manage those actors we need to create an untyped actor that routes them, a simple actor with any of the default Akka routers or even with one you define, and then pass the typed actors you created before as workers.

To complete the typed actors router we obviously need a typed actor, so we can have a typed interface to the untyped actor as if we have a single one. This is achieved by creating a typed actor equal to the ones in the sequence, but in this case you pass him the router you created in the second step, and that will have a typed actor set up.

Implementation

Since we use Scala, we’re providing a simplified Scala implementation.

Starting by the typed actors that will be routed:

val actors = (1 to actorCount).map {
    i =>
      TypedActor.get(system).getActorRefFor(TypedActor.get(system).typedActorOf(TypedProps(Reflect(system).actorClassFor(className.get)).withTimeout(timeout)))
  }

Then the untyped actor that will route the previous actors:

val router = system.actorOf(Props.empty.withRouter(SmallestMailboxRouter.create(actors.toIterable.asJava)))

And to finish the typed actor that will be the interface to the routing system:

TypedActor(system).typedActorOf(TypedProps(Reflect(system).actorClassFor(className.get)).withTimeout(timeout), router)

And now a complete example:

123456789101112131415161718

val defaultAkkaTimeout = 60

val defaultNumberOfActors = 10

def getComponentActor[T <: AnyRef](timeout: akka.util.Timeout = Timeout(Duration(defaultAkkaTimeout, SECONDS)))(implicit m: Manifest[T]): T = {

val className = this.classCache.get(m.runtimeClass.getName)

val actorCount = defaultNumberOfActors

val actors = createRouterActors(actorCount,className,timeout)

val router = system.actorOf(Props.empty.withRouter(SmallestMailboxRouter.create(actors.toIterable.asJava)))

TypedActor(system).typedActorOf(TypedProps(Reflect(system).actorClassFor(className.get)).withTimeout(timeout), router)

}

def createRouterActors[T <: AnyRef](actorCount:Int, className:Option[String], timeout:akka.util.Timeout)(implicit m: Manifest[T]): Seq[ActorRef] = {

(1 to actorCount).map {

i =>

TypedActor.get(system).getActorRefFor(TypedActor.get(system).typedActorOf(TypedProps(Reflect(system).actorClassFor(className.get)).withTimeout(timeout)))

}

}

view rawtype-actors-routing.scala hosted with ❤ by GitHub

The code is quite simple and allows us to use a beautiful architecture. With this, we have a system that is easily scalable and we are still using Akka’s typed actors.

That’s it for this week. Hope you find this useful and can use it in your projects.


Edit: We just published an ebook: “The Ultimate Guide to Code Review” based on a survey of 680+ developers. Enjoy!


About Codacy

Codacy is used by thousands of developers to analyze billions of lines of code every day!

Getting started is easy – and free! Just use your  GitHub, Bitbucket or Google account to sign up.

GET STARTED

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Subscribe to our newsletter

To be updated with all the latest news, offers and special announcements.

Recent posts

OWASP Top 10 vulnerabilities and how Codacy helps to address them

In today’s modern, digitized world, security is more important than ever to respond to growing threats. Every web application comes with system vulnerabilities, and...

2020, It’s a wrap! 🎊

Looking back at 2020, it has been a year of change and innovation for Codacy. We became fully remote and will continue to be,...

Migrating to React: Typed named routes in react-router and Typescript

INTRODUCTION If you’re a regular user of Codacy, you might have noticed a few changes over the course of this year on some pages. We’re...

Introducing Pulse to help companies achieve elite engineering performance

At Codacy, we envision a future where everyone can impact the world by crafting complex software with confidence and focus at the speed of...

First QA Engineer in a Startup

This is the story of how I joined a startup as the first QA Engineer in the company.  My name is Bruno Medley, I'm a...