import { CanHandleErrorFunction, ErrorFilter } from './filter/base';
/**
 * The result of an error resolver.
 *
 * @property remainingAttempts - The number of attempts remaining, can be adapted on the go. If it hits 0, the next resolver will be tried or the operation will fail.
 * @property unrecoverable - Whether the error is unrecoverable. If true, the operation will fail, no more resolvers will be tried.
 * @property context - Additional context for the next called resolver (will be this resolver if remainingAttempts is >0)
 */
export interface ErrorResolution<C extends RetryContext<X>, X> {
    remainingAttempts: number;
    unrecoverable: boolean;
    context: C;
}
/**
 * The base type for error resolvers.
 *
 * @param error - The error that occurred.
 * @param attempt - The number of attempts made.
 * @param retryContext - The context passed from the previous handler or iteration
 * @param abortSignal - The abort signal, if you have a long running operation, consider implementing it.
 * @returns The error resolution.
 */
export interface ErrorResolverBase<C extends RetryContext<X>, X> {
    ({ error, attempt, retryContext, abortSignal, }: {
        error: unknown;
        attempt: number;
        retryContext: C;
        abortSignal?: AbortSignal;
    }): Promise<ErrorResolution<C, X>>;
}
/**
 * Abstract function that creates an error resolver.
 *
 * @param configuration - The configuration for the resolver.
 * @param canHandleError - Function that determines if an error can be handled.
 * @param context - The context for the next resolver called (will be null on the first call)
 * @returns The error resolver.
 */
export type ErrorResolver<T, C extends RetryContext<X>, X> = ({ configuration, canHandleError, context, }: {
    configuration: T;
    canHandleError?: CanHandleErrorFunction<X> | ErrorFilter<X>;
    context?: C;
}) => ErrorResolverBase<C, X>;
export interface RetryContext<C> {
    data?: C;
}
/**
 * Options for the retry operation.
 *
 * @param operation - The operation to retry.
 * @param errorResolvers - The error resolvers to use. In the order to resolve the error.
 * @param throwOnUnrecoveredError - Whether to throw an error if the operation failed to recover, instead of returning a result.
 * @param overallTimeout - The overall timeout for the operation. If set and the operation takes longer than this, it will be cancelled, any retries will not be attempted.
 * @param abortSignal - An optional abort signal to cancel the operation if timeouts are used.
 */
export interface RetryOptions<T, X> {
    operation: (retryContext?: RetryContext<X>, abortSignal?: AbortSignal) => Promise<T> | T;
    errorResolvers?: Array<ErrorResolverBase<RetryContext<X>, X>>;
    throwOnUnrecoveredError?: boolean;
    overallTimeout?: number;
    abortSignal?: AbortSignal;
    finallyCallback?: (() => void) | undefined;
}
/**
 * The result of the operation.
 *
 * @param success - Whether the operation was successful.
 * @param result - The result of the operation.
 * @param error - The error that occurred.
 * @param totalAttempts - The total number of attempts made.
 * @param totalDurationMs - The total duration of the operation in milliseconds.
 */
export interface RetryResult<T> {
    success: boolean;
    result?: T;
    error?: Error;
    totalAttemptsToSucceed?: number;
    totalAttempts?: number;
    totalDurationMs: number;
}
export declare function abortSignalAny(abortSignals: (AbortSignal | undefined)[]): {
    abortController: AbortController;
    signal: AbortSignal;
    abortListeners: ((e: Event) => void)[];
};
/**
 * Executes an operation with retry logic.
 *
 * @param operation - The operation to retry.
 * @param errorResolvers - The resolvers to use to try and recover
 * @param throwOnUnrecoveredError - Whether to throw an error if the operation failed to recover, instead of returning a result.
 * @returns The result of the operation
 */
export declare function advancedRetry<T, X>({ operation: operation, errorResolvers, throwOnUnrecoveredError, overallTimeout, finallyCallback, abortSignal: externalAbortSignal, }: RetryOptions<T, X>): Promise<RetryResult<T>>;
/**
 * Executes an operation with retry logic.
 *
 * @param operations - The operations to retry. All operations will be executed in parallel, if any of the operations fail, the operation will be retried. The other operations will continue to run.
 * @param errorResolvers - The resolvers to use to try and recover
 * @param overallTimeout - The overall timeout for the operation. If set and the operation takes longer than this, it will be cancelled, any retries will not be attempted.
 * @param abortSignal - An optional abort signal to cancel the operations if timeouts are used.
 * @returns The result of the operations
 */
export declare function advancedRetryAll<T extends unknown[], X>({ operations, errorResolvers, overallTimeout, abortSignal, }: {
    operations: {
        [K in keyof T]: () => Promise<T[K]>;
    };
    errorResolvers?: Array<ErrorResolverBase<RetryContext<X>, X>>;
    overallTimeout?: number;
    abortSignal?: AbortSignal;
}): Promise<{
    [K in keyof T]: RetryResult<T[K]>;
}>;
