我很难找到一个优雅的解决方案来链接一些期货。我尝试实现的方法如下所示(它是缓存的一部分):
def acquire(key: A, producer: => Future[B]): Future[B]
算法大致是这样的:
- 如果密钥被锁定,立即通过运行时异常(是否会提前使用 Future.failed?)
- 否则打开一个
future { getOrRefresh }
块,因为它需要一些时间来检索密钥 getOrRefresh
要么返回一个顺子B
,然后是未来和方法的结果- 或者它需要运行
producer
最后一步意味着我需要从 future内部对未来进行“扁平化” 。也就是说,我不能做 a outer.flatMap
,所以我猜策略是使用Await
.
现在,Await
有一个奇怪的精神分裂症,你可以得到一个Option[Try[B]]
, using 方法ready
,或者 unwound B
, using result
。问题是,我需要Failure
在完成外部未来之前释放一个锁,所以我必须坚持Await.ready
,我猜。
这变得丑陋:
val fut = producer
val prod = Await.ready(fut, Duration.Inf).value.get
if (prod.isFailure) sync.synchronized { locked = false }
prod.get
能有这么丑吗?必须有更好的方法来做到这一点。
所以重复一遍:在Future[B]
运行中,一些同样以 完成的对等未来B
,并返回对等的结果,但在失败的情况下,在完成主要未来之前清理锁。