Skip to content

Commit

Permalink
Merge pull request #397 from eed3si9n/wip/retry
Browse files Browse the repository at this point in the history
fix: Retry to retry non-IOException
  • Loading branch information
eed3si9n authored Jan 2, 2025
2 parents 88fbe96 + e4da4c5 commit 24e2813
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 13 deletions.
4 changes: 3 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,9 @@ val io = (project in file("io"))
commonSettings,
name := "IO",
libraryDependencies ++= {
Vector(scalaCompiler.value % Test, scalaCheck % Test, scalatest % Test)
Vector(scalaCompiler.value % Test, scalaVerify % Test, scalaCheck % Test, scalatest % Test)
} ++ Vector(swovalFiles),
testFrameworks += new TestFramework("verify.runner.Framework"),
Test / fork := System.getProperty("sbt.test.fork", "false") == "true",
Test / testForkedParallel := true,
Compile / generateContrabands / sourceManaged := baseDirectory.value / "src" / "main" / "contraband-scala",
Expand All @@ -106,6 +107,7 @@ val io = (project in file("io"))
"1.7.0",
"1.8.0",
"1.9.0",
"1.10.0",
) map (version => organization.value %% moduleName.value % version)
}),
mimaBinaryIssueFilters ++= Seq(
Expand Down
12 changes: 6 additions & 6 deletions io/src/main/scala/sbt/internal/io/Retry.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,33 @@ private[sbt] object Retry {
try System.getProperty("sbt.io.retry.limit", defaultLimit.toString).toInt
catch { case NonFatal(_) => defaultLimit }
}
private[sbt] def apply[@specialized T](f: => T, excludedExceptions: Class[? <: IOException]*): T =
private[sbt] def apply[@specialized T](f: => T, excludedExceptions: Class[? <: Throwable]*): T =
apply(f, limit, excludedExceptions: _*)
private[sbt] def apply[@specialized T](
f: => T,
limit: Int,
excludedExceptions: Class[? <: IOException]*,
excludedExceptions: Class[? <: Throwable]*,
): T = apply(f, limit, 100, excludedExceptions: _*)
private[sbt] def apply[@specialized T](
f: => T,
limit: Int,
sleepInMillis: Long,
excludedExceptions: Class[? <: IOException]*,
excludedExceptions: Class[? <: Throwable]*,
): T = {
require(limit >= 1, "limit must be 1 or higher: was: " + limit)
def filter(e: Exception): Boolean = excludedExceptions match {
def filter(e: Throwable): Boolean = excludedExceptions match {
case s if s.nonEmpty =>
!excludedExceptions.exists(_.isAssignableFrom(e.getClass))
case _ =>
true
}
var attempt = 1
var firstException: IOException = null
var firstException: Throwable = null
while (attempt <= limit) {
try {
return f
} catch {
case e: IOException if filter(e) =>
case NonFatal(e) if filter(e) =>
if (firstException == null) firstException = e
// https://github.com/sbt/io/issues/295
// On Windows, we're seeing java.nio.file.AccessDeniedException with sleep(0).
Expand Down
17 changes: 12 additions & 5 deletions io/src/test/scala/sbt/internal/io/RetrySpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@ package sbt.internal.io
import java.io.IOException
import java.util.concurrent.atomic.AtomicInteger

import org.scalatest.flatspec.AnyFlatSpec

final class RetrySpec extends AnyFlatSpec {
object RetrySpec extends verify.BasicTestSuite {
private val noExcluded: List[Class[? <: IOException]] = List[Class[? <: IOException]]()
"retry" should "throw first exception after number of failures" in {
test("retry should throw first exception after number of failures") {
val i = new AtomicInteger()
def throww(): Any = throw new IOException(i.incrementAndGet().toString)
try {
Expand All @@ -31,7 +29,7 @@ final class RetrySpec extends AnyFlatSpec {
}
}

"retry" should "throw recover" in {
test("retry should throw recover") {
for (recoveryStep <- (1 to 14)) {
val i = new AtomicInteger()
val value = Retry(
Expand All @@ -46,4 +44,13 @@ final class RetrySpec extends AnyFlatSpec {
assert(value == "recover")
}
}

test("retry should recover from non-IO exceptions") {
val i = new AtomicInteger()
def throww(): Any =
if (i.incrementAndGet() == 5) 0
else ???
Retry(throww())
()
}
}
1 change: 1 addition & 0 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ object Dependencies {
"org.scala-lang" % "scala-compiler" % v
}

val scalaVerify = "com.eed3si9n.verify" %% "verify" % "1.0.0"
val scalaCheck = "org.scalacheck" %% "scalacheck" % "1.18.1"
val scalatest = "org.scalatest" %% "scalatest" % "3.2.19"
val swovalFiles = "com.swoval" % "file-tree-views" % "2.1.12"
Expand Down
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.9.8
sbt.version=1.10.7

0 comments on commit 24e2813

Please sign in to comment.