23
votes

In the official akka 2.0.4 docs it says:

An actor restart replaces only the actual actor object; the contents of the mailbox is unaffected by the restart, so processing of messages will resume after the postRestart hook returns. The message that triggered the exception will not be received again. Any message sent to an actor while it is being restarted will be queued to its mailbox as usual.

Let's say I have a message that caused my actor to restart. It isn't in the mailbox anymore, so it won't be processed by the actor that will take it's place. If I want this message to be processed by the actor anyways (assuming the order doesn't matter in that case), would it be a bad idea for the actor to send the message to themself on restart?

Some (pseudo)code to show what I mean:

class ResendingActor extends Actor {
  var curMessage: Option[MyMessage] = None
  def receive = {
    case MyMessage(x) => {
      curMessage = Some(MyMessage(x))
      /* processing */
      curMessage = None
    }
  }
  override def preRestart(reason: Throwable, message: Option[Any]) {
    curMessage match {
      case Some(x) => self ! x
      case None => ;
    }
  }
}

This way the message that wasn't processed by the actor before it got restarted is pushed to the end of the queue for the new actor.

So my question is: Is there any reason I shouldn't be doing this?

The only thing I can think of is that if the message is for some reason malformed, it will never leave the system and cause the actor to be restarted regularly...

1
You are right in your last assumption, redelivering the same message over and over is one of the problems, known as a poison message.Tomasz Nurkiewicz
Assuming your error handling is complete enough that any such message would be unexpected (and not a known edge case), I think the better solution is to log the message so it can be manually inspected, and not attempt to re-process it. Otherwise you should be able to handle the message without crashing the actor.Dan Simon

1 Answers

17
votes

You already get the failing message in preRestart (see: message: Option[Any]) so no need to stash it away yourself. And yes, it is perfectly fine to re-send it to yourself, but beware of infinite restarts in combination with this since you'll most likely end up with a message that will never be discarded.