This is the note of the Akka actor development. It is based on the Akka Actors documents.

Style Guide

  • Prefer functional style actor because of immutable state and stateless behavior.
  • Use enclosing class and parameter class to avoid too many parameters.
  • Create initial behavior in a factory method in the companion object. The factory method is a good place to retrieving resoruces like Behaviors.withItmers, Behaviors.withStash and ActorContext with Behaviors.setup.
  • Define messages in the companion object.
  • Use the companion object name as message prefix when use it outside tha actor.
  • Use replyTo for ActorRef[Reply] for reply/ack message parameter.
  • Use sealed treat Command as the name for incoming commands.
  • Use past tense for events.
  • Use ask, not ?.
  • To use exhaustive checking, don’t use case guards.

Lifecycle

The ActorContext is passed by Behaviors.setup and can be used to

  • spawn child actors
  • watch Terminated signal of other actors
  • log
  • create message adapters
  • ask another actor
  • access to the self ActorRef

The ActorContext is not thread safe therefore don’t use it in Future or shared with other actors. Only use it the normal message processing thred.

The SpawnProtocol implements a predefined message protocol to spawn new actors. The spawnProtocol.ask(SpawnProtocol.Spawn(...)) returns a Future[ActorRefe[_]].

An actor can be stop in one of three ways: call Behaviors.stopped by itself, context.stop(child) by its parent, parent stops.

Use context.watch or context.watchWith(customMessage) to watch an actor when the actor stops.

Interaction

The fundamental way to interact with an actor is through “tell”, a fire and forget pattern.

Based on the fire and forget pattern, it is easy to have a request-response pattern.

For 1:1 mapping between a request and a response, use tha ask pattern. The context.ask() uses an implicit timeout.

When accessing APIs that returning Future, such as a database or an external service, use context.pipeToSelf(futureResult). It is the “send future result to self” pattern.

Use “per session child actor” to cases that there are multiple tasks from other actors. The sessoin child actor contains logic to implement retrying, failing on timeout, progress inspection etc. The session child actor stops when all tasks are done.

Fault Tolerance

Supervision declaratively describes what should happen when certain type of excetpion are thrown inside an actor. The default strategy is to stop the actor.

The strategies include restart, resume, stop, restart with number of tries and a time range.

To handle different exceptions, use nested supervise calls.

By default, when a parent restarts, its children stop. To avoid it, use SupervisorStrategy.restart.withStopChildren(false).

Before a supervised actor is restarted, it sents the PreRestart signal and the behavior returned from the signal handling is ignored.

When a child is stopped because of failure, the ChildSignal, a subclass of Terminated will be received by its parent. If a parent doesn’t handle the Terminated message, it will fail with an DeathPactException.

Actor Discovery

Actor refs are obtained either by creating actors or using the Receptionist. The actor references can be used as constructor parameters or part of messages.

Actors regist to local Receptionist with a key. The registry of actor references is propagated to all cluster nodes via distributed data. Use Find to get a Listing that contains a set of actor references for a key. The registry is dynamic therefore you can subscribe to changes of a key.

Routers

A router is also a behavior. It forwards any received messages to one final recipient of a set of routees. Akka includes two kinds of routers: the pool router and the group router.

User context.spawn(Routers.pool(poolSize)...) to create a pool of routee with a size and a supviser strategy, usually restart.

The group router is created with a ServiceKey and uses the receptionist to discover available actors for that key and routes messages to one actor for a key.

There are two routing strategies: round robin (the default) and random.

Stash

Stash messages to a buffer when an actor cannot or should not handle messages using the current behavior, for example when loading from db or saving to db. When it is ready, use StashBuffer.unstash to resume processing.

Mailbox

Teh defaul mailbox is unbounded SingleConsumerOnlyUnboundedMailbox. Other mailboxes include bounded and priority mailboxes.