glimr_postgres/db/pool

PostgreSQL Connection Pool

Opening a new PostgreSQL connection per query adds TCP handshake and authentication overhead on every request. A pool keeps a fixed set of connections open and lends them out on demand, so queries execute against already- authenticated sockets and callers never need to manage connection lifecycle themselves.

Types

Re-exporting pog.Connection under a local alias lets the rest of the codebase reference Connection without depending on pog directly, so swapping the underlying driver only requires changes here.

pub type Connection =
  pog.Connection

Re-exporting DbError here keeps downstream modules from importing db just for the error type, reducing coupling to the framework internals.

pub type DbError =
  db.DbError

The pool must be opaque so callers can’t bypass the checkout/checkin protocol by accessing the raw connections directly. Storing closures rather than an Erlang PID keeps the Erlang pool internals hidden from Gleam code.

pub opaque type Pool

The Erlang FFI returns closures that capture the pool handle internally, so a named record type is needed to receive them across the FFI boundary. This stays public so the FFI module can construct it.

pub type PoolOps {
  PoolOps(
    checkout: fn() -> Result(
      #(pog.Connection, fn() -> Nil),
      String,
    ),
    stop: fn() -> Nil,
  )
}

Constructors

  • PoolOps(
      checkout: fn() -> Result(#(pog.Connection, fn() -> Nil), String),
      stop: fn() -> Nil,
    )

Values

pub fn get_connection(
  pool: Pool,
  f: fn(pog.Connection) -> a,
) -> a

A callback-based API guarantees the connection is returned to the pool even if the function crashes, preventing connection leaks that would eventually exhaust the pool under sustained traffic.

pub fn raw_checkout(
  pool: Pool,
) -> #(
  fn() -> Result(#(pog.Connection, fn() -> Nil), String),
  fn() -> Nil,
)

The framework’s driver-agnostic Pool vtable needs the raw checkout and stop closures to wire PostgreSQL into the shared db interface. Returning a tuple avoids exposing the opaque Pool internals.

pub fn start_pool(config: db.Config) -> Result(Pool, db.DbError)

Wrapping the FFI result in the opaque Pool type ensures callers interact with the pool only through the public API. The Config is validated inside start, so errors from misconfiguration surface here rather than later.

pub fn stop_pool(pool: Pool) -> Nil

PostgreSQL connections hold server-side resources (memory, process slots) that aren’t released until the connection closes. Stopping the pool explicitly frees those resources instead of waiting for the BEAM process to exit.

Search Document