Reputation: 2527
I want to execute List of functions which returns futures sequentially.
What could be the possible implementations for following method:
def runSequentially[A, B](lazyFutures: List[A ⇒ Future[B]])(input: A)
(implicit ec: ExecututionContext): Future[List[B]]
Test
test("execute futures sequentially") {
import scala.concurrent.ExecutionContext.Implicits.global
def runSequentially[A, B](lazyFutures: List[A ⇒ Future[B]])(input: A): Future[List[B]] = ???
val l: List[Unit ⇒ Future[Unit]] = List(
_ ⇒ Future { Thread.sleep(1000); println(1) },
_ ⇒ Future { Thread.sleep(5000); println(2) },
_ ⇒ Future { Thread.sleep(500); println(3) }
)
Await.result(runSequentially(l)(5), 20.seconds)
}
This should print:
1
2
3
Upvotes: 2
Views: 2300
Reputation: 48400
Try creating a pool with one thread and use Future.traverse
like so
implicit val singleThreadEc: ExecutionContext =
ExecutionContext.fromExecutor(Executors.newSingleThreadExecutor())
def runSequentially[A, B](lazyFutures: List[A ⇒ Future[B]])(input: A): Future[List[B]] =
Future.traverse(lazyFutures)(f => f(input))
Upvotes: 4
Reputation: 3390
You can also use cats
and Kleisli
import scala.concurrent.ExecutionContext.Implicits.global
import cats.implicits._
import cats.data.Kleisli
def runSequentially[A, B](lazyFutures: List[A ⇒ Future[B]])(input: A) : Future[List[B]] = lazyFutures
.map(Kleisli.apply) //List[Kleisli[Future, A, B]]
.sequence //Kleisli[Future, A, List[B]]
.run(input)
Upvotes: 2
Reputation: 2527
This is what I came up with which does work
def runSequentially[A, B](lazyFutures: List[A ⇒ Future[B]])(input: A): Future[List[B]] = {
lazyFutures.foldLeft(Future.successful(List.empty[B])) { (acc, curr) ⇒
for {
a ← acc
c ← curr(input)
} yield c :: a
}
}
Upvotes: 0
Reputation: 20551
def runSequentially[A, B](lazyFutures: Seq[A => Future[B]])(input: A)(implicit ctx: ExecutionContext): Future[List[B]] =
lazyFutures.foldLeft(Future.successful(List.empty[B])) { (futAcc, f) =>
futAcc.flatMap { acc =>
f(input).flatMap { result =>
result :: acc
}
}
}.map(_.reverse)
Should do the trick (haven't tested it). By prepending to the list and reversing, the complexity is O(n), while appending is O(n^2), since appending is O(n) and the append is done n times.
Upvotes: 2