Hi everybody!

On these days I had a break and I was able to investigate something different from work not related to streams and I discovered this library Typed Actors by @knutwalker which I liked so much that I decided to write a post about it. And just a short post because its documentation is already very good! For the impatient here’s the demo project I’ve created 🙂

AKKA ACTORS

As you might know, if you ever used Akka actors, its main method type ‘receive’ is Any => Unit, exposing the lack of type safety. This is very dangerous and human error prone, given the fact that you can send any message to an Actor B and it might not handle that specific type of message. But what if you can get errors in compile time to identify these cases? Well, this is what Typed Actors provide and it’s very nice to work with.

TYPED ACTORS

Taken directly from its documentation, Typed Actors has the following goals:

add a compile-time layer to existing ActorRefs with minimal runtime overhead

be compatible with all of the existing Akka modules, traits, and extensions in terms of composition and behavior

There are a few ways to define a TypedActor but the one I like the most and I recommend is to extend the TypedActor trait to add more exhaustiveness check for our types. Let’s see a few examples:

import com.gvolpe.typed.examples.actor.StrictTypedActor._ import de.knutwalker.akka.typed._ object StrictTypedActor { sealed trait StrictMessage extends Product with Serializable case object StrictOne extends StrictMessage case object StrictTwo extends StrictMessage case object NotStrict // Same as Props[StrictMessage, StrictTypedActor] but using type derivation def props = PropsFor[StrictTypedActor] } class StrictTypedActor extends TypedActor.Of[StrictMessage] { override def typedReceive: TypedReceive = { case StrictOne => println(s"received StrictOne at $typedSelf") case StrictTwo => println(s"received StrictTwo at $typedSelf") // case NotStrict => println(s"this does not compile!") } }

In the case above, the actor will only handle messages of type StrictMessage defined as an ADT. Let’s see the types that we will get when using this typed actor and what we can do with it:

import akka.actor.ActorSystem import de.knutwalker.akka.typed._ implicit val system = ActorSystem("typed-actors-demo") val actor: ActorRef[StrictMessage] = ActorOf(StrictTypedActor.props, name = "typed-actor") actor ! StrictOne //actor ! "Hello world!" // This won't compile!!!

It’s very nice that if we try to send a message that is not handled by the actor we get a compilation error!

INTERACTION WITH EXISTING AKKA ACTORS

It’s also possible to work with an existent unsafe actor application without any problems. The library provides two main functions to switch between typed and untyped actors all we want. Let’s see an example:

import akka.actor.ActorSystem import de.knutwalker.akka.typed._ implicit val system = ActorSystem("typed-actors-demo") val actor: ActorRef[StrictMessage] = ActorOf(StrictTypedActor.props, name = "typed-actor") val unsafeActor: UntypedActorRef = actor.untyped // Alias for akka.actor.ActorRef val typedAgain: ActorRef[StrictMessage] = unsafeActor.typed[StrictMessage]

That’s it, not too much to add. Typed Actors makes it easy only by adding a small extra amount of code and we gain all the best of type safety. However we decide how much type safety we want to put in our application just because it’s very easy to have both typed and untyped actors living together in the same context.

EXAMPLES

There are a lot of cases that I haven’t mentioned in this post like Union Types, Ask Pattern (or ReplyTo), Persistence Actors and the Typed Creator module among others, but almost everything is possible using this powerful library. Check out the official documentation that is awesome! And I’ve also created a demo project with a lot of examples and also the Akka example to calculate a Pi approximation converted to use Typed Actors. Check it out on GitHub!

Until next post!

Gabriel.