mirror of https://github.com/sbt/sbt.git
retry publish on all 5XX errors
This commit is contained in:
parent
39090fa0d3
commit
07e3815261
|
|
@ -31,8 +31,14 @@ private[sbt] object IvyUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Currently transient network errors are defined as:
|
||||||
|
* - a network timeout
|
||||||
|
* - all server errors (response code 5xx)
|
||||||
|
* - rate limiting (response code 429)
|
||||||
|
*/
|
||||||
object TransientNetworkException {
|
object TransientNetworkException {
|
||||||
private val _r = """.*HTTP response code: (503|429).*""".r
|
private val _r = """.*HTTP response code: (5\d{2}|408|429).*""".r
|
||||||
|
|
||||||
@inline private def check(s: String): Boolean = {
|
@inline private def check(s: String): Boolean = {
|
||||||
if (s == null) return false
|
if (s == null) return false
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
package sbt.internal.librarymanagement
|
||||||
|
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
import org.scalatest.FunSuite
|
||||||
|
import sbt.internal.librarymanagement.IvyUtil._
|
||||||
|
|
||||||
|
class IvyUtilSpec extends FunSuite {
|
||||||
|
test("503 should be a TransientNetworkException") {
|
||||||
|
val statusCode503Exception =
|
||||||
|
new IOException("Server returned HTTP response code: 503 for URL:")
|
||||||
|
assert(TransientNetworkException(statusCode503Exception))
|
||||||
|
}
|
||||||
|
|
||||||
|
test("500 should be a TransientNetworkException") {
|
||||||
|
val statusCode500Exception =
|
||||||
|
new IOException("Server returned HTTP response code: 500 for URL:")
|
||||||
|
assert(TransientNetworkException(statusCode500Exception))
|
||||||
|
}
|
||||||
|
|
||||||
|
test("408 should be a TransientNetworkException") {
|
||||||
|
val statusCode408Exception =
|
||||||
|
new IOException("Server returned HTTP response code: 408 for URL:")
|
||||||
|
assert(TransientNetworkException(statusCode408Exception))
|
||||||
|
}
|
||||||
|
|
||||||
|
test("429 should be a TransientNetworkException") {
|
||||||
|
val statusCode429Exception =
|
||||||
|
new IOException(" Server returned HTTP response code: 429 for URL:")
|
||||||
|
assert(TransientNetworkException(statusCode429Exception))
|
||||||
|
}
|
||||||
|
|
||||||
|
test("404 should not be a TransientNetworkException") {
|
||||||
|
val statusCode404Exception =
|
||||||
|
new IOException("Server returned HTTP response code: 404 for URL:")
|
||||||
|
assert(!TransientNetworkException(statusCode404Exception))
|
||||||
|
}
|
||||||
|
|
||||||
|
test("IllegalArgumentException should not be a TransientNetworkException") {
|
||||||
|
val illegalArgumentException = new IllegalArgumentException()
|
||||||
|
assert(!TransientNetworkException(illegalArgumentException))
|
||||||
|
}
|
||||||
|
|
||||||
|
test("it should retry for 3 attempts") {
|
||||||
|
var i = 0
|
||||||
|
def f: Int = {
|
||||||
|
i += 1
|
||||||
|
if (i < 3) throw new RuntimeException() else i
|
||||||
|
}
|
||||||
|
// exception predicate retries on all exceptions for this test
|
||||||
|
val result = retryWithBackoff(f, _ => true, maxAttempts = 3)
|
||||||
|
assert(result == 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("it should fail after maxAttempts") {
|
||||||
|
var i = 0
|
||||||
|
def f: Int = {
|
||||||
|
i += 1
|
||||||
|
throw new RuntimeException()
|
||||||
|
}
|
||||||
|
intercept[RuntimeException] {
|
||||||
|
retryWithBackoff(f, _ => true, maxAttempts = 3)
|
||||||
|
}
|
||||||
|
assert(i == 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue