Akka - resending the “breaking” message

2020-07-01 11:32发布

问题:

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