/**
 * backoff — builders of a `RetryPolicy.backoffMs` function: an exponential
 * schedule, and a wait the server stated winning over it.
 *
 * STAND-IN, TO BE DELETED. footprintjs is adding these two helpers to its
 * attempt runner (`attempt/backoff.ts`): `exponentialBackoff({ baseDelayMs,
 * multiplier, jitter, maxDelayMs, random })` and
 * `statedWaitFirst(readStatedWaitMs, inner)`, with these names, signatures and
 * laws. Once a footprintjs release
 * ships them, import them in `throttleRetry.ts` and delete this file; nothing
 * else changes.
 *
 * Pattern: Two pure builders. Each returns `(attempt, error?) => ms`.
 * Role:    The wait `throttleRetry.ts` plans for each retry.
 * Emits:   N/A.
 *
 * ── THE LAW ──────────────────────────────────────────────────────────────
 * `exponentialBackoff`: after failed attempt `n` (1-based) the ceiling is
 *
 *     c = min(maxDelayMs, baseDelayMs × multiplier^(n − 1))
 *                                     (saturating at MAX_SAFE_INTEGER)
 *
 * and, for `r = random()` in [0, 1]:
 *
 *     'none'    c                        `random` is never called
 *     'equal'   min(c, c/2 + r × c/2)    never below half the ceiling
 *     'full'    r × c                    anywhere from 0 up to it
 *
 * Waits are exact milliseconds — nothing is rounded. `random` defaults to
 * `Math.random`, taken when the function is BUILT; a fixed source makes a test
 * exact. A `random()` answering outside [0, 1] throws when asked.
 *
 * `statedWaitFirst`: when `readStatedWaitMs(error)` answers a finite number
 * ≥ 0, that is the wait; otherwise `inner` decides. A reader that throws or
 * answers anything else states nothing, so a malformed `Retry-After` falls back
 * to the schedule rather than to a wrong wait.
 *
 * `maxDelayMs` caps the CEILING, before the draw, so capped waits keep their
 * jitter: at the cap, equal jitter still spreads between c/2 and c. Capped
 * after the draw instead, every wait past twice the cap would BE the cap, and
 * clients refused together would retry in lockstep. A stated wait is never
 * capped: `statedWaitFirst` hands it back whole.
 */
/** How much of an exponential wait is random: none of it, half of it, or all of it. */
export type BackoffJitter = 'none' | 'equal' | 'full';
/** The schedule {@link exponentialBackoff} builds a backoff function from. */
export interface BackoffSpec {
    /** The ceiling of the first wait (after attempt 1), in milliseconds — a finite number ≥ 0. */
    readonly baseDelayMs: number;
    /** How much each ceiling grows over the one before — a finite number ≥ 1. Default `2`. */
    readonly multiplier?: number;
    /** How much of each wait is random. Default `'none'`: the wait IS the ceiling. */
    readonly jitter?: BackoffJitter;
    /**
     * The cap on every ceiling, in milliseconds — a number ≥ 0, applied BEFORE
     * the draw, so capped waits keep their jitter. Default: none.
     */
    readonly maxDelayMs?: number;
    /** The jitter's random source, answering in [0, 1]. Default `Math.random`, taken when built. */
    readonly random?: () => number;
}
/** A `RetryPolicy.backoffMs` function: the wait in milliseconds after failed attempt `attempt` (1-based). */
export type BackoffFunction = (attempt: number, error?: unknown) => number;
/** Reads the wait an error states (a parsed `Retry-After`), in milliseconds, or `undefined` when it states none. */
export type StatedWaitReader = (error: unknown) => number | undefined;
/**
 * An exponential schedule: the wait after failed attempt `n` is drawn under
 * `baseDelayMs × multiplier^(n − 1)` by the declared jitter.
 *
 * @throws when built: a `TypeError` for an option of the wrong type, a
 *   `RangeError` for one out of range — each naming the option.
 */
export declare function exponentialBackoff(spec: BackoffSpec): BackoffFunction;
/**
 * A wait the outside system stated wins; otherwise `inner` — a backoff
 * function, or a fixed number of milliseconds — decides.
 *
 * @throws when built: a `TypeError` for a reader that is not a function, or an
 *   `inner` that is neither a function nor a finite number ≥ 0.
 */
export declare function statedWaitFirst(readStatedWaitMs: StatedWaitReader, inner: BackoffFunction | number): BackoffFunction;
//# sourceMappingURL=backoff.d.ts.map