как использовать akka.actor.Status.Failure, чтобы поймать исключение - PullRequest
0 голосов
/ 25 января 2019

У меня есть субъект, который отвечает за операции CRUD MongoDB, он может выдать mongoException Я хочу поймать это исключение в коде вызова, где я использую шаблон запроса, но я все еще получаю исключение TimeOutException, которое не требуется вВ моем случае из документов я перешел по этой ссылке

Предупреждение. Для завершения с исключением необходимо отправить сообщение akka.actor.Status.Failure отправителю.Это не выполняется автоматически, когда актер генерирует исключение при обработке сообщения.

Я следовал фрагменту кода, приведенному в документе

, вот мой код

class test extends Actor {

def receive () {

case GetRecordLists=>
try {  
 //some operations here 
   sender ! resultList
}
catch {
  mongoEX:MongoException=>
  log.error("got mongodb exception",mongoex)
  sender ! akka.actor.Status.Failure(mongoEx)
  throw mongoEx

e:Exception=>
  log.error("got exception",e)
  sender ! akka.actor.Status.Failure(e)
  throw e
}

}

}


class MainClass extends App {

try {
     val future: Future[scala.collection.mutable.Set[String]] = ask(test, GetRecordLists).mapTo[scala.collection.mutable.Set[String]]
     val results = Await.result(future, timeout.duration)
    }
    catch  {
      case e:Exception=>log.error("got the exception in main class ",e)
      throw new Exception(e)
    }
}

здесь ожидаемое поведение - поймать MongoException, но я получаю

java.util.concurrent.TimeoutException: Futures timed out after [5 seconds]
    at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:219) ~[scala-library-2.11.1.jar:na]
    at scala.concurrent.impl.Promise$DefaultPromise.result(Promise.scala:223) ~[scala-library-2.11.1.jar:na]
    at scala.concurrent.Await$$anonfun$result$1.apply(package.scala:111) ~[scala-library-2.11.1.jar:na]
    at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:53) ~[scala-library-2.11.1.jar:na]
    at scala.concurrent.Await$.result(package.scala:111) ~[scala-library-2.11.1.jar:na]
    at MainClass(MainClass.scala:118) [xyz_2.11.jar:0.1.0-SNAPSHOT]

1 Ответ

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

То, что вы делаете, выглядит правильно. Единственное объяснение ошибки тайм-аута состоит в том, что операция с mongo еще не завершена и 5 seconds недостаточно.

Пожалуйста, проверьте очень упрощенный код, который обрабатывает случаи успеха, неудач и тайм-аута.

import akka.actor.{Actor, ActorSystem, Props}
import akka.actor.Status.Failure
import akka.util.Timeout
import akka.pattern.ask

import concurrent.duration._

class TestActor(body: () => String) extends Actor {
  override def receive: Receive = {
    case msg => try {
      sender() ! body()
    } catch {
      case ex: Throwable =>
        sender() ! Failure(ex)
    }
  }
}

object TestApp extends App {
  val system = ActorSystem("test")
  import system.dispatcher
  implicit val timeout: Timeout = 1.second
  val actorOk = system.actorOf(Props(new TestActor(() => "Hello")))
  val actorNok = system.actorOf(Props(new TestActor(() => sys.error("Boom"))))
  val actorTimeout = system.actorOf(Props(new TestActor(() => {Thread.sleep(3000); ""})))
  (actorOk ? "some message").mapTo[String].onComplete(println)
  (actorNok ? "some message").mapTo[String].onComplete(println)
  (actorTimeout ? "some message").mapTo[String].onComplete(println)
  Thread.sleep(2000)
  system.terminate()
}

Отпечатки

Success(Hello)
Failure(java.lang.RuntimeException: Boom)
Failure(akka.pattern.AskTimeoutException: Ask timed out on [Actor[akka://test/user/$c#-765807830]] after [1000 ms]. Message of type [java.lang.String]. A typical reason for `AskTimeoutException` is that the recipient actor didn't send a reply.)
...