johanandren / futiles

The missing utils for working with Scala Futures

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Boolean ops aren't as clever as they could be

johanandren opened this issue · comments

Consider these cases:

Future { Thread.sleep(5000); false } && Future.successful(false)
Future { Thread.sleep(5000); false } || Future.successful(true)

We could make them resolve as fast as the fastest future, in best case.

The problem is that a solution that tries to short circuit becomes a bit race conditiony and how failures are propagated becomes unclear.

Sample solution, if there is a failure in both fa and fb, which is used?

 /**
   * @return A new future that will complete with false as soon as either future completes with false
   *         or true when both futures has completed and are true.
   */
  def firstAnd(fa: Future[Boolean], fb: Future[Boolean])(implicit ec: ExecutionContext) = {
    val promise = Promise[Boolean]()

    fa.onComplete {
      case Success(false) => promise.trySuccess(false)
      case Failure(ex) => promise.tryFailure(ex)
    }
    fb.onComplete {
      case Success(false) => promise.trySuccess(false)
      case Failure(ex) => promise.tryFailure(ex)
    }
    fa.zip(fb).onComplete {
      // this is the only case that can happen after the above
      case Success((true, true)) => promise.trySuccess(true)
    }

    promise.future
  }