Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concatenate many Future[Seq] into one Future[Seq]

Without Future, that's how I combine all smaller Seq into one big Seq with a flatmap

category.getCategoryUrlKey(id: Int):Seq[Meta] // main method
val appDomains: Seq[Int]

val categories:Seq[Meta] = appDomains.flatMap(category.getCategoryUrlKey(_))

Now the method getCategoryUrlKey could fail. I put a circuit breaker in front to avoid to call it for the next elements after an amount of maxFailures. Now the circuit breaker doesn't return a Seq but a Future[Seq]

lazy val breaker = new akka.pattern.CircuitBreaker(...)

private def getMeta(appDomainId: Int): Future[Seq[Meta]] = {
  breaker.withCircuitBreaker {
    category.getCategoryUrlKey(appDomainId)
  }
}

How to iterate through the List appDomains and combine the result into one single Future[Seq] , possible into Seq ?

If Functional Programming is applicable, is there a way to directly transform without temporary variables ?

like image 378
Raymond Chenon Avatar asked Jun 16 '17 09:06

Raymond Chenon


1 Answers

Squash seq of futures using Future.sequence

Future.sequenceconverts Seq[Future[T]] to Future[Seq[T]]

In your case T is Seq. After the sequence operation, you will end up with Seq[Seq[T]]. So Just flatten it after the sequence operation using flatten.

def squashFutures[T](list: Seq[Future[Seq[T]]]): Future[Seq[T]] =
  Future.sequence(list).map(_.flatten)

Your code becomes

Future.sequence(appDomains.map(getMeta)).map(_.flatten)
like image 179
pamu Avatar answered Oct 14 '22 11:10

pamu