作为演员遇到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
    }
  }
}