No need to return the Source
itself from isValid
. Simply append the source itself to each result of an isValid
request.
Once the results of validity checks are there, filter those sources that
are valid, and throw away the validity-boolean:
val sources: Seq[Source] = ...
val validSources: Future[Seq[Source]] = (for {
checkedSources <- Future.sequence(
sources.map(s => s.isValid.map(b => (s, b)))
)
} yield checkedSources.filter(_._2).map(_._1))
Here, s.isValid
returns a Future[Boolean]
. This future is mapped with b => (s, b)
, so that s.isValid.map(b => (s, b))
is a Future[(Source, Boolean)]
. The Future.sequence
transforms bunch of futures into a single future of a sequence. Once the sequence has been computed, it can be filtered by the second component, and then the second component can be discarded.
I'm not sure whether this is "the best" way to do this, because it's not clear to me how long the validity check remains sufficiently "fresh": it might well be that half of the results of isValid
checks are outdated by the time all results are collected into the checkedSources
sequence.
EDIT (1): Even shorter:
val validSources: Future[Seq[Source]] =
Future.sequence(sources.map(_.isValid)).map {
bs => (sources zip bs).filter(_._2).map(_._1)
}
This should work too.
(code unchecked with compiler, rough sketch off the top of my head; Please provide minimal compilable example if you want a compilable solution)