Eduardo
Eduardo

Reputation: 7141

Scala: Chaining futures, returning the first

I have a scenario where I have a Future[Something]: a which when successful needs to trigger a second Future[Unit]: b. I want to chain a and b together but I only care that a succeeds. if b fails I can just log an error and leave it at that:

So far I have:

def updateSomething(something: Something): Future[Something] = {
    val eventual: Future[Something] = repository.update(something)
    eventual.onSuccess({
      case updated =>
        repository.audit(updated.id, "Update successful")
          .onFailure({
            case throwable: Throwable => Logger.error("Audit failed", throwable)
          })
        Logger.info("Update Complete")
    })
    eventual
}

But this does not link the lifecyles of the update and the audit together. e.g when I Await.result(service.updateSomething(...), duration) there is no guarantee the repository.audit future has completed.

Upvotes: 1

Views: 309

Answers (3)

LuisKarlos
LuisKarlos

Reputation: 547

also, you can just use a val

val = a <- executeA()
a.andThen{ case _ => executeB(b).recover{case e => println(e)} }
a //and return a 

Upvotes: 0

RoberMP
RoberMP

Reputation: 1356

flatMap is your friend. You can just use a for-comprehension + recover:

for {
  a <- executeA()
  _ <- executeB(b).recover{case e => println(e); Future.unit } // awaits B to complete
} yield a

Upvotes: 4

Ivan Aristov
Ivan Aristov

Reputation: 152

Also you can use more friendly form:

execudeA().flatMap(a =>
  executeB().recover { case e => println(e); () }.map(_ => a)
)

Upvotes: 0

Related Questions