我有一个负责MongoDB CRUD操作的演员,它可能抛出mongoException
,我想在调用代码中捕获此异常,而我使用的是Ask模式,但是我仍然收到TimeOutException异常,但不是就我而言,我已经over this link
警告 要完成异常操作,您需要发送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]
答案 0 :(得分:0)
您所做的看起来很正确。超时错误的唯一解释是,对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.)