mirror of https://github.com/sbt/sbt.git
[2.x] Retry on HTTP 5xx during dependency resolution (#8903)
This commit is contained in:
parent
1bd5a5e409
commit
29d2653bf6
|
|
@ -144,12 +144,7 @@ object ResolutionRun {
|
|||
resolveTask.io.attempt
|
||||
.flatMap {
|
||||
case Left(e: ResolutionError) =>
|
||||
val hasConnectionTimeouts = e.errors.exists {
|
||||
case err: CantDownloadModule =>
|
||||
err.perRepositoryErrors.exists(_.contains("Connection timed out"))
|
||||
case _ => false
|
||||
}
|
||||
if (hasConnectionTimeouts)
|
||||
if (isTransientResolutionError(e))
|
||||
if (attempt + 1 >= maxAttempts) {
|
||||
log.error(s"Failed, maximum iterations ($maxAttempts) reached")
|
||||
Task.point(Left(e))
|
||||
|
|
@ -280,4 +275,16 @@ object ResolutionRun {
|
|||
}
|
||||
|
||||
private lazy val retryScheduler = ThreadUtil.fixedScheduledThreadPool(1)
|
||||
|
||||
private[internal] def isTransientResolutionError(e: ResolutionError): Boolean =
|
||||
e.errors.exists {
|
||||
case err: CantDownloadModule => isTimeout(err) || isServerError(err)
|
||||
case _ => false
|
||||
}
|
||||
|
||||
private def isTimeout(err: CantDownloadModule): Boolean =
|
||||
err.perRepositoryErrors.exists(_.contains("Connection timed out"))
|
||||
|
||||
private def isServerError(err: CantDownloadModule): Boolean =
|
||||
err.perRepositoryErrors.exists(_.contains("Server returned HTTP response code: 5"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
package lmcoursier.internal
|
||||
|
||||
import coursier.core.{ Module, ModuleName, Organization, Resolution }
|
||||
import coursier.error.ResolutionError.CantDownloadModule
|
||||
import org.scalatest.funsuite.AnyFunSuite
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class ResolutionRunSpec extends AnyFunSuite with Matchers:
|
||||
|
||||
private def cantDownload(errors: String*): CantDownloadModule =
|
||||
new CantDownloadModule(
|
||||
Resolution(),
|
||||
Module(Organization("org"), ModuleName("mod"), Map.empty),
|
||||
"1.0",
|
||||
errors.toSeq
|
||||
)
|
||||
|
||||
test("503 is a transient resolution error"):
|
||||
val err = cantDownload(
|
||||
"Server returned HTTP response code: 503 for URL: https://repo.example.com/org/mod/1.0/mod-1.0.pom"
|
||||
)
|
||||
ResolutionRun.isTransientResolutionError(err) shouldBe true
|
||||
|
||||
test("500 is a transient resolution error"):
|
||||
val err = cantDownload(
|
||||
"Server returned HTTP response code: 500 for URL: https://repo.example.com/org/mod/1.0/mod-1.0.pom"
|
||||
)
|
||||
ResolutionRun.isTransientResolutionError(err) shouldBe true
|
||||
|
||||
test("connection timeout is a transient resolution error"):
|
||||
val err = cantDownload("Connection timed out")
|
||||
ResolutionRun.isTransientResolutionError(err) shouldBe true
|
||||
|
||||
test("404 is not a transient resolution error"):
|
||||
val err = cantDownload(
|
||||
"Server returned HTTP response code: 404 for URL: https://repo.example.com/org/mod/1.0/mod-1.0.pom"
|
||||
)
|
||||
ResolutionRun.isTransientResolutionError(err) shouldBe false
|
||||
Loading…
Reference in New Issue