Scala - Execute arbitrary number of Futures sequentially but dependently -
this question has reply here:
is there sequential future.find? 3 answersi'm trying figure out neatest way execute series of futures in sequence, 1 future's execution depends on previous. i'm trying arbitrary number of futures.
user case:
i have retrieved number of ids database. i need retrieve related info on web service. i want stop 1 time i've found valid result. i care result succeeded.executing these in parallel , parsing collection of results returned isn't option. have 1 request @ time, , execute next request if previous request returned no results.
the current solution along these lines. using foldleft execute requests , evaluating next future if previous future meets condition.
def dblfuture(i: int) = { * 2 } val list = list(1,2,3,4,5) val future = list.foldleft(future(0)) { (previousfuture, next) => { { previousresult <- previousfuture nextfuture <- { if (previousresult <= 4) dblfuture(next) else previousfuture } } yield (nextfuture) } }
the big downside of a) maintain processing items 1 time i've got result i'm happy , b) 1 time i've found result i'm after, maintain evaluating predicate. in case it's simple if, in reality more complicated.
i sense i'm missing far more elegant solution this.
looking @ example, seems though previous result has no bearing on subsequent results, , instead matters previous result satisfies status prevent next result beingness computed. if case, here recursive solution using filter
, recoverwith
.
def untilfirstsuccess[a, b](f: => future[b])(condition: b => boolean)(list: list[a]): future[b] = { list match { case head :: tail => f(head).filter(condition).recoverwith { case _: throwable => untilfirstsuccess(f)(condition)(tail) } case nil => future.failed(new exception("all failed..")) } }
filter
called when future
has completed, , recoverwith
called if future
has failed.
def dblfuture(i: int): future[int] = future { println("executing.. " + i) * 2 } val list = list(1, 2, 3, 4, 5) scala> untilfirstsuccess(dblfuture)(_ > 6)(list) executing.. 1 executing.. 2 executing.. 3 executing.. 4 res1: scala.concurrent.future[int] = scala.concurrent.impl.promise$defaultpromise@514f4e98 scala> res1.value res2: option[scala.util.try[int]] = some(success(8))
scala future sequential for-comprehension foldleft
No comments:
Post a Comment