Skip to content

Commit af6cfcb

Browse files
Fix retry inside handleErrorWith (#50)
* Fix retry inside handleErrorWith TxnRetryException (control-flow from scheduleRetry) was caught by the generic handleErrorWith in the TxnHandleError compiler case, causing `(retry).handleErrorWith(...)` to fail instead of retrying. Re-raise TxnRetryException before falling through to the error handler. * Fix scalafmt formatting
1 parent 6784d32 commit af6cfcb

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

src/main/scala/bengal/stm/runtime/TxnCompilerContext.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,9 @@ private[stm] trait TxnCompilerContext[F[_]] {
255255
case _ =>
256256
Async[F].pure(originalResult)
257257
}
258-
} yield (finalResult._1, finalResult._2)).handleErrorWith { ex =>
259-
s.raiseError(ex).map((_, ().asInstanceOf[V]))
258+
} yield (finalResult._1, finalResult._2)).handleErrorWith {
259+
case ex: TxnRetryException => Async[F].raiseError(ex)
260+
case ex => s.raiseError(ex).map((_, ().asInstanceOf[V]))
260261
}
261262
}
262263
case _ =>

src/test/scala/runtime/TxnCompilerContextSpec.scala

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,39 @@ class TxnCompilerContextSpec extends AsyncFreeSpec with AsyncIOSpec with Matcher
210210
}
211211
.asserting(_ shouldBe "recovered")
212212
}
213+
214+
"retry propagates through handleErrorWith" in {
215+
STM
216+
.runtime[IO]
217+
.flatMap { implicit stm =>
218+
for {
219+
tVar <- TxnVar.of(0)
220+
readerFiber <- (for {
221+
v <- tVar.get
222+
_ <- STM[IO].waitFor(v > 0)
223+
} yield v)
224+
.handleErrorWith(_ => STM[IO].pure(-1))
225+
.commit
226+
.start
227+
_ <- tVar.set(42).commit
228+
result <- readerFiber.joinWithNever
229+
} yield result
230+
}
231+
.asserting(_ shouldBe 42)
232+
}
233+
234+
"handleErrorWith still recovers real errors" in {
235+
STM
236+
.runtime[IO]
237+
.flatMap { implicit stm =>
238+
STM[IO]
239+
.abort(new RuntimeException("boom"))
240+
.flatMap(_ => STM[IO].pure("unreachable"))
241+
.handleErrorWith(_ => STM[IO].pure("recovered"))
242+
.commit
243+
}
244+
.asserting(_ shouldBe "recovered")
245+
}
213246
}
214247

215248
"pure/delay transaction" - {

0 commit comments

Comments
 (0)