/**
 * retry.ts — exponential backoff helper with abort signal.
 *
 * Used by driver implementations that want to retry transient transport
 * failures (DriverInvocationError) before giving up. Pure, dependency-free.
 */
/**
 * Run `fn` with exponential backoff. Returns the result of the first
 * successful call. If every attempt fails (or the signal aborts), throws
 * the last error.
 */
export async function retryWithBackoff(fn, opts = {}) {
    const maxAttempts = Math.max(1, opts.max_attempts ?? 3);
    const baseDelay = Math.max(0, opts.base_delay_ms ?? 100);
    const maxDelay = Math.max(0, opts.max_delay_ms ?? 5000);
    const multiplier = opts.multiplier ?? 2;
    const signal = opts.signal;
    const shouldRetry = opts.shouldRetry ?? (() => true);
    let lastErr;
    for (let attempt = 1; attempt <= maxAttempts; attempt++) {
        if (signal?.aborted) {
            throw signal.reason instanceof Error ? signal.reason : new Error('retryWithBackoff aborted');
        }
        try {
            return await fn();
        }
        catch (err) {
            lastErr = err;
            if (attempt >= maxAttempts)
                break;
            if (!shouldRetry(err))
                break;
            const delay = Math.min(maxDelay, baseDelay * multiplier ** (attempt - 1));
            await new Promise((resolve, reject) => {
                const timer = setTimeout(resolve, delay);
                if (signal) {
                    const onAbort = () => {
                        clearTimeout(timer);
                        reject(signal.reason instanceof Error
                            ? signal.reason
                            : new Error('retryWithBackoff aborted'));
                    };
                    signal.addEventListener('abort', onAbort, { once: true });
                }
            });
        }
    }
    throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));
}
//# sourceMappingURL=retry.js.map