# Simple async pool driver for postgress. # Inspired by: https://github.com/treeform/pg/ when (NimMajor, NimMinor) < (1, 4): {.push raises: [Defect].} else: {.push raises: [].} import std/sequtils, stew/results, chronicles, chronos import ../../driver, ./connection logScope: topics = "postgres asyncpool" type PgAsyncPoolState {.pure.} = enum Closed, Live, Closing type PgDbConn = object dbConn: DbConn busy: bool open: bool insertStmt: SqlPrepared type # Database connection pool PgAsyncPool* = ref object connString: string maxConnections: int state: PgAsyncPoolState conns: seq[PgDbConn] proc new*(T: type PgAsyncPool, connString: string, maxConnections: int): T = let pool = PgAsyncPool( connString: connString, maxConnections: maxConnections, state: PgAsyncPoolState.Live, conns: newSeq[PgDbConn](0) ) return pool func isLive(pool: PgAsyncPool): bool = pool.state == PgAsyncPoolState.Live func isBusy(pool: PgAsyncPool): bool = pool.conns.mapIt(it.busy).allIt(it) proc close*(pool: PgAsyncPool): Future[Result[void, string]] {.async.} = ## Gracefully wait and close all openned connections if pool.state == PgAsyncPoolState.Closing: while pool.state == PgAsyncPoolState.Closing: await sleepAsync(0.milliseconds) # Do not block the async runtime return ok() pool.state = PgAsyncPoolState.Closing # wait for the connections to be released and close them, without # blocking the async runtime if pool.conns.anyIt(it.busy): while pool.conns.anyIt(it.busy): await sleepAsync(0.milliseconds) for i in 0..