Umgang mit Fehlern in Akka-Darstellern
Ich habe ein sehr einfaches Beispiel, wo ich einen Schauspieler habe (SimpleActor
), die eine periodische Aufgabe ausführen, indem sie eine Nachricht an sich selbst senden. Die Nachricht wird im Konstruktor für den Akteur eingeplant. Im Normalfall (d. H. Ohne Fehler) funktioniert alles einwandfrei.
Aber was ist, wenn der Schauspieler mit Fehlern umgehen muss? Ich habe einen anderen Schauspieler (SimpleActorWithFault
). Dieser Schauspieler könnte Fehler haben. In diesem Fall generiere ich selbst eine Ausnahme. Wenn ein Fehler auftritt (d. H.SimpleActorWithFault
löst eine Ausnahme aus) wird automatisch neu gestartet. Dieser Neustart bringt jedoch den Scheduler im Actor durcheinander, der nicht mehr wie vorgesehen funktioniert. Und wenn die Fehler schnell genug auftreten, führt dies zu unerwartetem Verhalten.
Meine Frage ist, wie in solchen Fällen mit Fehlern umgegangen werden soll. Ich weiß, dass ich es gebrauchen kannTry
Blöcke zur Behandlung von Ausnahmen. Aber was ist, wenn ich einen anderen Schauspieler verlängere, bei dem ich keinen Versuch in die Superklasse stecken kann, oder in einem Fall, bei dem ich einen Ausnahmefehler im Schauspieler habe?
import akka.actor.{Props, ActorLogging}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import akka.actor.Actor
case object MessageA
case object MessageToSelf
class SimpleActor extends Actor with ActorLogging {
//schedule a message to self every second
context.system.scheduler.schedule(0 seconds, 1 seconds, self, MessageToSelf)
//keeps track of some internal state
var count: Int = 0
def receive: Receive = {
case MessageA => {
log.info("[SimpleActor] Got MessageA at %d".format(count))
}
case MessageToSelf => {
//update state and tell the world about its current state
count = count + 1
log.info("[SimpleActor] Got scheduled message at %d".format(count))
}
}
}
class SimpleActorWithFault extends Actor with ActorLogging {
//schedule a message to self every second
context.system.scheduler.schedule(0 seconds, 1 seconds, self, MessageToSelf)
var count: Int = 0
def receive: Receive = {
case MessageA => {
log.info("[SimpleActorWithFault] Got MessageA at %d".format(count))
}
case MessageToSelf => {
count = count + 1
log.info("[SimpleActorWithFault] Got scheduled message at %d".format(count))
//at some point generate a fault
if (count > 5) {
log.info("[SimpleActorWithFault] Going to throw an exception now %d".format(count))
throw new Exception("Excepttttttiooooooon")
}
}
}
}
object MainApp extends App {
implicit val akkaSystem = akka.actor.ActorSystem()
//Run the Actor without any faults or exceptions
akkaSystem.actorOf(Props(classOf[SimpleActor]))
//comment the above line and uncomment the following to run the actor with faults
//akkaSystem.actorOf(Props(classOf[SimpleActorWithFault]))
}