Add more guarantees that a same module can't be downloaded concurrently

traverse called in ResolutionProcess.fetchAll relies on Applicative, so
doesn't guarantee that the module groups will be fetched one after the
other. The Applicative instance of scalaz.concurrent.Task doesn't
parallelize the tasks by default, so it works fine here. But that extra
security ensures that code can be fine with other monads.
This commit is contained in:
Alexandre Archambault 2017-07-22 17:29:29 +02:00
parent ef59fb5e49
commit 862169c6bb
1 changed files with 11 additions and 6 deletions

View File

@ -3,9 +3,8 @@ package core
import scala.annotation.tailrec
import scala.language.higherKinds
import scalaz.{Monad, -\/, \/-}
import scalaz.Scalaz.{ToFunctorOps, ToTraverseOps, vectorInstance}
import scalaz.{-\/, Monad, \/, \/-}
import scalaz.Scalaz.{ToFunctorOps, ToBindOps, ToTraverseOps, vectorInstance}
sealed abstract class ResolutionProcess {
@ -166,7 +165,10 @@ object ResolutionProcess {
Missing(resolution0.missingFromCache.toSeq, resolution0, apply)
}
private def fetchAll[F[_]](modVers: Seq[(Module, String)], fetch: Fetch.Metadata[F])(implicit F: Monad[F]) = {
private[coursier] def fetchAll[F[_]](
modVers: Seq[(Module, String)],
fetch: Fetch.Metadata[F]
)(implicit F: Monad[F]): F[Vector[((Module, String), Seq[String] \/ (Artifact.Source, Project))]] = {
def uniqueModules(modVers: Seq[(Module, String)]): Stream[Seq[(Module, String)]] = {
@ -191,8 +193,11 @@ object ResolutionProcess {
uniqueModules(modVers)
.toVector
.traverse(fetch)
.map(_.flatten)
.foldLeft(F.point(Vector.empty[((Module, String), Seq[String] \/ (Artifact.Source, Project))])) {
(acc, l) =>
for (v <- acc; e <- fetch(l))
yield v ++ e
}
}
}