Search code examples
akkaakka-persistence

akka persistence, resume on failure, at least once semantics


I have small mess in my head Avoid having poisoned mailbox http://doc.akka.io/docs/akka/2.4.2/general/supervision.html

The new actor then resumes processing its mailbox, meaning that the restart is not visible outside of the actor itself with the notable exception that the message during which the failure occurred is not re-processed.

My case: actor receives the "command" to run smth. Actor tries to reach remote service. Service is unavailable. Exception is thrown. I want actor to keep going contact remote server. I don't wan't actor to skip input command which caused exception. Will Resume help me to force actor to keep going?

override val supervisorStrategy: SupervisorStrategy =
    OneForOneStrategy(maxNrOfRetries = -1, withinTimeRange = 5.minutes) {
      case _: RemoteServiceIsDownException => Resume
      case _ => Stop
    }

By Resume, I mean retry the invocation that caused the exception to be thrown. I suspect that akka Resume means keep actor instance, but not retry failed invocation

Does akka persistence means durable mailboxes?

Extending first case. Actor tries to reach remote service. Now actor is persistent. SupervisorStrategy forces Actor to continue to contact remote service. The whole JVM shuts down. Akka app is restarted. Will Actor Resume from the point where it tired desperately reach remote service?

Does akka persistence means At least once semantics?

Actor receives message. Then JVM crashes. Will parent re-receive message it was processing during crush?


Solution

  • Expanding my comment:

    Will Resume help me to force actor to keep going? ... By Resume, I mean retry the invocation that caused the exception to be thrown. I suspect that akka Resume means keep actor instance, but not retry failed invocation

    No, I do not believe so. The Resume directive will keep the actor chugging along after your message processing failure. One way to retry the message though, is to actually just use Restart and to take advantage of an Actor's preRestart hook:

    override def preRestart(t: Throwable, msgBeforeFailure: Option[Any]): Unit = {
      case t: RemoteServiceIsDownException if msgBeforeFailure.isDefined =>
         self ! msgBeforeFailure.get
      case _: =>
    }
    

    When the actor crashes, it will run this hook and offer you an opportunity to handle the message that caused it to fail.

    Does akka persistence means durable mailboxes?

    Not necessarily, using a persistent actor just means that the actor's domain events, and subsequently, internal state is durable, not the mailbox it uses to process messages. That being said, it is possible to implement a durable mailbox pretty easily, see below.

    Does akka persistence means At least once semantics?

    Again not necessarily, but the toolkit does have a trait called AtleastOnceDelivery to let you achieve this (and durable mailbox)!

    See http://doc.akka.io/docs/akka/current/scala/persistence.html#At-Least-Once_Delivery