概要
前回の記事では、
ZIOのScopeについて簡単に共有しました。
今回の記事では、より実績的なScopeの有効期間の制御例について共有させていただきます。
Scopeの動的な有効期間について
Scopeの有効期間は動的です。
Scopeを必要とするZIOエフェクトがある場合、それをflatMapして新しいエフェクトを作成できます。
新しいZIOエフェクトは元のScopeの有効期間を延長します。
したがって、Scopeを閉じない限り、リソースは解放されず、Scopeを閉じるまでリソースはどんどん大きくなります。
Scopeが延長される例
以下のサンプルプログラムは、使い終わったら削除されるような一時ファイルtmpFileをScopeによって取り扱ったものです。
checkFileExistsでファイルが存在するかどうか(Scopeが閉じられたかどうか)が確認できるようになっています。
import zio.*
import java.io.File
object Main extends ZIOAppDefault:
val PathToFile = "/tmp/tmp.txt"
def tmpFile: ZIO[Scope, Throwable, Unit] = for {
file <- ZIO.acquireRelease(
ZIO.attemptBlocking {
val file = new File(PathToFile)
file.createNewFile()
file
}
)(deleteFile)
} yield ()
def deleteFile(file: File): UIO[Unit] =
ZIO.attemptBlocking(file.delete()).orDie.unit
def checkFileExists: Task[Unit] = for {
exists <- ZIO.attemptBlocking(new File(PathToFile).exists())
_ <- Console.printLine(exists)
} yield ()
override def run: ZIO[ZIOAppArgs & Scope, Any, Any] =
for {
_ <- ZIO.debug("開始")
_ <- tmpFile
_ <- checkFileExists
_ <- ZIO.debug("終了")
_ <- checkFileExists
} yield ()
開始
true
終了
true
$ pwd
/tmp
$ ls | grep 'tmp.txt'
実行結果およびlsコマンドの結果より、
一時ファイルは作られてからプログラム終了時まで存在し続けていたことが示唆されます。
Scope#scopedでScopeを閉じる
次にサンプルプログラムを改変して、以下のようにtmpFileをZIO.scopedで包むようにしてみます。
これによりtmpFileのScopeが延長されないようになります。
override def run: ZIO[ZIOAppArgs & Scope, Any, Any] =
for {
_ <- ZIO.debug("開始")
_ <- ZIO.scoped(tmpFile)
_ <- checkFileExists
_ <- ZIO.debug("終了")
_ <- checkFileExists
} yield ()
開始
false
終了
false
実行結果よりZIO.scoped(tmpFile)以降の処理ではファイルが存在しない(Scopeが閉じられた)ことが確認できます。