在 Spray 中处理返回 Try 值的服务

Handle services returning Try values in Spray

我正在开发一个代码库,在该代码库中调用我的 Spray API 需要同步调用一个服务,该服务 return 是一个 Try Spray 需要格式化并且 return 通过 HTTP。

我最初的尝试是这样的:

// Assume myService has a run method that returns a Try[Unit]
lazy val myService = new Service() 

val routes = 
  path("api") {
    get {
      tryToComplete {
        myService.run()
      } 
    }
  } ~ 
  path("api" / LongNumber) { (num: Long) =>
    get {
      tryToComplete {
        myService.run(num)
      } 
    }
  }

def tryToComplete(result: => Try[Unit]): routing.Route = result match {
  case Failure(t) => complete(StatusCodes.BadRequest, t.getMessage)
  case Success(_) => complete("success")
}

然而,这导致 myService.run() 在应用程序启动时被调用。我不确定为什么调用此方法,因为没有进行 HTTP 调用。

所以我有两个问题:

  1. 为什么在初始化路由时调用我的服务?
  2. 处理这种情况最干净的方法是什么?想象一下,还有其他几个端点遵循类似的模式。所以我需要能够始终如一地处理这个问题。

即使您将结果参数作为按名称调用,它也会在您执行操作时立即得到评估

result match {

为了不对其进行评估,它必须在完整范围内,即您的代码应该类似于(尚未尝试编译):

def tryToComplete(result: => Try[Unit]): routing.Route = complete {
result match {
  case Failure(t) => StatusCodes.BadRequest, t.getMessage
  case Success(_) => "success"
}
}

我解决这个问题的方法是执行以下操作:

lazy val myService = new Service() 

val routes = 
  path("api") {
    get {
      complete {
        handleTry {
          myService.run()
        }
      } 
    }
  } ~ 
  path("api" / LongNumber) { (num: Long) =>
    get {
      complete {
         handleTry {
          myService.run(num)
        } 
      }
    }
  }

private def handleTry(operation: Try[_]):HttpResponse = operation match {
  case Failure(t) => 
    HttpResponse(status = StatusCodes.BadRequest, entity = t.getMessage)
  case Success(_) => 
    HttpResponse(status = StatusCodes.OK, entity = successMessage)
}