0

scalaとspray-routingでシンプルなCRUDアプリケーションを作成しようとしています。私は次のルートを持っています:

override def receive = runRoute {
    path("entities" / LongNumber) { id =>
      get {
        produce(instanceOf[MyEntity]) {
          func => ctx => heavyLookupById(id, func)
        }
    }
}

公式ドキュメントhttp://spray.io/documentation/1.2.2/spray-routing/marshalling-directives/produce/に従ってこれを書きました

MyEntity は次のとおりです (実際には関係ありません)。

case class MyEntity(text: String, id: Option[Long])

そして、次のjson-supportオブジェクトがあります

object MyJsonSupport extends DefaultJsonProtocol with SprayJsonSupport {
    implicit val format = jsonFormat2(MyEntity)
}

「heavyLookupById」関数には、いくつかの重いブロッキング計算が含まれており (データベース クエリや http 要求を想定)、そのために scala future を処理する必要があります。

def heavyLookupById(id: Long, func: MyEntity => Unit) = {
   // ... heavy computations
   future onSuccess { case x => func(x) }
}

しかし、私の将来が失敗した場合、どうすればよいでしょうか? Bad request (400) や not found (404) などの HTTP エラーで応答したいのですが、どうすればよいですか? 「heavyLookupById」内で「func」を呼び出さない場合-リクエストがハングするだけです-デフォルトのサーバータイムアウト(1分程度)で失敗すると思います。

4

1 に答える 1

1

RequestContext (ctx) があるので、reject、failWith、または で利用可能なその他のメソッドを呼び出すことができますRequestContext

  val route = path("entities" / LongNumber) { id =>
    get {
      produce(instanceOf[MyEntity]) {
        func => ctx => heavyLookupById(id, func, ctx)
      }
    }
  }

  def heavyLookupById(id: Long, func: MyEntity => Unit, ctx: RequestContext) = {
    // ... heavy computations
    val future = Future.successful(MyEntity("Hello", Some(1)))
    future.onComplete {
      case Success(value) => func(value)
      case Failure(ex) => ctx.failWith(ex)
    }

  }

個人的にはプロデュースよりもハンドルウィズの方が好きで、少し読みやすいと思います。

また、失敗した場合、スプレーは例外ハンドラでカスタマイズできる 500 を返します。

  def heavyLookupById(id: Long) = {
    // ... heavy computations
    Future.successful(MyEntity("Hello", Some(1)))
  }


  val route = path("entities" / LongNumber) { id =>
    get {
      handleWith(heavyLookupById)
    }
  }
于 2015-07-08T09:52:38.327 に答える