Process a List[Future[...]] sequentially

Say I have a function that accepts a List[Future[Whatever]]. For my use case, I want to process the Futures sequentially. Meaning, I will only process future2 after future1 has finished with success (aka flatMap).

By reading the documentation of Future.sequence, I don’t think that the Futures will be run sequentially, so this doesn’t seem to be what I want.

I reckon this may not be a common pattern, but is there any clean way of doing this?

The reason I want the Futures to be run sequentially is that I want to avoid process any remaining Futures if one of them fails.

Thanks!

When you have list of futures it means that they are already running. Because futures are evaluated eagerly.
You can consider using IO from cats or Task from monix.

1 Like

Once you have a Future in hand, it’s already running, so by the time you have your Seq[Future], you’ve already lost that game…

The order you process the eventual values in a pile of Futures doesn’t relate to the order the operations producing those values get executed.

This is one of the reasons people dislike Future.

What you want to do is make aflatMap chain of the processes that CREATE theFuturess in the first place. Create future2 INSIDE the method passed to future1.flatMap to achieve sequentiality.

-dave-

You could consider accepting a List[() => Future[Foo]] instead. And then:

list.foldLeft(Future.unit)((a, b) => a.flatMap(_ => b()))

But even then it’s not guaranteed that those futures are run in sequence. I could for instance create a () => Future[Foo] like this:

val f = Future(new Foo)
() => f
2 Likes

The functional definition of Future[X] gives absolutely no guarantees about the relative “timing” of the computation of an X value for different Future instance.

What you do have is a guarantee that specific Future-creating functions guarantee the use of provided ExecutionContexts to perform such a computations (using ExecutionContext.execute), and you can put sequential constraints on invocations of execute() for ExecutionContexts.

So I agree with Jasper M that you can’t guarantee the sequential computations of arbitrary Futures. However you could impose sequential constraints if your code is in control of the creation of the Futures, since in that case you could put restrictions on the ExecutionContext(s) that are used.

Brian Maso