I have a large computation roughly based on the following pattern :
def f1(i:Int):Int = ???
def f2(i:Int):Int = ???
def processA(l: List[Int]) =
l.map(i => Future(f1(i)))
def processB(l: List[Int]) = {
val p = processA(l)
p.map(fut => fut.map(f2))
}
def main() = {
val items = List( /* 1k to 10k items here */ )
val results = processB(items)
results.map(_.onComplete ( ... ))
}
The problem I encounter, if my understanding is correct, is that the processing is breadth-first. ProcessA starts thousands of Futures, and processB will then enqueue thousands of new Futures that will be processed after those of processA are finished. The onComplete callback will start to be fired very late...
I would like to turn this depth-first : few Futures of processA starts, and then, processB continues from there instead of switching to something else in queues.
Can it be done in vanilla scala ? Should I turn to some lib with an alternative to Futures() and ThreadPools ?
EDIT: a bit more detail. Rewriting into f1 andThen f2
, as it has been suggested in answers, is not practicable at this time. Actually, processA and B
are doing a bunch of other things (incl. side effect). And the fact that processB
relies on ProcessA
is private. It would break SoC if it's exposed.
EDIT 2: I think I'm going to relax a bit the "vanilla" constraint. Someone suggested Akka streams that would help. I'm currently having a look at scalaz.Task: an opinion anyone ?