Scala Akka Actor - Dead Letters encountered

1408 views scala
10

I am using Scala with Akka actors. I know that an actor has a mailbox. So any communication with the actor is serialized. I have an actor that does a certain job--say it downloads an image.

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)
      }
  }
}

As you can see, the actor downloads the image in an async fashion. imageDownloadService.downloadImage returns a Future on whose completion a message is sent to the sender. Now this is where I get the dead letters encountered message.

Where have I gone wrong?

answered question

did you check whether the sender session is already terminated? and can we see the implementation of your Actor reference ? because Dead Letter cause when then Actor reference for Parent Actor is already terminated.

1 Answer

4

Don't know if any other problem, but the method you use sender in Future is wrong, you need to assign it to a new variable, then combine the onComplete callback it forms a closure which will not be override by other actor handle.

In your code, need to add lineA, and replace lineB, lineC with lineD, lineE. Or you may want to have a look for pipeTo function of Future.

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
    }
  }
}

posted this

Have an answer?

JD

Please login first before posting an answer.