tpolecat / pool-party   0.0.4

MIT License GitHub

Turn a normal resource into a pooled one.

Scala versions: 3.x 2.13
Scala.js versions: 1.x

Pool Party!

Discord Maven Central Javadocs

Pool full of scary monsters.

Pool Party is a Scala micro-library that turns a regular cats.effect.Resource into a non-blocking, fixed-size pooled resource with optional health checking and event reporting. This is pre-release software so it may cause your data center to burn down or (worse) not burn down. Either way it's not my problem.

Pool Party is published for Scala 2.13/3.0 and you can include it in your project thus:

libraryDependencies += "org.tpolecat" %% "pool-party" % <version>

Usage

PooledResourceBuilder builds a resource that yields a pooled version of some other underlying resource that you provide.

val r: Resource[F, Woozle] = ... // A limited resource

PooledResourceBuilder.of(r, 10).build.use { pool =>
  // `pool` has the same apparent behavior as `r`, but will never allow more than
  // 10 concurrent `Woozle`s, which will be recycled and reused on return.
}

In most cases you will create a pool when your program starts, and it will not be finalized until the program shuts down. In the common case for a web app your IOApp.run will look something like:

// A server is usually a resource you hang onto until someone hits ^C.
def run(args: List[String]): IO[ExitCode] =
  runResource[IO](args).use(_ => IO.never)

// That resource is the composition of many things, including our pool.
def runResource[F[_]: Temporal: OtherStuff](args: List[String]): Resource[F, ExitCode] =
  for {
    ...
    pool <- PoolBuilder.of(...).withHealthCheck(...).withReporter(...).build
    ...  <- httpServerResource(pool, etc) // request handler can say pool.use
  } yield ExitCode.Success

What you don't want to do is create a new pool for each request. It's a common error that defeats the purpose of pooling.

Configuration

In addition to the pool size (required), PooledResourceBuilder provides the following configurable properties:

Property Type Explanation
HealthCheck A => F[Boolean] Check the health of a pooled instance after it's returned to the pool, and perform any necessary cleanup. Yield false if the instance should be finalized and discarded. Default behavior always yields true.
ShutdownTimeout FiniteDuration Amount of time to wait for pooled instances to be finalized when the pool shuts down by leaving .use scope. Default is Long.MaxValue.ns (~292 years).
Reporter PoolEvent[A] => F[Unit] Callback that will receive events about the pool's lifecycle, including error conditions that you probably want to know about. So it's usually a good idea to specify this. The default behavior does nothing.

Note that the Reporter is invoked synchronously so it should not do anything time-consuming. A production reporter might enqueue events for later asynchronous processing.

Getting Help

First check out the Scaladoc, and if you're still in trouble please open an issue or find me on the Typelevel Discord.