Akka Typedを試してみる

MEAPが開始してから丸4年、Akka in Actionがようやく完成したそうです。

完成版のPDFをパラ見していたところ、最後の16章にこれから入る予定の新機能の解説があり、その中でAkka Typedが取り上げられていたので少し試してみました。

Akka TypedはAkkaのアクターが返すメッセージを型安全に扱うためのものです。

まずはAkka Typedを使わずに普通にアクターを実装してみます。以下は受信したメッセージに反応して送信元にメッセージを返却する簡単なアクターです。

import akka.actor._
import akka.pattern.ask
import akka.util.Timeout
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

object Hello {
  final case class HelloMessage(name: String)
  final case class HelloResult(message: String)

  class HelloActor extends Actor {
    def receive = {
      case HelloMessage(name) => sender ! HelloResult(s"Hello $name!")
    }
  }
}

implicit val timeout = Timeout(5 seconds)

val system = ActorSystem("system")
val actor = system.actorOf(Props[Hello.HelloActor])
val f: Future[Any] = actor ? Hello.HelloMessage("Naoki")

f.mapTo[Hello.HelloResult].foreach { result =>
  println(result.message)
}

アクターに?で問い合わせた結果の型がFuture[Any]になっており、mapToで返却されるメッセージの型にキャストしています。この部分を型安全にしようというのがAkka Typedです。

同じ処理をAkka Typedで書き直してみます。

import akka.typed._
import akka.typed.ScalaDSL._
import akka.typed.AskPattern._
import akka.util.Timeout
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

object TypedHello {
  final case class HelloMessage(name: String, replyTo: ActorRef[HelloResult])
  final case class HelloResult(message: String)

  val helloBahavior = ContextAware[HelloMessage] { ctx =>
    Static {
      case HelloMessage(name, replyTo) => replyTo ! HelloResult(s"Hello $name!")
    }
  }
}

implicit val timeout = Timeout(5 seconds)

val system: ActorSystem[TypedHello.HelloMessage] = ActorSystem("system", Props(TypedHello.helloBahavior))
val f: Future[Hello.HelloResult] = system ? (TypedHello.HelloMessage("Naoki", _: ActorRef[TypedHello.HelloResult]))

f.foreach { result =>
  println(result.message)
}

ちょっとわかりにくいんですが、アクターの中で行っていた処理はContextAwareの中で行うようになっており、送信メッセージに返信先の型付きActorRefを持たせ、その返信先アクターに対してメッセージを送信するようになっています。ActorSystemActorRef?メソッドなどはAkka標準のものではなくAkka Typedが提供するものを使用することで型安全になるようになっています。

個人的には効果の割に修正が多くてちょっと厳しいかなという気がします。Akka in Actionにも「型安全のメリットは大きいので将来的にAkka Typedが重要なモジュールになる可能性はあるけど、今後大きく変更する可能性があるからまだプロダクションで使うべきではない」というようなことが書かれていました。

Akka in Action

Akka in Action

16章にはAkka Typedの他にAkka Streams、Akka HTTP、Akka Distributed Dataがちょっとずつですが紹介されています。

しかしこの本、完成するまで4年かかったのか…。4年…。