2017-02-05 1 views
0

У меня есть два актера Компьютер и принтер. Компьютер является родительским принтером и имеет одну стратегию, определенную для принтера.Возможно ли, чтобы супервизор передал исключение вызывающему актеру, если дочерний актер вышел из строя даже после повторной попытки N раз?

Я перечислил приведенный ниже код.

class Computer extends Actor with ActorLogging{ 
    import Computer._ 
    import Printer._ 

    implicit val timeout: Timeout = 2 seconds 

    val printer: ActorRef = context.actorOf(Props[Printer], "printer-actor") 

    override def receive: Receive = { 
    case Print(text) => { 
     val printJob: Future[Any] = printer ? PrintJob(Random.nextInt, text) 

     printJob.mapTo[Page].map { 
     case Page(text) => { 
      log.info(s"Received page containing text ${text}") 
      context.system.shutdown() 
     } 
     }.onFailure { 
     case t: Throwable => sender ! akka.actor.Status.Failure(t) 
     } 
    } 
    } 

    override val supervisorStrategy = 
    OneForOneStrategy(maxNrOfRetries = 3, withinTimeRange = 1 minute) { 
     case e : Exception => { 
     log.info(s"caught exception of type ${e.getClass}") 
     SupervisorStrategy.Restart 
     } 
    } 
} 

class Printer extends Actor with ActorLogging{ 
    import Printer._ 

    override def receive: Receive = { 
    case PrintJob(id, text) => { 
     log.info(s"Received ${PrintJob(id, text)}") 
     if (Random.nextBoolean) sender ! Page(text) 
     else throw new NoPaperException(id) 
    } 
    } 


    override def preRestart(cause: Throwable, message: Option[Any]) = { 
    log.info(s"Restarting actor ${self} because of ${cause}. Queueing message ${message}") 
    postStop() 
    message.map(self forward _) 
    } 
} 

Принтер выбрасывает исключение на основе случайного генератора. Код работает нормально, супервизор перезапускает и повторяет дочерний актер при ошибке, как указано.

Однако шаблон запроса val printJob: Future[Any] = printer ? PrintJob(Random.nextInt, text) не работает с исключением AkkaTimeoutException, если все попытки заставить работу актера принтера терпят неудачу.

Есть ли способ передать точное исключение, из-за которого актер потерпел неудачу? В этом случае NoPapperException.

Cheers,

Utsav

ответ

0

передать исключение обратно отправителю необходимо sender ! Status.Failure(e) - где е является исключением

Вы можете сделать это прямо из актера, или если вы хотите сделать это от супервизора, вам нужно иметь подкласс исключения, который будет содержать ссылку отправителя с ним, чтобы супервизор мог отправить исключение обратно

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