Akka Logo

Akka for the Impatient

Josep Prat  GitHub Logo - 2020/09/08

Link to the companion Repo

QR code for the repository

Questions:

  • What is Akka?
  • What is an Actor?
  • When should I use Actors?
  • Which Actor style to choose?
  • How do I test Actors?

What is Akka?

Akka is a toolkit and runtime whose focus is on simplifying the creation of concurrent and distributed systems.
Akka is most commonly associated with their actor library.

What is Akka?

However, Akka Platform comprises several modules and libraries:

  • Akka (Actors)
  • Akka Persistence
  • Akka Cluster
  • Akka Streams
  • Akka HTTP
  • Alpakka
  • and others...

What is Akka?

Akka's success comes primarily from bringing the Actor Model (highly inspired by the Erlang one) to the JVM.

What is an Actor?

Actors organize themselves in parent-children hierarchies. Each parent takes care of their children during their complete lifetime.

And yes:

“One Actor is no Actor. Actors come in Systems.”
Carl Hewitt

What is an Actor?

Actors can only communicate with each other using messages. Any attempt to access directly their internal state is against the Actor Model.

Ideally such messages should be immutable.

What is an Actor?

Overly simplifying an actor encapsulates:

  • State
  • Behavior
  • Mailbox
  • Children*
  • Supervision Strategy*

* Optional

What is an Actor? - State

An Actor that doesn't keep any kind of state, most probably is not an Actor.

Akka Actors provide concurrency safety in regards of their state, meaning, it can be modified without worrying about concurrency issues.

What is an Actor? - Behavior

A behavior is how an actor handles messages. In the end, it is a function that takes a message as an argument and performs some given actions accordingly.

An actor's behavior can be dynamically changed.

What is an Actor? - Mailbox

All messages sent to an Actor are first stored in their mailbox until they can be processed.

One can tune the actor by choosing different types of Mailboxes.

What is an Actor? - Children

Optionally, an Actor can create children to delegate subtasks to them. Unlike in real life, their lifetime is controlled by the parent.

What is an Actor? - Supervision Strategy

Set of rules that define how to react in front of exceptions:

  • Resume
  • Restart
  • Stop

What is an Actor? - ActorRef

An ActorRef is the "address we send the messages". It encapsulates the internals of an actor and it's their external representation.

When should I use Actors?

If you can solve your problem with a Future, probably you won't need Actors.

When should I use Actors?

Nowadays, Actors are the lowest level of abstraction on the Akka ecosystem. There might be higher abstractions that would fit better to your use case.

For example Akka Streams and Akka HTTP.

When should I use Actors?

  • More than one Actor
  • Actors have State
  • Actors talk to each other

Which Actor style to choose?

Classic Akka Actors


					type Receive = PartialFunction[Any, Unit]
				

The main criticism to Akka Actors has always been the lack of any types on their Actors.

Explicit State

import akka.actor.{Actor, Props}
import io.github.jlprat.akka.lnl.intro.classic.MiniExample.{Click, RetrieveClicks}

object MiniExample {
  sealed trait Command
  case object Click extends Command
  case object RetrieveClicks extends Command

  def props(): Props = Props(classOf[MiniExample])
}

class MiniExample extends Actor {

  var clicks: Long = 0

  override def receive: Actor.Receive = {
    case Click => clicks = clicks + 1
    case RetrieveClicks => sender() ! clicks
  }
}					
				

Changing Behavior

import akka.actor.{Actor, Props}
import io.github.jlprat.akka.lnl.intro.classic.MiniExampleBecome.{Click, RetrieveClicks}

object MiniExampleBecome {
  sealed trait Command
  case object Click extends Command
  case object RetrieveClicks extends Command

  def props(): Props = Props(classOf[MiniExampleBecome])
}

class MiniExampleBecome extends Actor {

  override def receive: Actor.Receive = clickCounting(0)

  private def clickCounting(count: Long): Actor.Receive = {
    case Click => context.become(clickCounting(count + 1))
    case RetrieveClicks => sender() ! count
  }
}
				

Akka Typed

Since Akka 2.6.x a new type of Actors is available and production ready.

Akka Typed

import akka.actor.typed.{ActorRef, Behavior}
import akka.actor.typed.scaladsl.Behaviors

object MiniExample {

  sealed trait Command
  case object Click extends Command
  case class RetrieveClicks(replyTo: ActorRef[Long]) extends Command

  def apply(): Behavior[Command] = counting(0)

  private def counting(count: Long): Behavior[Command] =
    Behaviors.receiveMessage {
      case Click => counting(count + 1)
      case RetrieveClicks(replyTo) =>
        replyTo ! count
        Behaviors.same
    }
}
				

How do I test Actors?

There are two different modes for testing: Synchronous and Asynchronous.

Typically asynchronous testing is the preferred one, leaving synchronous testing for the pure unit tests.

Why Asynchronous?

It replicates a "live environment" and offers out of the box probes and mocking capabilities. It works for advanced Akka features like Timers and Clustering.

Why Synchronous?

On Akka Typed it's independent from the ActorSystem and is useful to test Actors in isolation.

Why Synchronous?

On Akka Classic, this type of testing is not actively encouraged, but it's still useful to check the side effects caused by the processing of a message.

Let's see some examples!

Repository

Thanks! And leave feedback!

Write Feedback!

Josep Prat  GitHub Logo - 2020/09/08