Правильный способ обработки исключений при использовании актеров Akka - PullRequest
0 голосов
/ 17 января 2019

Я пытаюсь правильно обработать исключения в моих проектах Akka с помощью супервизоров. Просто хотел убедиться, что это правильный подход к вещам. У меня есть 1 система актеров, которая создает 4 отдельных актера. Допустим, 1 мой актер наносит удар по БД. Является ли стратегия надзора правильным способом обработки вещей?

object ExceptionHandlingSupervisor extends App{
  val actorSystem = ActorSystem("ExceptionHandlingActorSystem")
  val actor = actorSystem.actorOf(Props[SupervisorActor], "SupervisorActor")
  actor ! Start

  class SupervisorActor extends Actor {
    val dbActor = context.actorOf(Props[ChildActor],"ChildActor")
    override def receive: Receive = {
      case Start => dbActor ! HitDatabase("","")
    }

    override val supervisorStrategy = OneForOneStrategy(loggingEnabled = false){
      case ae:SQLException => println("Found an SQLException") //Add my logging logic here and error notification logic here
        Resume

      case _:Exception => println("Found an Exception")
        Restart

    }

  }

  class ChildActor extends Actor{
    override def receive: Receive = {
      case HitDatabase(user,pass) => dbFunction(user,pass)
    }
  }
}

Будет ли приведенный выше код подходить для этого подхода, или мне следует придерживаться обычного блока Try / Catch:

class DbActor extends Actor{
        override def receive: Receive = {
          case HitDatabase(user,pass) => 
    try{
            dbFunction(user,pass)
          }
            catch {
              case ae:SQLException => println("Found an SQLException") //Add my logging logic here and error notification logic here
            }

Также я был бы очень признателен, если бы вы могли сказать, почему при таких обстоятельствах следует выбирать подход супервизора вместо обычной обработки исключений? Можем ли мы указать некоторую другую логику обработки ошибок в supervisorStrategy, кроме выполнения Resume или Restart?

1 Ответ

0 голосов
/ 17 января 2019

Если нет необходимости обрабатывать исключения очень детально или по-разному в отдельных субъектах, я бы позволил встроенному supervisorStrategy обрабатывать исключения и перезапуск / завершение соответствующего субъекта и т. Д. Это также дает преимущество удобочитаемость благодаря центральному месту для логики обработки ошибок.

Можем ли мы указать некоторую другую логику обработки ошибок в supervisorStrategy кроме как просто сделать Resume или Restart?

В supervisorStrategy существуют другие действия по обработке ошибок, такие как Stop, Escalate. Stop завершает дочерний актер, а Escalate расширяет цепочку до родительского супервизора. Пользовательский код может быть добавлен до возврата Directive в каждом case, если кодовый блок decider соответствует PartialFunction[Throwable, Directive]. Например:

override val supervisorStrategy =
  OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
    case e: ArithmeticException =>
      myLogActor ! s"ERROR: $e from $sender; Resuming."
      Resume
    case _: Exception =>
      myLogActor ! s"ERROR: unknown exception from $sender; Escalating."
      Escalate
  }

В качестве дополнительного примечания: если вы должны использовать подход try/catch, рассмотрите вариант использования Try, как показано ниже:

Try(dbFunction(user, pass)) match {
  case Success(res)             => // do something with `res`
  case Failure(e: SQLException) => // log `e`, etc
  case Failure(e)               => // other exceptions ...
}
...