Akka HTTPの onSuccess ディレクティブは The Magnet Pattern によって実装されているのでOnSuccessMagnet型クラスのインスタンスさえ定義してしまえば割りと何でも受け取ることができる。型がM[Future[A]]になっているオブジェクトをそのままonSuccessに渡したくなった時のために覚えておくと良いかもしれない。

例えば、次のコードでDirective[Tuple1[Future[A]]]に対応することが可能。

implicit def directiveIncludingFuture[T](futureDirective: Directive[Tuple1[Future[T]]])(implicit tupler: Tupler[T]): OnSuccessMagnet { type Out = tupler.Out } = {
  new OnSuccessMagnet {
    type Out = tupler.Out
    val directive: Directive[Out] = futureDirective.flatMap { future =>
      Directive[tupler.Out] { inner => ctx =>
        import ctx.executionContext
        future.fast.flatMap(t => inner(tupler(t))(ctx))
      }(tupler.OutIsTuple)
    }(tupler.OutIsTuple)
  }
}

Directive[Tuple1[Future[A]]]なんてそう滅多に出てこないでしょ…と思うかもしれないが、複数の Directive1 から取得した値を非同期で処理するというシチュエーションはそれなりにあるかもしれない。

こんな感じのやつ。

val result = for {
  value1 <- directive1
  value2 <- directive2
} yield hogeAsyncRepository.findBy(value1, value2) // resultの型は Directive[Tuple1[Future[Option[A]]]] になる

onSuccess(result) {
  case Some(_) => complete(OK)
  case None    => complete(NotFound)
}