Skip to content

Commit

Permalink
Fix ZPool hangs during parallel item acquisition after invalidation (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
daemas committed May 21, 2024
1 parent ee8c132 commit 83940e8
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 1 deletion.
14 changes: 14 additions & 0 deletions core-tests/shared/src/test/scala/zio/ZPoolSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,20 @@ object ZPoolSpec extends ZIOBaseSpec {
value <- count.get
} yield assertTrue(result == 2 && value == 10)
} +
test("reallocate invalidated item on concurrent demand and maxed out pool size") {
ZIO.scoped {
for {
allocated <- Ref.make(0)
finalized <- Ref.make(0)
get = ZIO.acquireRelease(allocated.updateAndGet(_ + 1))(_ => finalized.update(_ + 1))
pool <- ZPool.make(get, 0 to 1, Duration.fromSeconds(100))
getZIO = ZIO.scoped(pool.get.flatMap(pool.invalidate))
_ <- Live.live(ZIO.foreachPar(0 to 9)(_ => getZIO).disconnect.timeout(1.second))
allocatedCount <- allocated.get
finalizedCount <- finalized.get
} yield assertTrue(allocatedCount == 10 && finalizedCount == 10)
}
} +
test("invalidate all items in pool and check that pool.get doesn't hang forever") {
for {
allocated <- Ref.make(0)
Expand Down
2 changes: 1 addition & 1 deletion core/shared/src/main/scala/zio/ZPool.scala
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ object ZPool {
attempted.forEach(a => invalidated.update(_ - a)) *>
attempted.finalizer *>
state.modify { case State(size, free) =>
if (size <= range.start)
if (size <= range.start || free < 0)
allocate -> State(size, free + 1)
else
ZIO.unit -> State(size - 1, free)
Expand Down

0 comments on commit 83940e8

Please sign in to comment.