Tôi đang gọi một diễn viên sử dụng mẫu yêu cầu trong ứng dụng Phun và trả về kết quả là phản hồi HTTP. Tôi ánh xạ các lỗi từ diễn viên đến một mã lỗi tùy chỉnh.Giải quyết tương lai Akka từ yêu cầu trong trường hợp thất bại
val authActor = context.actorOf(Props[AuthenticationActor])
callService((authActor ? TokenAuthenticationRequest(token)).mapTo[LoggedInUser]) { user =>
complete(StatusCodes.OK, user)
}
def callService[T](f: => Future[T])(cb: T => RequestContext => Unit) = {
onComplete(f) {
case Success(value: T) => cb(value)
case Failure(ex: ServiceException) => complete(ex.statusCode, ex.errorMessage)
case e => complete(StatusCodes.InternalServerError, "Unable to complete the request. Please try again later.")
//In reality this returns a custom error object.
}
}
Điều này hoạt động chính xác khi authActor gửi một lỗi, nhưng nếu authActor ném ngoại lệ, không có gì xảy ra cho đến khi hết thời gian yêu cầu. Ví dụ:
override def receive: Receive = {
case _ => throw new ServiceException(ErrorCodes.AuthenticationFailed, "No valid session was found for that token")
}
Tôi biết rằng các tài liệu Akka nói rằng
Để hoàn thành tương lai với một ngoại lệ bạn cần gửi một thông điệp Không cho người gửi. Điều này không được thực hiện tự động khi một diễn viên ném một ngoại lệ trong khi xử lý tin nhắn.
Nhưng vì tôi sử dụng yêu cầu nhiều giao diện giữa các diễn viên định tuyến Phun và diễn viên dịch vụ, tôi không muốn quấn phần nhận của mỗi diễn viên trẻ bằng try/catch. Có cách nào tốt hơn để đạt được xử lý tự động các ngoại lệ trong các diễn viên trẻ và ngay lập tức giải quyết tương lai trong trường hợp ngoại lệ?
Chỉnh sửa: đây là giải pháp hiện tại của tôi. Tuy nhiên, nó khá lộn xộn để làm điều này cho mọi diễn viên trẻ.
override def receive: Receive = {
case default =>
try {
default match {
case _ => throw new ServiceException("")//Actual code would go here
}
}
catch {
case se: ServiceException =>
logger.error("Service error raised:", se)
sender ! Failure(se)
case ex: Exception =>
sender ! Failure(ex)
throw ex
}
}
Bằng cách đó nếu đó là lỗi dự kiến (nghĩa là ServiceException), nó được xử lý bằng cách tạo lỗi. Nếu nó bất ngờ, nó trả về một thất bại ngay lập tức để tương lai được giải quyết, nhưng sau đó ném ngoại lệ để nó vẫn có thể được xử lý bởi SupervisorStrategy.
Vâng ... gửi thông báo lỗi trước khi ném ngoại lệ. –
Đó là những gì tôi không muốn làm - tôi nói ** Tôi không muốn quấn phần nhận của mỗi diễn viên trẻ với một thử/bắt **. Đây là một ví dụ đồ chơi, nó hoàn toàn có thể là tôi không kiểm soát nơi mà các ngoại lệ được ném. –
Vâng ... bạn biết đấy ... một trong những con đường cơ bản của các hệ thống phân tán phục hồi là "làm cho các lỗi rõ ràng". Hãy nghĩ về các lỗi khác nhau có thể xảy ra ... làm cho chúng rõ ràng. Nếu bạn có thể có lỗi "TypeSafe" ... thậm chí tốt hơn. –