/** Seconds. Long enough for a cold cross-region connect, short enough to page. */ export declare const DEFAULT_DATABASE_CONNECT_TIMEOUT_SECONDS = 10; /** * Resolve the connect budget in MILLISECONDS, or `null` when the bound is * disabled. * * Milliseconds because every consumer needs them: `setTimeout` and all four * driver knobs are in ms. Seconds are the operator-facing unit, so the variable * is read as seconds and converted once, here. * * Call this ONCE per connect and pass the result down - it is the only resolver, * so calling it twice would warn twice about one typo. */ export declare function connectTimeoutMillis(): number | null; /** * Clock slack when deciding whether a failed connect was OUR bound expiring. * * THE DECISION IS MADE BY ELAPSED TIME, NEVER BY MATCHING THE DRIVER'S TEXT. * The four clients word an expiry four different ways - pg `timeout expired`, * mysql2 `connect ETIMEDOUT`, tedious `Failed to connect to ... in 2000ms`, * Mongo `Server selection timed out after 2000 ms` - and a marker table would * drift the moment any of them reworded, then MISS. A missed timeout is the * whole defect this file exists to prevent, so nothing here reads the message. * * WHY 50ms, AND WHY NOT ZERO. Python and PHP use no tolerance at all, PHP having * measured its four C clients OVERSHOOTING their deadline by ~3ms at a 3s bound - * a client that measures its own elapsed time can never report early. Node's * knobs are not those: all four are plain JS `setTimeout` calls (pg `client.js`, * mysql2 `base/connection.js`, tedious `connection.js`, and the Mongo driver's * selection loop), and libuv's loop time is coarse, so a Node timer CAN fire * before `performance.now()` agrees the budget has passed. MEASURED, 60 rounds * at a 200ms budget: * * Linux x64, Node v24.18.0 earliest -0.7125ms (fires EARLY) * darwin arm64, Node v24.9.0 earliest +0.0872ms (never early) * * Zero would therefore be a real miss on Linux. 50ms is a ~70x margin on the * measured worst case, and still 0.5% of the 10s default. Ruby's 250ms is for a * different problem - libpq's `connect_timeout` is INTEGER SECONDS and reads a * 10s bound back as 9.998s - which no Node client has. * * It does NOT inflate the operator's N: it only widens what COUNTS as the bound * expiring, never how long anything waits. It errs deliberately: over-translating * a genuine fast failure that lands within 50ms of the bound still shows the * operator the driver's real error (`Driver reported:`, plus `cause`), whereas * under-translating hands them a bare driver message naming no variable. */ export declare const CONNECT_TIMEOUT_TOLERANCE_MS = 50; /** * The value for a driver's own connect-timeout option, from the Tina4 budget. * `null` in, `null` out - a disabled bound sets no driver option at all. * * ROUNDED UP, AND NEVER TO 0. Up, so the driver's timer can never expire before * our clock has reached the bound - that ordering is the whole basis for the * elapsed-time test in `withConnectTimeout`, and rounding down would break it. * Never 0, because three of the four knobs read 0 as WAIT FOREVER: pg does * `connectionTimeoutMillis || 0` then `if (> 0)`, mysql2 does * `if (this.config.connectTimeout)`, and libpq (the same trap Python and Ruby * name) treats `connect_timeout=0` as no limit. A sub-millisecond bound must * therefore floor at 1ms rather than silently disabling the bound being set. */ export declare function driverConnectTimeoutMillis(budgetMs: number | null): number | null; /** * Best-effort host/port for the DIAGNOSTIC, from either a config object or a * connection URL. Never used to connect - the adapter has already done that with * its own parsing, and this must not become a second, divergent parser that * decides where anything dials. */ export declare function connectTarget(config: { host?: string; port?: number; } | string, defaultPort: number): { host: string; port: number | string; }; /** * Bound a driver connect, and name the bound when it expires. * * @param attempt a THUNK that starts the driver's connect. It is a thunk, not a * promise, so OUR CLOCK STARTS FIRST - everything that touches * the driver must run inside it. That ordering is load-bearing: * the driver arms its own timer somewhere in here (mysql2 arms * its at the END OF ITS CONSTRUCTOR, not in `connect()`), and * only by starting first can we know that the driver's timer * cannot expire before `elapsed` has reached the bound. * @param budgetMs from `connectTimeoutMillis()`; `null` runs `attempt` untouched * @param host named in the error - an operator needs to know WHICH server hung * @param port named in the error alongside the host * @param abandon called if the driver answers AFTER we gave up, with whatever it * produced. Nobody will ever use that connection, so the adapter * closes it here rather than leaking a socket for the life of the * process - a connect that is retried every 10s would otherwise * accumulate one abandoned connection per attempt, forever. * * TWO WAYS OUT, both wearing the same message. Normally the DRIVER's timer fires * first (it was armed first) and we TRANSLATE its failure; where the driver has * no knob, or its knob did not cover the phase that hung, our own timer fires as * the backstop and there is no driver diagnosis to report. */ export declare function withConnectTimeout(attempt: () => Promise, budgetMs: number | null, host: string, port: number | string, abandon?: (arrived: T) => void): Promise;