scalaadvanced
Cats Effect Resource Management
Manage resources safely with Cats Effect Resource: acquire-release, composition, and lifecycle.
scalaPress ⌘/Ctrl + Shift + C to copy
import cats.effect.*
import cats.syntax.all.*
// Simulated resources
class DatabaseConnection(url: String):
def query(sql: String): IO[List[String]] =
IO.println(s" Query: $sql") *> IO.pure(List("row1", "row2"))
def close(): IO[Unit] = IO.println(s" Closed DB: $url")
class HttpClient(name: String):
def get(url: String): IO[String] =
IO.pure(s"Response from $url")
def close(): IO[Unit] = IO.println(s" Closed HTTP: $name")
class Cache(name: String):
private val store = scala.collection.mutable.Map.empty[String, String]
def get(key: String): IO[Option[String]] = IO(store.get(key))
def put(key: String, value: String): IO[Unit] = IO(store(key) = value)
def close(): IO[Unit] = IO.println(s" Closed Cache: $name")
// Resource definitions
def mkDatabase(url: String): Resource[IO, DatabaseConnection] =
Resource.make(
IO.println(s" Opening DB: $url") *> IO(new DatabaseConnection(url))
)(_.close())
def mkHttpClient(name: String): Resource[IO, HttpClient] =
Resource.make(
IO.println(s" Creating HTTP: $name") *> IO(new HttpClient(name))
)(_.close())
def mkCache(name: String): Resource[IO, Cache] =
Resource.make(
IO.println(s" Init Cache: $name") *> IO(new Cache(name))
)(_.close())
// Composed resources
case class AppResources(
db: DatabaseConnection,
http: HttpClient,
cache: Cache
)
def mkAppResources: Resource[IO, AppResources] =
for
db <- mkDatabase("postgres://localhost/myapp")
http <- mkHttpClient("main")
cache <- mkCache("app")
yield AppResources(db, http, cache)
// Parallel resource acquisition
def mkAppResourcesPar: Resource[IO, AppResources] =
(
mkDatabase("postgres://localhost/myapp"),
mkHttpClient("main"),
mkCache("app")
).parMapN(AppResources.apply)
// Resource with finalizer ordering
def orderedResources: Resource[IO, Unit] =
for
_ <- Resource.make(IO.println(" Acquire A"))(_ => IO.println(" Release A"))
_ <- Resource.make(IO.println(" Acquire B"))(_ => IO.println(" Release B"))
_ <- Resource.make(IO.println(" Acquire C"))(_ => IO.println(" Release C"))
yield () // Released in reverse: C, B, A
object ResourceApp extends IOApp.Simple:
def run: IO[Unit] = for
// Single resource
_ <- IO.println("=== Single Resource ===")
_ <- mkDatabase("test").use { db =>
db.query("SELECT 1").flatMap(r => IO.println(s" Result: $r"))
}
// Composed resources
_ <- IO.println("\n=== Composed Resources ===")
_ <- mkAppResources.use { app =>
for
rows <- app.db.query("SELECT * FROM users")
resp <- app.http.get("https://api.example.com")
_ <- app.cache.put("key", resp)
v <- app.cache.get("key")
_ <- IO.println(s" DB: $rows, Cache: $v")
yield ()
}
// Ordering demo
_ <- IO.println("\n=== Release Order ===")
_ <- orderedResources.use(_ => IO.println(" Using all resources"))
// Error safety
_ <- IO.println("\n=== Error Safety ===")
_ <- mkDatabase("error-test").use { db =>
IO.raiseError(RuntimeException("Boom!"))
}.handleError(e => IO.println(s" Caught: ${e.getMessage}"))
yield ()Use Cases
- Safe resource lifecycle management
- Composed service initialization
- Error-safe cleanup guarantees
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
scalaadvanced
Cats Effect IO Monad Basics
Use Cats Effect IO for pure functional effects: sequencing, error handling, resource management.
Best for: Pure functional effect management
#scala#cats-effect
scalaintermediate
Resource Management with Using
Manage resources safely with Using, try-with-resources, bracket pattern, and Cats Resource.
Best for: Safe file handling
#scala#resource
scalabeginner
Scala Hello World Application
Create a basic Scala application with main method, string interpolation, and val/var basics.
Best for: Getting started with Scala
#scala#basics
scalabeginner
Pattern Matching Fundamentals
Use Scala pattern matching with guards, type patterns, tuple patterns, and nested extractors.
Best for: Control flow with pattern matching
#scala#pattern-matching