bath

Types

An error returned when failing to apply a function to a pooled resource.

pub type ApplyError {
  NoResourcesAvailable
  CheckOutResourceCreateError(error: String)
}

Constructors

  • NoResourcesAvailable
  • CheckOutResourceCreateError(error: String)

Configuration for a Pool.

pub opaque type Builder(resource_type)

The strategy used to check out a resource from the pool.

pub type CheckoutStrategy {
  FIFO
  LIFO
}

Constructors

  • FIFO
  • LIFO

How to create resources in the pool. Lazy will create resources when required (i.e. the pool is empty but has extra capacity), while Eager will create the maximum number of resources upfront.

pub type CreationStrategy {
  Lazy
  Eager
}

Constructors

  • Lazy
  • Eager

A message sent to the pool actor.

pub opaque type Msg(resource_type)

The type used to indicate what to do with a resource after use.

pub opaque type Next(return)

An error returned when the resource pool fails to shut down.

pub type ShutdownError {
  ResourcesInUse
}

Constructors

  • ResourcesInUse

    There are still resources checked out. Ignore this failure case by calling shutdown function with force set to True.

Pool actor state.

pub opaque type State(resource_type)

Values

pub fn apply(
  pool pool: process.Subject(Msg(resource_type)),
  timeout timeout: Int,
  next next: fn(resource_type) -> Next(result_type),
) -> Result(result_type, ApplyError)

Check out a resource from the pool, apply the next function, then check the resource back in.

let assert Ok(pool) =
  bath.new(fn() { Ok("Some pooled resource") })
  |> bath.start(1000)

use resource <- bath.apply(pool, 1000)

// Do stuff with resource...

// Return the resource to the pool, returning "Hello!" to the caller.
bath.keep()
|> bath.returning("Hello!")
pub fn checkout_strategy(
  builder builder: Builder(resource_type),
  strategy checkout_strategy: CheckoutStrategy,
) -> Builder(resource_type)

Change the checkout strategy for the pool. Defaults to FIFO.

pub fn creation_strategy(
  builder builder: Builder(resource_type),
  strategy creation_strategy: CreationStrategy,
) -> Builder(resource_type)

Change the resource creation strategy for the pool. Defaults to Lazy.

pub fn discard() -> Next(Nil)

Instruct Bath to discard the checked out resource, running the shutdown function on it.

Discarded resources will be recreated lazily, regardless of the pool’s creation strategy.

pub fn keep() -> Next(Nil)

Instruct Bath to keep the checked out resource, returning it to the pool.

pub fn log_errors(
  builder builder: Builder(resource_type),
  log_errors log_errors: Bool,
) -> Builder(resource_type)

Set whether the pool logs errors when resources fail to create.

pub fn name(
  builder builder: Builder(resource_type),
  name name: process.Name(Msg(resource_type)),
) -> Builder(resource_type)

Set the name for the pool process. Defaults to None.

You will need to provide a name if you plan on using the pool under a static supervisor.

pub fn new(
  resource create_resource: fn() -> Result(resource_type, String),
) -> Builder(resource_type)

Create a new Builder for creating a pool of resources.

import bath
import fake_db

pub fn main() {
  // Create a pool of 10 connections to some fictional database.
  let assert Ok(pool) =
    bath.new(fn() { fake_db.connect() })
    |> bath.with_size(10)
    |> bath.start(1000)
}

Default values

ConfigDefault
nameoption.None
size10
shutdown_resourcefn(_resource) { Nil }
checkout_strategyFIFO
creation_strategyLazy
log_errorsFalse
pub fn on_shutdown(
  builder builder: Builder(resource_type),
  shutdown shutdown_resource: fn(resource_type) -> Nil,
) -> Builder(resource_type)

Set a shutdown function to be run for each resource when the pool exits.

pub fn returning(next: Next(old), value: new) -> Next(new)

Return a value from a use of apply.

pub fn shutdown(
  pool pool: process.Subject(Msg(resource_type)),
  force force: Bool,
  timeout timeout: Int,
) -> Result(Nil, ShutdownError)

Shut down the pool, calling the shutdown function on each resource in the pool. Calling with force set to True will force the shutdown, not calling the shutdown function on any resources.

Will fail if there are still resources checked out, unless force is True.

You only need to call this when using unsupervised pools. You should let your supervision tree handle the shutdown of supervised resource pools.

pub fn size(
  builder builder: Builder(resource_type),
  size size: Int,
) -> Builder(resource_type)

Set the pool size. Defaults to 10. Will be clamped to a minimum of 1.

pub fn start(
  builder builder: Builder(resource_type),
  timeout init_timeout: Int,
) -> Result(process.Subject(Msg(resource_type)), actor.StartError)

Start an unsupervised pool using the given Builder and return a Pool. In most cases, you should use the supervised function instead.

pub fn supervised(
  builder builder: Builder(resource_type),
  timeout init_timeout: Int,
) -> supervision.ChildSpecification(
  process.Subject(Msg(resource_type)),
)

Return the ChildSpecification for creating a supervised resource pool.

In order to use a supervised pool, your pool must be named, otherwise you will not be able to send messages to your pool. See the name function.

Example

import bath
import gleam/erlang/process
import gleam/otp/static_supervisor as supervisor

fn main() {
  // Create a name to interact with the pool once it's started under the
  // static supervisor.
  let pool_name = process.new_name("bath_pool")

  let assert Ok(_started) =
    supervisor.new(supervisor.OneForOne)
    |> supervisor.add(
      bath.new(create_resource)
      |> bath.name(pool_name)
      |> bath.supervised(1000)
    )
    |> supervisor.start

  let pool = process.named_subject(pool_name)

  // Do more stuff...
}
pub fn supervised_map(
  builder builder: Builder(resource_type),
  using mapper: fn(process.Subject(Msg(resource_type))) -> a,
  timeout init_timeout: Int,
) -> supervision.ChildSpecification(a)

Like supervised, but allows you to pass a mapping function to transform the pool return value to the receiver. This is mostly useful for library authors who wish to use Bath to create a pool of resources.

Search Document