mirror of https://github.com/sbt/sbt.git
Retry downloads if an SSLException is caught
This commit is contained in:
parent
f7020fd0ad
commit
869d7c628e
|
|
@ -189,44 +189,78 @@ object Cache {
|
||||||
} finally if (out != null) out.close()
|
} finally if (out != null) out.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private def defaultRetryCount = 3
|
||||||
|
|
||||||
|
private lazy val retryCount =
|
||||||
|
sys.props
|
||||||
|
.get("coursier.sslexception-retry")
|
||||||
|
.flatMap(s => scala.util.Try(s.toInt).toOption)
|
||||||
|
.filter(_ >= 0)
|
||||||
|
.getOrElse(defaultRetryCount)
|
||||||
|
|
||||||
private def downloading[T](
|
private def downloading[T](
|
||||||
url: String,
|
url: String,
|
||||||
file: File,
|
file: File,
|
||||||
logger: Option[Logger]
|
logger: Option[Logger],
|
||||||
|
retry: Int = retryCount
|
||||||
)(
|
)(
|
||||||
f: => FileError \/ T
|
f: => FileError \/ T
|
||||||
): FileError \/ T =
|
): FileError \/ T = {
|
||||||
try {
|
|
||||||
val o = new Object
|
|
||||||
val prev = urlLocks.putIfAbsent(url, o)
|
|
||||||
if (prev == null) {
|
|
||||||
logger.foreach(_.downloadingArtifact(url, file))
|
|
||||||
|
|
||||||
val res =
|
@tailrec
|
||||||
try \/-(f)
|
def helper(retry: Int): FileError \/ T = {
|
||||||
catch {
|
|
||||||
case nfe: FileNotFoundException if nfe.getMessage != null =>
|
|
||||||
logger.foreach(_.downloadedArtifact(url, success = false))
|
|
||||||
-\/(-\/(FileError.NotFound(nfe.getMessage)))
|
|
||||||
case e: Exception =>
|
|
||||||
logger.foreach(_.downloadedArtifact(url, success = false))
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
urlLocks.remove(url)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (res0 <- res)
|
val resOpt =
|
||||||
logger.foreach(_.downloadedArtifact(url, success = res0.isRight))
|
try {
|
||||||
|
val o = new Object
|
||||||
|
val prev = urlLocks.putIfAbsent(url, o)
|
||||||
|
|
||||||
res.merge
|
val res =
|
||||||
} else
|
if (prev == null) {
|
||||||
-\/(FileError.ConcurrentDownload(url))
|
logger.foreach(_.downloadingArtifact(url, file))
|
||||||
}
|
|
||||||
catch { case e: Exception =>
|
val res =
|
||||||
-\/(FileError.DownloadError(s"Caught $e${Option(e.getMessage).fold("")(" (" + _ + ")")}"))
|
try \/-(f)
|
||||||
|
catch {
|
||||||
|
case nfe: FileNotFoundException if nfe.getMessage != null =>
|
||||||
|
logger.foreach(_.downloadedArtifact(url, success = false))
|
||||||
|
-\/(-\/(FileError.NotFound(nfe.getMessage)))
|
||||||
|
case e: Exception =>
|
||||||
|
logger.foreach(_.downloadedArtifact(url, success = false))
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
urlLocks.remove(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (res0 <- res)
|
||||||
|
logger.foreach(_.downloadedArtifact(url, success = res0.isRight))
|
||||||
|
|
||||||
|
res.merge[FileError \/ T]
|
||||||
|
} else
|
||||||
|
-\/(FileError.ConcurrentDownload(url))
|
||||||
|
|
||||||
|
Some(res)
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
case _: javax.net.ssl.SSLException if retry >= 1 =>
|
||||||
|
// TODO If Cache is made an (instantiated) class at some point, allow to log that exception.
|
||||||
|
None
|
||||||
|
case NonFatal(e) =>
|
||||||
|
Some(-\/(FileError.DownloadError(s"Caught $e${Option(e.getMessage).fold("")(" (" + _ + ")")}")))
|
||||||
|
}
|
||||||
|
|
||||||
|
resOpt match {
|
||||||
|
case Some(res) => res
|
||||||
|
case None =>
|
||||||
|
helper(retry - 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
helper(retry)
|
||||||
|
}
|
||||||
|
|
||||||
private def temporaryFile(file: File): File = {
|
private def temporaryFile(file: File): File = {
|
||||||
val dir = file.getParentFile
|
val dir = file.getParentFile
|
||||||
val name = file.getName
|
val name = file.getName
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue