Files
travel-app/node_modules/bullmq/dist/esm/postgres/postgres-connection.d.ts
2026-08-09 21:56:00 +00:00

134 lines
6.0 KiB
TypeScript

import { EventEmitter } from 'events';
import { PgListenClient, PgPool, PgPoolConfig } from './pg-types';
/**
* A node-postgres pool config / connection string, optionally carrying the
* BullMQ-specific `schema` (the connection-level namespace for all queues) and
* `skipVersionCheck` (bypass the minimum-server-version assertion).
*/
export type PostgresPoolConfig = PgPoolConfig & {
schema?: string;
skipVersionCheck?: boolean;
};
/**
* What the user may pass as the PostgreSQL `connection` option:
*
* - an already-constructed `pg.Pool` instance (we use it as-is and do NOT close
* it on `close()` — the caller owns its lifecycle), or
* - a node-postgres pool config / connection string (we lazily `require('pg')`
* and construct the pool ourselves, owning its lifecycle).
*
* The optional `schema` (the namespace for all queues) is only read from the
* **config-object** form, because that is the only case where we build the pool
* ourselves and can pin each connection's `search_path` to it. A bare
* connection string or an already-constructed `pg.Pool` always uses
* {@link DEFAULT_SCHEMA} — a raw pool cannot carry a `schema`, and we cannot set
* the `search_path` on a pool we did not create. To select a different schema,
* pass a config object (a connection string can be wrapped as
* `{ connectionString, schema }`; a pre-built pool must be configured with the
* desired `search_path` by the caller).
*/
export type PostgresConnectionOptions = PgPool | PostgresPoolConfig | string;
/**
* Owns the PostgreSQL connection resources for a single backend:
*
* - a `pg.Pool` for regular, short-lived queries, and
* - a dedicated, long-lived `LISTEN` client used by the blocking
* "wait for job" primitive (lazily established).
*
* Lifecycle mirrors {@link RedisConnection}: it is an {@link EventEmitter} that
* surfaces normalized `'ready' | 'error' | 'close'` events, exposes
* {@link PostgresConnection.waitUntilReady} (which also runs the schema
* migrations exactly once, on a dedicated checked-out client) and
* {@link PostgresConnection.close}.
*/
export declare class PostgresConnection extends EventEmitter {
readonly pool: PgPool;
/**
* The PostgreSQL schema (namespace) this connection's queues live in. It is
* applied to every pooled connection's `search_path`, so the `.sql` command
* files (and the operation functions) reference unqualified names and stay
* portable — the schema selects the namespace, never the SQL itself.
*/
readonly schema: string;
/**
* `true` when this instance constructed the pool (and must therefore close
* it). `false` when the user passed in their own `pg.Pool`.
*/
private readonly ownsPool;
/**
* When `true`, the minimum-server-version assertion in {@link runMigrations}
* is skipped. Only settable via a config object (a raw `pg.Pool` or a bare
* connection string always run the check).
*/
private readonly skipVersionCheck;
private readyPromise;
private closing;
private listenClient;
/**
* Memoizes the in-flight {@link PostgresConnection.getListenClient}
* establishment so concurrent first-callers (e.g. a backend naming its
* connection in `waitUntilReady` while its consume loop also asks for the
* LISTEN client) all share one connection instead of each opening a
* duplicate.
*/
private listenClientPromise;
/**
* When this instance owns the pool, the lazily-required `pg` module and the
* resolved client config (with the pinned `search_path`) used to build a
* *dedicated standalone* `LISTEN` connection — so a long-lived `LISTEN` never
* consumes a pool slot. Undefined when the user passed their own `pg.Pool`
* (then the `LISTEN` client is checked out of that pool instead).
*/
private readonly pgModule;
private readonly listenClientConfig;
/**
* `true` when {@link listenClient} is a standalone `pg.Client` we must `end()`
* (owned pool); `false` when it is a pooled client we must `release()`.
*/
private listenClientIsStandalone;
constructor(connection: PostgresConnectionOptions);
/**
* Forwards an underlying pool / LISTEN-client error as this connection's
* `'error'` event, but only when a listener is attached. `EventEmitter.emit`
* throws when emitting `'error'` with no listeners, so an unguarded forward
* would turn an idle-client error into a hard process crash. Mirrors the
* guard in {@link RedisConnection}.
*/
private emitError;
/**
* Resolves once the pool is reachable and the schema is up to date.
*
* Idempotent and memoized: the migration runs exactly once per connection,
* on a single dedicated client checked out of the pool (so the migration's
* advisory lock and transaction share one session — see {@link runMigrations}).
*/
waitUntilReady(): Promise<void>;
private bootstrap;
/**
* Returns the dedicated client used for `LISTEN`/`NOTIFY`, establishing it on
* first use.
*
* When this connection owns the pool we use a *standalone* `pg.Client` (its
* own dedicated TCP connection) so the long-lived `LISTEN` never consumes a
* pool slot — this is what lets the query pool run at `max: 1` without
* deadlocking. When the user supplied their own `pg.Pool` we check a client
* out of it (so such pools should be sized `>= 2`).
*/
getListenClient(): Promise<PgListenClient>;
/**
* Truthy once {@link PostgresConnection.close} has begun.
*/
get isClosing(): Promise<void> | undefined;
/**
* Closes the connection: releases the `LISTEN` client and (if owned) ends the
* pool. Safe to call multiple times.
*/
close(): Promise<void>;
/**
* Forcibly tears down the connection. For PostgreSQL there is no distinct
* "disconnect without waiting" semantics beyond closing, so this delegates to
* {@link PostgresConnection.close}.
*/
disconnect(): Promise<void>;
}