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),
 * `migrate` / `skipMigrations` (explicit migration mode), and
 * `skipVersionCheck` options.
 */
export type PostgresPoolConfig = PgPoolConfig & {
    schema?: string;
    skipVersionCheck?: boolean;
    migrate?: boolean;
    skipMigrations?: 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 and exposes
 * {@link PostgresConnection.waitUntilReady} 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 readonly migrateOnConnect;
    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 compatible.
     *
     * Idempotent and memoized. By default this only reads the migration ledger.
     * When `migrate: true` was configured, migrations run on one checked-out
     * client so their advisory lock and transaction share a session.
     */
    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>;
}
