2017-02-05 3 views
0

私はコンピューターとプリンターの2人の俳優がいます。コンピュータはプリンタの親であり、プリンタ用に定義された1つの戦略の1つを有する。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です。 eはあなたが俳優から直接それを行うか、またはもしどちらかの例外

ある -

乾杯、

UTSAV

答えて

0

は、バックあなたがsender ! Status.Failure(e)に必要な送信者に例外を渡しますスーパーバイザからそれを行いたい場合は、スーパーバイザが例外を返すことができるように、送信者の参照を保持する例外のサブクラスを持つ必要があります

関連する問題