Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

A borrowed resource can postpone its termination

オープン
#291 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

@iRevive がすでに取り組んでいます。

2021年11月10日 から。

  • #293 @iRevive による — オープン

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
45/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
停滞
技術スタック
scala
領域
backend

調査の方向性

まず、keypool リポジトリでプールのファイナライズと借用リソースのライフサイクルに関するコードを見つけます。IO.never のケースを含め、issue の Scala 例を再現し、プールが閉じられた後に借用リソースがどのように追跡されるかを調べます。プールのファイナライズが完了する前に借用された接続が破棄およびクローズされ、期待される出力と一致すれば完了です。

索引モデルが issue の本文から書いたものです。

説明

keypool version: 0.4.7

When a resource is borrowed from the pool, it's not a part of the PoolMap anymore. Hence it will not be destroyed during the finalization of the pool.
The resource will be open until it's not completed itself. Thus IO.never as a part of the operation with the resource can hang the whole system.

Example:

sealed trait Key
case object Key extends Key

class Connection(val isOpen: Ref[IO, Boolean])

val pool = KeyPool
  .Builder(
    (_: Key) => IO.ref(true).map(new Connection(_)),
    (conn: Connection) => conn.isOpen.set(false)
  )
  .doOnCreate(conn => IO.println(s"created $conn"))
  .doOnDestroy(conn => IO.println(s"destroyed $conn"))
  .build
  .onFinalize(IO.println("pool was closed"))
  
def example(outerAwait: Deferred[IO, Unit]): IO[FiberIO[(Boolean, Boolean)]] =
  pool.use { p =>
    def job(innerAwait: Deferred[IO, Unit]): IO[(Boolean, Boolean)] =
      p.take(Key).use { managed =>
        val connection = managed.value
        
        for {
          status1 <- connection.isOpen.get
          _       <- IO.println("awaiting inner")
          _       <- innerAwait.complete(())
          _       <- IO.println("awaiting outer")
          _       <- outerAwait.get          // wait for the signal from the outside
          _       <- IO.println("after awaits")
          status2 <- connection.isOpen.get   // isOpen should be 'false' there
          // _ <- IO.never[Unit] // once uncommented the program will hang
        } yield (status1, status2)
      }
      
    for {
      await <- IO.deferred[Unit]
      fiber <- job(await).start
      _     <- await.get // make sure first part happens inside of the open pool
    } yield fiber
  }
  
for {
  await   <- IO.deferred[Unit]
  fiber   <- example(await)
  _       <- await.complete(()) // pool is closed and we continue execution of the job
  outcome <- fiber.join
  (status1, status2) <- outcome.embedNever
  _                  <- IO.println(s"(pool open): is connection open $status1")
  _                  <- IO.println(s"(pool closed): is connection open $status2")
} yield ()

Output:

created Connection@76426537
awaiting inner
awaiting outer
pool was closed
after awaits
destroyed Connection@76426537
(pool open): is connection open true
(pool closed): is connection open true

Expected output:

created Connection@76426537
awaiting inner
awaiting outer
destroyed Connection@76426537
pool was closed
after awaits
(pool open): is connection open true
(pool closed): is connection open false
主要言語
Scala
スター
40
フォーク
19
平均マージ
15日 2時間
マージ済み PR(30日)
3

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

typelevel/keypool のほかの issue

typelevel/keypool の issue をすべて見る

似ている issue

Scala の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。