2013-02-11 5 views
2

У меня есть наблюдательный аккорский аккор, который использует маршрутизатор для отправки сообщений рабочим актерам.Обработка исключений Akka 2.1 (Scala)

У меня есть класс, который обертывает супервизора, и когда я вызываю метод в этом классе, он «просит» супервизора что-то сделать, а затем я использую Await.result(theFuture) для ожидания результата (я не могу продолжить без результата).

Если рабочие бросают исключение, я хочу перезапустить рабочего, который выбросил исключение, и я хочу, чтобы исключение было захвачено кодом, вызывающим класс-оболочку.

Я передал OneForOneStrategy конструктору маршрутизатора, который возвращает RESTART в случае Exception. В методе postRestart рабочего я регистрирую перезапуск, поэтому могу подтвердить, что рабочий фактически перезагружен.

Когда рабочий выдает исключение, он перезапускается, но исключение исчезает. Future, который является результатом запроса супервизора, содержит исключение, но это akka.pattern.AskTimeoutException, который вызывается через 5 секунд, а не 20 секунд, что является неявным таймаутом, который я задерживаю. Исключение фактически происходит менее секунды после начала работы.

Вопрос 1: Как я могу получить исключение от работника в коде, который вызывает мой класс оболочки?

Кроме того, способ приема работника, как это:

def receive = { 
    case r: Request => 
     val response = ??? //throws an exception sometimes 
     sender ! response 
} 

Что-то регистрирует исключение на консоль, но это не мой код. Трассировка стека является:

[ERROR] [02/11/2013 21:34:20.093] [MySystem-akka.actor.default-dispatcher-9] 
[akka://MySystem/user/MySupervisor/MyRouter/$a] Something went wrong! 
    at myApp.Worker.$$anonfun$receive$1.applyOrElse(Source.scala:169) 
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:425) 
at akka.actor.ActorCell.invoke(ActorCell.scala:386) 
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:230) 
at akka.dispatch.Mailbox.run(Mailbox.scala:212) 
at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(AbstractDispatcher.scala:502) 
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:262) 
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:975) 
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1478) 
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:104) 

Линия 169 из Source.scala является линия val response = ??? показано в листинг receive выше способом.

Вопрос 2:, который регистрирует это исключение для консоли и как его остановить?

+0

Q2: см. ActorLogging. – twillouer

+0

Q1: почему бы не использовать Try? (scala 2.10) – twillouer

+0

@twillouer Я использую Try -> myFuture.value.get дает Try, который в этом случае является ошибкой, содержащей исключение таймаута. –

ответ

3

1)

try somethingThatCanFail() catch { 
    case e: Exception => sender ! Status.Failure(e); throw e 
} 

"Говори сбой" приводит к тому, вызывающий абонент получит Failure, содержащий исключение. Бросок «e» вызывает вызов oneForOneStrategy, который перезапускает рабочего.

2)

Она сама система актер, который регистрирует отказ, и единственный способ , чтобы успокоить его вниз, чтобы отфильтровать вещи путем создания и настройки собственный LoggingAdapter, как описано здесь http://doc.akka.io/docs/akka/2.1.0/scala/logging.html Существует билет на изменение этого https://www.assembla.com/spaces/akka/tickets/2824 но она предназначена для Акку 2.2

Ответил https://groups.google.com/forum/#!topic/akka-user/fenCvYu3HYE

0

Для того, чтобы получать уведомления о один из ваших детей не удается, вам нужен

  • Первого watch ребенок
  • Тогда вы будете посланы Terminated(), когда актер умирает со ссылкой на него.

Что-то вроде:

class ParentActor extends Actor { 
    // this is sample of how to watch for death of one of your children 
    val childActor = context.actorOf(Props[SomeService], "SomeService") 
    val dyingChild = context.watch(context.actorOf(childActor)) 

    def receive = { 
    case Terminated(`dyingChild`) => 
     println("dyingChild died") 
    case Terminated(terminatedActor) => 
     println(s"This child just died $terminatedActor") 
    } 
} 

Надеется, что это помогает.

+0

Это не отвечает ни на вопрос. –

Смежные вопросы