带有 akka-http 的 Scala 未来
Scala future with akka-http
我需要用 akka-http 和 reactivemongo 编写简单的网络服务。
保存数据的函数如下所示
def saveRoute(route: Route):Future[WriteResult] = {
collection.insert(route)
}
调用此函数的代码如下所示
val userRoutes = {
logRequestResult("akka-http-microservice") {
path("routes") {
(post & entity(as[Route])) { route =>
Database.saveRoute(route)
}
}
}
}
我需要 return 使用插入的路由 ID 生成结果,并且在不让线程等待的情况下执行此操作。
如果尝试
Database.saveRoute(route).onComplete{
case Success(r) => complete(r.toString)
case Failure(e) => complete(e.getMessage)
}
它无法编译,因为它没有 return 值。
我知道如何以肮脏的方式制作它,但真的想以适当的方式制作。
这种情况应该怎么办?
这个怎么样,替换:
Database.saveRoute(route)
与:
complete(Database.saveRoute(route).map(_.toString).recover(_.getMessage))
您可以映射未来,然后完成如下请求。
val future = Database.saveRoute(route)
val response = future.map(_.getId).recover(_.getMessage)
complete(response)
附带说明一下,为了处理异常,最好有一个 ExceptionHandler 并将其包装在您的路由中。您可以找到示例 here.
使用 onSuccess
处理未来完成时的有效响应,使用 handleExceptions
处理未来不成功的响应。
val userRoutes = {
handleExceptions(mongoDbExceptionHandler) {
logRequestResult("akka-http-microservice") {
path("routes") {
(post & entity(as[Route])) { route =>
onSuccess(Database.saveRoute(route)) { result =>
complete(result)
}
}
}
}
}
}
// Something like this for whatever the exceptions you expect are
val mongoDbExceptionHandler = ExceptionHandler {
case ex: MongoDbReadException => complete(HttpResponse(InternalServerError, "No database")))
}
处理异常:
http://doc.akka.io/docs/akka/2.4.9/scala/http/routing-dsl/exception-handling.html
看来我找到了最有效的方法。它内置于 onComplete 指令
(path("routes" / "add") & post & entity(as[Route])) {
route =>
onComplete(routesController.addRoute(route)) {
case Success(result) => complete(StatusCodes.Created, "OK")
case Failure(ex) => complete(new ErrorResponse(StatusCodes.InternalServerError.intValue, ErrorResponse.ERROR, ex.getMessage))
}
}
你没有多少选择,我会尝试将最常用的选项用于基于 REST API 的解决方案:
OnSuccess 当你希望你的期望冒泡并由 expectionHandler 处理时使用它
concat(
path("success") {
onSuccess(Future { "Ok" }) { extraction =>
complete(extraction)
}
},
path("failure") {
onSuccess(Future.failed[String](TestException)) { extraction =>
complete(extraction)
}
}
)
https://doc.akka.io/docs/akka-http/current/routing-dsl/directives/future-directives/onSuccess.html
onComplete:当你想手动处理异常时。尝试包裹 Monad。
val route =
path("divide" / IntNumber / IntNumber) { (a, b) =>
onComplete(divide(a, b)) {
case Success(value) => complete(s"The result was $value")
case Failure(ex) => complete((InternalServerError, s"An error occurred: ${ex.getMessage}"))
}
}
https://doc.akka.io/docs/akka-http/current/routing-dsl/directives/future-directives/onComplete.html
我需要用 akka-http 和 reactivemongo 编写简单的网络服务。
保存数据的函数如下所示
def saveRoute(route: Route):Future[WriteResult] = {
collection.insert(route)
}
调用此函数的代码如下所示
val userRoutes = {
logRequestResult("akka-http-microservice") {
path("routes") {
(post & entity(as[Route])) { route =>
Database.saveRoute(route)
}
}
}
}
我需要 return 使用插入的路由 ID 生成结果,并且在不让线程等待的情况下执行此操作。 如果尝试
Database.saveRoute(route).onComplete{
case Success(r) => complete(r.toString)
case Failure(e) => complete(e.getMessage)
}
它无法编译,因为它没有 return 值。 我知道如何以肮脏的方式制作它,但真的想以适当的方式制作。
这种情况应该怎么办?
这个怎么样,替换:
Database.saveRoute(route)
与:
complete(Database.saveRoute(route).map(_.toString).recover(_.getMessage))
您可以映射未来,然后完成如下请求。
val future = Database.saveRoute(route)
val response = future.map(_.getId).recover(_.getMessage)
complete(response)
附带说明一下,为了处理异常,最好有一个 ExceptionHandler 并将其包装在您的路由中。您可以找到示例 here.
使用 onSuccess
处理未来完成时的有效响应,使用 handleExceptions
处理未来不成功的响应。
val userRoutes = {
handleExceptions(mongoDbExceptionHandler) {
logRequestResult("akka-http-microservice") {
path("routes") {
(post & entity(as[Route])) { route =>
onSuccess(Database.saveRoute(route)) { result =>
complete(result)
}
}
}
}
}
}
// Something like this for whatever the exceptions you expect are
val mongoDbExceptionHandler = ExceptionHandler {
case ex: MongoDbReadException => complete(HttpResponse(InternalServerError, "No database")))
}
处理异常: http://doc.akka.io/docs/akka/2.4.9/scala/http/routing-dsl/exception-handling.html
看来我找到了最有效的方法。它内置于 onComplete 指令
(path("routes" / "add") & post & entity(as[Route])) {
route =>
onComplete(routesController.addRoute(route)) {
case Success(result) => complete(StatusCodes.Created, "OK")
case Failure(ex) => complete(new ErrorResponse(StatusCodes.InternalServerError.intValue, ErrorResponse.ERROR, ex.getMessage))
}
}
你没有多少选择,我会尝试将最常用的选项用于基于 REST API 的解决方案:
OnSuccess 当你希望你的期望冒泡并由 expectionHandler 处理时使用它
concat(
path("success") {
onSuccess(Future { "Ok" }) { extraction =>
complete(extraction)
}
},
path("failure") {
onSuccess(Future.failed[String](TestException)) { extraction =>
complete(extraction)
}
}
)
https://doc.akka.io/docs/akka-http/current/routing-dsl/directives/future-directives/onSuccess.html
onComplete:当你想手动处理异常时。尝试包裹 Monad。
val route =
path("divide" / IntNumber / IntNumber) { (a, b) =>
onComplete(divide(a, b)) {
case Success(value) => complete(s"The result was $value")
case Failure(ex) => complete((InternalServerError, s"An error occurred: ${ex.getMessage}"))
}
}
https://doc.akka.io/docs/akka-http/current/routing-dsl/directives/future-directives/onComplete.html