如何使用超时链接 Scala Futures?

How to chain Scala Futures with timeouts?

假设我有一些函数 return Future:

def fab(a: A, timeOutMillis: Long): Future[B] = ???
def fbc(b: B, timeOutMillis: Long): Future[C] = ???
def fcd(c: C, timeOutMillis: Long): Future[D] = ???

如果 timeOutMillis > 0timeOutMillis 时间段内完成的功能 return 期货。否则他们 return 失败了 Future.

现在我想将这些函数组合成facfad:

def fac(a: A, timeOutMillis: Long): Future[C] = ???
def fad(a: A, timeOutMillis: Long): Future[D] = ???

所以我可以这样实现 fac

def fac(a: A, timeOutMillis: Long): Future[C] = {
  val startTime = System.currentTimeMillis()
  for {
     b <- fab(a, timeOutMillis)
     timeAB = System.currentTimeMillis() - startTime
     c <- fbc(b, timeOutMillis - timeAB)
  } yield c
}

注意我不想等待 完成期货,因此我不使用Await

这个 fac 实现可能会工作,但它看起来很笨拙并且包含样板代码。
您如何建议带超时的链 Futures

P.S。我正在考虑覆盖 FutureflatMap 来计算下一次超时。你怎么看?

为什么不呢:

import scala.concurrent.{Await,Future}

Await.ready(fut1, 5.seconds).flatMap { sucInTime =>
  fut2
}

我想,您正在寻找 scala.duration.Deadline

    d = timeoutMillis.millis.fromNow
    fab(a, d.timeLeft.toMillis)
      .flatMap(fbc(_, d.timeLeft.toMillis))
      .flatMap(fcd(_, d.timeLeft.toMillis))

如果您不喜欢重复 d.timeTimeLeft.toMillis 咒语, 你可以把它折叠成一个折叠,也可以将它概括为任何数字 链接调用数:

Seq(fab _, fbc _, fcd _)
  .foldLeft(Future(a)) { case (last, next) => 
     last.flatMap(next(_, d.timeLeft.toMillis))
   }