#!/usr/bin/env amm import $ivy.`com.typesafe.akka::akka-actor-typed:2.6.8` import $ivy.`ch.qos.logback:logback-classic:1.2.3` import akka.actor.typed.delivery.ConsumerController.Command import akka.actor.Actor import akka.actor.typed.ActorRef import akka.actor.typed.ActorSystem import akka.actor.typed.Behavior import akka.actor.typed.scaladsl.Behaviors import akka.util.Timeout import scala.concurrent.duration._ import akka.actor.typed.scaladsl.AskPattern._ import scala.concurrent.ExecutionContext.Implicits.global import akka.actor.typed.scaladsl.AbstractBehavior import akka.actor.typed.scaladsl.ActorContext import scala.util.Success import scala.util.Failure import scala.concurrent.Await import scala.concurrent.Future object CounterActor { final case class CounterResult(count: Int) sealed trait Command final case object IncCount extends Command final case class GetResult(sender: ActorRef[CounterResult]) extends Command def apply(): Behavior[Command] = Behaviors.setup(ctx => new CounterActor(ctx)) private class CounterActor(context: ActorContext[Command]) extends AbstractBehavior[Command](context) { private var counter = 0 // encapsulated mutable state override def onMessage(msg: Command): Behavior[Command] = { msg match { case IncCount => counter += 1 Behaviors.same case GetResult(sender) => context.log.info(s"Value of counter is $counter"); sender ! CounterResult(counter) Behaviors.same } } } } object RootActor { sealed trait Command final case class Reply[T](reply: T) extends Command final case object Begin extends Command final case class GetResult(repyTo: ActorRef[CounterActor.CounterResult]) extends Command implicit val timeout: Timeout = 3.seconds def apply(): Behavior[Command] = Behaviors.setup { context => implicit val system = context.system val counterActor = context.spawn(CounterActor(), "counterActor") Behaviors.receiveMessage { message => message match { case Reply(reply) => context.log.info(s"Received message $message") case Begin => context.log.info("--- Beginning ---") counterActor ! CounterActor.IncCount counterActor ! CounterActor.IncCount counterActor ! CounterActor.IncCount counterActor ! CounterActor.IncCount counterActor ! CounterActor.IncCount case GetResult(replyTo) => counterActor ! CounterActor.GetResult( replyTo ) } Behaviors.same } } } @main def main() = { implicit val system = ActorSystem(RootActor(), "TestActors") implicit val timeout: Timeout = 3.seconds system ! RootActor.Begin // system ! RootActor.GetResult val x: Future[CounterActor.CounterResult] = system ? (ref => RootActor.GetResult(ref)) Await.result(x, 1.second) }