作为演员遇到Scala - Dead Letters
Scala Akka Actor - Dead Letters encountered
我正在使用 Scala 和 Akka 演员。我知道演员有邮箱。所以与演员的任何交流都是序列化的。我有一个 actor 做某项工作——比如下载图像。
class DownloadImageActor(implicit val injector: Injector) extends Actor with Injectable {
val imageDownloadService = inject[ImageDownloadService]
implicit val ec = inject[ExecutionContext]
override def receive: Receive = {
case DownloadImage(jobId, imageUrl) =>
imageDownloadService.downloadImage(imageUrl).onComplete {
case Success(image) =>
sender() ! ImageDownloadSuccess(imageUrl, image, jobId)
case Failure(e) =>
sender() ! ImageDownloadFail(imageUrl, e, jobId)
}
}
}
如您所见,演员以异步方式下载图像。 imageDownloadService.downloadImage
returns 一个 Future
完成后向发件人发送一条消息。现在这是我收到 dead letters encountered
消息的地方。
我哪里做错了?
编辑 #1
向下载 actor 发送消息的父 actor
class ParentActor(implicit val injector : Injector) extends Actor with Injectable {
val downloadImageActor = inject[ActorRef](identified by "ImageDownloadActor")
override def receive: Receive = {
case DownloadImages(urls, _id) => urls.foreach(url =>
downloadImageActor ! DownloadImage(id, imageUrl = url)
)
case ImageDownloadSuccess(image : Image) =>
}
}
不知道有没有其他问题,但是你在Future
中使用sender
的方法是错误的,你需要将它赋值给一个新的变量,然后结合onComplete
回调它形成一个不会被其他参与者句柄覆盖的闭包。
在您的代码中,需要添加lineA,并将lineB、lineC替换为lineD、lineE。或者您可能想查看 Future.
的 pipeTo
函数
class DownloadImageActor(implicit val injector : Injector) extends Actor with Injectable{
val imageDownloadService = inject[ImageDownloadService]
implicit val ec = inject[ExecutionContext]
override def receive: Receive = {
case DownloadImage(jobId, imageUrl) =>
val client = sender // lineA
imageDownloadService.downloadImage(imageUrl).onComplete {
//case Success(image) => sender() ! ImageDownloadSuccess(imageUrl, image, jobId) // lineB
//case Failure(e) => sender() ! ImageDownloadFail(imageUrl,e, jobId) // lineC
case Success(image) => client ! ImageDownloadSuccess(imageUrl, image, jobId) // lineD
case Failure(e) => client ! ImageDownloadFail(imageUrl,e, jobId) // lineE
}
}
}
我正在使用 Scala 和 Akka 演员。我知道演员有邮箱。所以与演员的任何交流都是序列化的。我有一个 actor 做某项工作——比如下载图像。
class DownloadImageActor(implicit val injector: Injector) extends Actor with Injectable {
val imageDownloadService = inject[ImageDownloadService]
implicit val ec = inject[ExecutionContext]
override def receive: Receive = {
case DownloadImage(jobId, imageUrl) =>
imageDownloadService.downloadImage(imageUrl).onComplete {
case Success(image) =>
sender() ! ImageDownloadSuccess(imageUrl, image, jobId)
case Failure(e) =>
sender() ! ImageDownloadFail(imageUrl, e, jobId)
}
}
}
如您所见,演员以异步方式下载图像。 imageDownloadService.downloadImage
returns 一个 Future
完成后向发件人发送一条消息。现在这是我收到 dead letters encountered
消息的地方。
我哪里做错了?
编辑 #1
向下载 actor 发送消息的父 actor
class ParentActor(implicit val injector : Injector) extends Actor with Injectable {
val downloadImageActor = inject[ActorRef](identified by "ImageDownloadActor")
override def receive: Receive = {
case DownloadImages(urls, _id) => urls.foreach(url =>
downloadImageActor ! DownloadImage(id, imageUrl = url)
)
case ImageDownloadSuccess(image : Image) =>
}
}
不知道有没有其他问题,但是你在Future
中使用sender
的方法是错误的,你需要将它赋值给一个新的变量,然后结合onComplete
回调它形成一个不会被其他参与者句柄覆盖的闭包。
在您的代码中,需要添加lineA,并将lineB、lineC替换为lineD、lineE。或者您可能想查看 Future.
的pipeTo
函数
class DownloadImageActor(implicit val injector : Injector) extends Actor with Injectable{
val imageDownloadService = inject[ImageDownloadService]
implicit val ec = inject[ExecutionContext]
override def receive: Receive = {
case DownloadImage(jobId, imageUrl) =>
val client = sender // lineA
imageDownloadService.downloadImage(imageUrl).onComplete {
//case Success(image) => sender() ! ImageDownloadSuccess(imageUrl, image, jobId) // lineB
//case Failure(e) => sender() ! ImageDownloadFail(imageUrl,e, jobId) // lineC
case Success(image) => client ! ImageDownloadSuccess(imageUrl, image, jobId) // lineD
case Failure(e) => client ! ImageDownloadFail(imageUrl,e, jobId) // lineE
}
}
}