1 - triagedhelp wantedt:docs
倉庫指標
- Star
- (13,277 star)
- PR 合併指標
- (平均合併 8天 19小時) (30 天內合併 10 個 PR)
描述
akka version: 2.6.4
I am changing an actor in my project from classic to typed, and run into a weird issue regarding ask between classic and typed actors.
Currently, I have 2 classic actors: Pinger and Ponger. Ponger does only 1 thing: echo back the id and a fixed value 0. Pinger will ping the Ponger on load.
import akka.actor.Scheduler
import akka.actor.typed.scaladsl.Behaviors
import akka.actor.typed.scaladsl.adapter._
import akka.actor.typed.{ActorRef, ActorSystem, Behavior}
import akka.pattern.{RetrySupport, ask, pipe}
import akka.util.Timeout
import akka.{actor => classic}
import scala.concurrent.ExecutionContext
import scala.concurrent.duration._
import scala.util.Random
object ClassicAskClassic extends App {
val system: classic.ActorSystem = classic.ActorSystem("ClassicAskClassic")
val ponger = system.actorOf(classic.Props(new Ponger()), "Ponger")
val pinger =
system.actorOf(classic.Props(new Pinger(ponger)), "Pinger")
class Pinger(ponger: classic.ActorRef)
extends classic.Actor
with classic.ActorLogging
with RetrySupport {
override def preStart(): Unit = {
super.preStart()
self ! Pinger.Initialize
}
override def receive: Receive = {
case Pinger.Initialize =>
implicit val timeout: Timeout = Timeout(1.second)
implicit val scheduler: Scheduler = context.system.scheduler
implicit val ec: ExecutionContext = context.dispatcher
retry(
() => {
val id = (new Random).nextInt(1000)
log.info(s"Ping id=$id!")
ponger.ask(Ponger.Ping(id)).mapTo[Ponger.Pong]
},
10,
1.second
).pipeTo(self)
case Ponger.Pong(id, v) =>
log.info(s"Got a Pong id=$id, v=$v!")
log.info("=========================")
}
}
class Ponger extends classic.Actor with classic.ActorLogging {
override def receive: Receive = {
case Ponger.Ping(id) =>
sender() ! Ponger.Pong(id, 0)
}
}
object Pinger {
case object Initialize
}
object Ponger {
case class Ping(id: Int)
case class Pong(id: Int, v: Int)
}
}
Run the program, the console output is like:
18:18:44.994 [ClassicAskClassic-akka.actor.default-dispatcher-5] INFO akkaactors.ClassicAskClassic$Pinger - Ping id=45!
18:18:44.997 [ClassicAskClassic-akka.actor.default-dispatcher-5] INFO akkaactors.ClassicAskClassic$Pinger - Got a Pong id=45, v=0!
18:18:44.998 [ClassicAskClassic-akka.actor.default-dispatcher-5] INFO akkaactors.ClassicAskClassic$Pinger - =========================
This is expected: the ask succeeds in one attempt, and that's it.
However, if I switch the Ponger into typed actor, the behavior becomes weird:
import akka.actor.Scheduler
import akka.actor.typed.scaladsl.Behaviors
import akka.actor.typed.scaladsl.adapter._
import akka.actor.typed.{ActorRef, ActorSystem, Behavior}
import akka.pattern.{RetrySupport, ask, pipe}
import akka.util.Timeout
import akka.{actor => classic}
import scala.concurrent.ExecutionContext
import scala.concurrent.duration._
import scala.util.Random
object ClassicAskTyped extends App {
val system: classic.ActorSystem = classic.ActorSystem("ClassicAskTyped")
val typedSystem: ActorSystem[Nothing] = system.toTyped
val ponger = system.spawn(Ponger(), "Ponger")
val pinger =
system.actorOf(classic.Props(new Pinger(ponger.toClassic)), "Pinger")
class Pinger(ponger: classic.ActorRef)
extends classic.Actor
with classic.ActorLogging
with RetrySupport {
override def preStart(): Unit = {
super.preStart()
self ! Pinger.Initialize
}
override def receive: Receive = {
case Pinger.Initialize =>
implicit val timeout: Timeout = Timeout(1.second)
implicit val scheduler: Scheduler = context.system.scheduler
import akka.actor.typed.scaladsl.adapter._
implicit val ec: ExecutionContext = context.dispatcher
retry(
() => {
val id = (new Random).nextInt(1000)
log.info(s"Ping id=$id!")
ponger.ask(Ponger.Ping(id, self)).mapTo[Ponger.Pong]
},
10,
1.second
).pipeTo(self)
case Ponger.Pong(id, v) =>
log.info(s"Got a Pong id=$id, v=$v!")
log.info("=========================")
}
}
object Pinger {
case object Initialize
}
object Ponger {
def apply(): Behavior[Command] = {
Behaviors.receive { (context, message) =>
message match {
case Ping(id, replyTo) =>
context.log.info(s"Processing Ping id=$id!")
replyTo ! Pong(id, 0)
Behaviors.same
}
}
}
sealed trait Command
sealed trait Reply
case class Ping(id: Int, replyTo: ActorRef[Reply]) extends Command
case class Pong(id: Int, v: Int) extends Reply
private case class Set(v: Int) extends Command
}
}
The console output:
18:26:52.557 [ClassicAskTyped-akka.actor.default-dispatcher-6] INFO akkaactors.ClassicAskTyped$Pinger - Ping id=206!
18:26:52.561 [ClassicAskTyped-akka.actor.default-dispatcher-5] INFO akkaactors.ClassicAskTyped$Ponger$ - Processing Ping id=206!
18:26:52.562 [ClassicAskTyped-akka.actor.default-dispatcher-5] INFO akkaactors.ClassicAskTyped$Pinger - Got a Pong id=206, v=0!
18:26:52.562 [ClassicAskTyped-akka.actor.default-dispatcher-5] INFO akkaactors.ClassicAskTyped$Pinger - =========================
18:26:54.593 [ClassicAskTyped-akka.actor.default-dispatcher-6] INFO akkaactors.ClassicAskTyped$Pinger - Ping id=356!
18:26:54.593 [ClassicAskTyped-akka.actor.default-dispatcher-4] INFO akkaactors.ClassicAskTyped$Ponger$ - Processing Ping id=356!
18:26:54.593 [ClassicAskTyped-akka.actor.default-dispatcher-4] INFO akkaactors.ClassicAskTyped$Pinger - Got a Pong id=356, v=0!
18:26:54.593 [ClassicAskTyped-akka.actor.default-dispatcher-4] INFO akkaactors.ClassicAskTyped$Pinger - =========================
18:26:56.634 [ClassicAskTyped-akka.actor.default-dispatcher-6] INFO akkaactors.ClassicAskTyped$Pinger - Ping id=374!
18:26:56.634 [ClassicAskTyped-akka.actor.default-dispatcher-4] INFO akkaactors.ClassicAskTyped$Ponger$ - Processing Ping id=374!
18:26:56.635 [ClassicAskTyped-akka.actor.default-dispatcher-4] INFO akkaactors.ClassicAskTyped$Pinger - Got a Pong id=374, v=0!
18:26:56.635 [ClassicAskTyped-akka.actor.default-dispatcher-4] INFO akkaactors.ClassicAskTyped$Pinger - =========================
18:26:58.673 [ClassicAskTyped-akka.actor.default-dispatcher-6] INFO akkaactors.ClassicAskTyped$Pinger - Ping id=375!
18:26:58.673 [ClassicAskTyped-akka.actor.default-dispatcher-4] INFO akkaactors.ClassicAskTyped$Ponger$ - Processing Ping id=375!
18:26:58.673 [ClassicAskTyped-akka.actor.default-dispatcher-4] INFO akkaactors.ClassicAskTyped$Pinger - Got a Pong id=375, v=0!
18:26:58.673 [ClassicAskTyped-akka.actor.default-dispatcher-4] INFO akkaactors.ClassicAskTyped$Pinger - =========================
18:27:00.712 [ClassicAskTyped-akka.actor.default-dispatcher-4] INFO akkaactors.ClassicAskTyped$Ponger$ - Processing Ping id=402!
18:27:00.712 [ClassicAskTyped-akka.actor.default-dispatcher-6] INFO akkaactors.ClassicAskTyped$Pinger - Ping id=402!
18:27:00.713 [ClassicAskTyped-akka.actor.default-dispatcher-6] INFO akkaactors.ClassicAskTyped$Pinger - Got a Pong id=402, v=0!
18:27:00.713 [ClassicAskTyped-akka.actor.default-dispatcher-6] INFO akkaactors.ClassicAskTyped$Pinger - =========================
18:27:02.754 [ClassicAskTyped-akka.actor.default-dispatcher-6] INFO akkaactors.ClassicAskTyped$Ponger$ - Processing Ping id=729!
18:27:02.754 [ClassicAskTyped-akka.actor.default-dispatcher-4] INFO akkaactors.ClassicAskTyped$Pinger - Ping id=729!
18:27:02.754 [ClassicAskTyped-akka.actor.default-dispatcher-4] INFO akkaactors.ClassicAskTyped$Pinger - Got a Pong id=729, v=0!
18:27:02.754 [ClassicAskTyped-akka.actor.default-dispatcher-4] INFO akkaactors.ClassicAskTyped$Pinger - =========================
18:27:04.793 [ClassicAskTyped-akka.actor.default-dispatcher-4] INFO akkaactors.ClassicAskTyped$Ponger$ - Processing Ping id=406!
18:27:04.793 [ClassicAskTyped-akka.actor.default-dispatcher-5] INFO akkaactors.ClassicAskTyped$Pinger - Ping id=406!
18:27:04.794 [ClassicAskTyped-akka.actor.default-dispatcher-5] INFO akkaactors.ClassicAskTyped$Pinger - Got a Pong id=406, v=0!
18:27:04.794 [ClassicAskTyped-akka.actor.default-dispatcher-5] INFO akkaactors.ClassicAskTyped$Pinger - =========================
18:27:06.833 [ClassicAskTyped-akka.actor.default-dispatcher-5] INFO akkaactors.ClassicAskTyped$Ponger$ - Processing Ping id=663!
18:27:06.833 [ClassicAskTyped-akka.actor.default-dispatcher-6] INFO akkaactors.ClassicAskTyped$Pinger - Ping id=663!
18:27:06.833 [ClassicAskTyped-akka.actor.default-dispatcher-6] INFO akkaactors.ClassicAskTyped$Pinger - Got a Pong id=663, v=0!
18:27:06.833 [ClassicAskTyped-akka.actor.default-dispatcher-6] INFO akkaactors.ClassicAskTyped$Pinger - =========================
18:27:08.871 [ClassicAskTyped-akka.actor.default-dispatcher-5] INFO akkaactors.ClassicAskTyped$Pinger - Ping id=646!
18:27:08.871 [ClassicAskTyped-akka.actor.default-dispatcher-4] INFO akkaactors.ClassicAskTyped$Ponger$ - Processing Ping id=646!
18:27:08.872 [ClassicAskTyped-akka.actor.default-dispatcher-4] INFO akkaactors.ClassicAskTyped$Pinger - Got a Pong id=646, v=0!
18:27:08.872 [ClassicAskTyped-akka.actor.default-dispatcher-4] INFO akkaactors.ClassicAskTyped$Pinger - =========================
18:27:10.913 [ClassicAskTyped-akka.actor.default-dispatcher-6] INFO akkaactors.ClassicAskTyped$Ponger$ - Processing Ping id=521!
18:27:10.913 [ClassicAskTyped-akka.actor.default-dispatcher-5] INFO akkaactors.ClassicAskTyped$Pinger - Ping id=521!
18:27:10.914 [ClassicAskTyped-akka.actor.default-dispatcher-6] INFO akkaactors.ClassicAskTyped$Pinger - Got a Pong id=521, v=0!
18:27:10.914 [ClassicAskTyped-akka.actor.default-dispatcher-6] INFO akkaactors.ClassicAskTyped$Pinger - =========================
18:27:12.952 [ClassicAskTyped-akka.actor.default-dispatcher-4] INFO akkaactors.ClassicAskTyped$Pinger - Ping id=944!
18:27:12.952 [ClassicAskTyped-akka.actor.default-dispatcher-5] INFO akkaactors.ClassicAskTyped$Ponger$ - Processing Ping id=944!
18:27:12.953 [ClassicAskTyped-akka.actor.default-dispatcher-5] INFO akkaactors.ClassicAskTyped$Pinger - Got a Pong id=944, v=0!
18:27:12.953 [ClassicAskTyped-akka.actor.default-dispatcher-5] INFO akkaactors.ClassicAskTyped$Pinger - =========================
18:27:13.981 [ClassicAskTyped-akka.actor.default-dispatcher-5] INFO akka.actor.RepointableActorRef - Message [akka.actor.Status$Failure] from Actor[akka://ClassicAskTyped/user/Pinger#1224703828] to Actor[akka://ClassicAskTyped/user/Pinger#1224703828] was unhandled. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
It runs out of 10 retries.
Can anyone help? Thx