import type { RetryConfig } from "../common.js"; import { S2Error } from "../error.js"; import * as Types from "../types.js"; import type { AcksStream, AppendSessionOptions, AppendSession as AppendSessionType, ReadArgs, ReadSession as ReadSessionType, TransportAppendSession, TransportReadSession } from "./stream/types.js"; import { BatchSubmitTicket } from "./stream/types.js"; /** * Default retry configuration. */ export declare const DEFAULT_RETRY_CONFIG: Required; /** * Determines if an error should be retried based on its characteristics. * 400-level errors (except 408, 429) are non-retryable validation/client errors. */ export declare function isRetryable(error: S2Error): boolean; /** * Calculates the delay before the next retry attempt using exponential backoff * with additive jitter. * * Formula: * baseDelay = min(minBaseDelayMillis * 2^attempt, maxBaseDelayMillis) * jitter = random(0, baseDelay) * delay = baseDelay + jitter * * @param attempt - Zero-based retry attempt number (0 = first retry) * @param minBaseDelayMillis - Minimum delay for exponential backoff * @param maxBaseDelayMillis - Maximum base delay (actual delay can be up to 2x with jitter) */ export declare function calculateDelay(attempt: number, minBaseDelayMillis: number, maxBaseDelayMillis: number): number; /** * Sleeps for the specified duration. */ export declare function sleep(ms: number): Promise; /** * Executes an async function with automatic retry logic for transient failures. * * @param retryConfig Retry configuration (max attempts, backoff duration) * @param fn The async function to execute * @returns The result of the function * @throws The last error if all retry attempts are exhausted */ export declare function withRetries(retryConfig: RetryConfig | undefined, fn: () => Promise, isPolicyCompliant?: (config: RetryConfig, error: S2Error) => boolean): Promise; export declare class RetryReadSession extends ReadableStream> implements ReadSessionType { private _nextReadPosition; private _lastObservedTail; private _lastTailAtMs; private _recordsRead; private _bytesRead; static create(generator: (args: ReadArgs) => Promise>, args?: ReadArgs, config?: RetryConfig): Promise>; private constructor(); [Symbol.asyncDispose](): Promise; [Symbol.asyncIterator](): AsyncIterableIterator>; lastObservedTail(): Types.StreamPosition | undefined; nextReadPosition(): Types.StreamPosition | undefined; } export declare class RetryAppendSession implements AsyncDisposable, AppendSessionType { private readonly generator; private readonly sessionOptions?; private readonly requestTimeoutMillis; private readonly maxQueuedBytes; private readonly maxInflightBatches?; private readonly retryConfig; private readonly inflight; private capacityWaiters; private session?; private queuedBytes; private pendingBytes; private pendingBatches; private consecutiveFailures; private currentAttempt; private pumpPromise?; private pumpStopped; private closing; private pumpWakeup?; private closed; private fatalError?; private _lastAckedPosition?; private acksController?; readonly readable: ReadableStream; readonly writable: WritableStream; private readonly streamName; /** * If the session has failed, returns the original fatal error that caused * the pump to stop. Returns undefined when the session has not failed. */ failureCause(): S2Error | undefined; constructor(generator: (options?: AppendSessionOptions) => Promise, sessionOptions?: AppendSessionOptions | undefined, config?: RetryConfig, streamName?: string); static create(generator: (options?: AppendSessionOptions) => Promise, sessionOptions?: AppendSessionOptions, config?: RetryConfig, streamName?: string): Promise; /** * Wait for capacity to be available for the given batch size. * Call this before submit() to apply backpressure based on maxInflightBatches/maxInflightBytes. * * @param bytes - Size in bytes (use meteredBytes() to calculate) * @param numBatches - Number of batches (default: 1) * @returns Promise that resolves when capacity is available */ waitForCapacity(bytes: number, numBatches?: number): Promise; /** * Submit an append request. * Returns a promise that resolves to a submit ticket once the batch is enqueued (has capacity). * The ticket's ack() can be awaited to get the AppendAck once the batch is durable. * This method applies backpressure and will block if capacity limits are reached. */ submit(input: Types.AppendInput): Promise; /** * Internal submit that returns discriminated union. * Creates inflight entry and starts pump if needed. */ private submitInternal; /** * Release capacity and wake waiter if present. */ private releaseCapacity; private wakeCapacityWaiters; /** * Ensure pump loop is running. */ private ensurePump; /** * Main pump loop: processes inflight queue, handles acks, retries, and recovery. */ private runPump; /** * Wait for head entry's innerPromise with timeout. * Returns either the settled result or a timeout indicator. * * Per-attempt ack timeout semantics: * - The deadline is computed from the current attempt's start time using a * monotonic clock (performance.now) to avoid issues with wall clock adjustments. * - Each retry gets a fresh timeout window (attemptStartedMonotonicMs is reset * during recovery). * - If attempt start is missing (for backward compatibility), we measure * from "now" with the full timeout window. */ private waitForHead; /** * Recover from transient error: recreate session and resubmit all inflight entries. */ private recover; /** * Ensure session exists, creating it if necessary. */ private ensureSession; /** * Abort the session with a fatal error. */ private abort; /** * Close the append session. * Waits for all pending appends to complete before resolving. * Does not interrupt recovery - allows it to complete. */ close(): Promise; [Symbol.asyncDispose](): Promise; /** * Get a stream of acknowledgements for appends. */ acks(): AcksStream; /** * Get the last acknowledged position. */ lastAckedPosition(): Types.AppendAck | undefined; } //# sourceMappingURL=retry.d.ts.map