Actor( OrgaActor )向数据库角色( DbActor )询问文档。 DbActor 并不总是提供文档,而是数据库错误异常。 OrgaActor 现在应该使用详细信息更改收到的异常(它实际上是组织查询,而不是通用数据库查询)。我很难从 DbActor 拦截异常,并在发送给控制器的结果中更改它( OrgaCtl )。 OrgaActor
的非工作示例代码def receive = {
case GetDocument(id: String) => {
try {
val answer = (dbActor ? DbActor.GetDocument("Orga", id)).mapTo[JsValue]
play.Logger.debug("in answer")
answer.pipeTo(sender())
} catch {
case e: Exception =>
play.Logger.debug("in exception")
val fhe = error.FhException(e, 404, error.Error.ORGA_LOAD, "error on load " + id)
sender() ! akka.actor.Status.Failure(fhe)
}
}
DbActor 的 GetDocument :
case GetDocument(coll: String, id: String) =>
try {
val response = new FigureheadDb().get(coll, id)
sender() ! response.jsonElementPayload()
} catch {
case e: Exception =>
val fhe = error.FhException(e, 404, error.Error.FH_ID, "error on load " + id + " in coll " + coll)
sender() ! akka.actor.Status.Failure(fhe)
throw fhe
}
永远不会显示 inException 调试消息,所以我猜 DbActor 中的 throw fhe 代码永远不会到达调用 OrgaActor 即可。 DbActor 绑定到 OrgaActor ,其中 val dbActor = context.actorOf(Props [DbActor],name =“db-actor”)。< / p>
问题是:如何拦截组织actor中数据库actor抛出的错误并将丰富的错误传递给全局错误处理程序?目前,全局错误处理程序始终会获取数据库actor错误。
基于已接受的答案的代码
dbActor :
case GetDocument(coll: String, id: String, originalSender: ActorRef) =>
try {
val response = new FigureheadDb().get(coll, id)
sender() ! GetDocumentSuccess(response.jsonElementPayload(), originalSender)
} catch {
case e: Exception =>
val fhe = error.FhException(e, 404, error.Error.FH_ID, "error on load " + id + " in coll " + coll)
sender() ! GetDocumentFailed(fhe, id, originalSender)
}
OrgaActor :
case GetDocument(id: String) => {
val answer : Future[Any] = dbActor ? DbActor.GetDocument(coll, id, sender())
answer.map {
case success: DbActor.GetDocumentSuccess =>
play.Logger.debug("in success")
success.originalSender ! success.result.as[JsValue]
case failure: DbActor.GetDocumentFailed => {
play.Logger.debug("in failure")
val fhe = error.FhException(failure.cause, 404, error.Error.ORGA_LOAD, "error on load " + failure.id)
failure.originalSender ! akka.actor.Status.Failure(fhe)
}
case any => {
play.Logger.error("Dead end")
}
}
}
对象DbActor :
case class GetDocument(coll: String, id: String, originalSender: ActorRef)
// http://stackoverflow.com/questions/35549414/how-to-intercept-and-change-exception-in-scala-akka-in-play-framework-2-4-6
sealed trait GetDocumentResult
case class GetDocumentSuccess(result: JsValue, originalSender: ActorRef) extends GetDocumentResult
case class GetDocumentFailed(cause: Exception, id: String, originalSender: ActorRef) extends GetDocumentResult
答案 0 :(得分:0)
在你的OrgaActor
中,你试图捕捉一个永不抛出的异常。
以下代码引自您的问题,但我在answer
中添加了类型注释。
try {
val answer: Future[JsValue] = (dbActor ? DbActor.GetDocument("Orga", id)).mapTo[JsValue]
play.Logger.debug("in answer")
answer.pipeTo(sender())
} catch { ... }
您可能希望第二行(val answer ....
)抛出异常,但它不会抛出异常,但会返回Future,这可能会成功或失败。
使用answer.pipeTo(sender())
将来的结果(可能是Status.Failure
)发送给发件人()。
作为一种解决方案,您可以定义一个密封特征GetDocumentResult
,其中两个案例类实现了特征:
// you already have this case class, I added the original sender,
// since you might need this information to know where to send the final result
case class GetDocument(coll: String, id: String, originalSender: ActorRef)
sealed trait GetDocumentResult
case class GetDocumentSuccess(result: JsValue, originalSender: ActorRef) extends GetDocumentResult
case class GetDocumentFailed(cause: Exception, id: String, originalSender: ActorRef) extends GetDocumentResult
使用此DbActor
可以发送GetDocumentSuccess
或GetDocumentFailed
作为对OrgaActor
的回复。一旦OrgaActor
收到响应,它就可以将最终结果(成功或后处理的失败消息)发送给原始发件人。