import { Duration, Effect, Schedule } from "effect"; export { type Debounced, makeDebounced } from "./debounce.js"; export interface RetryOptions { /** Maximum number of attempts before giving up (including the first try). Default 3. */ readonly maxAttempts?: number; /** Base delay in ms before the first retry; doubles each subsequent attempt. Default 1000. */ readonly baseDelayMs?: number; /** Upper bound on the computed delay. Default 30_000. */ readonly maxDelayMs?: number; /** Return false to stop retrying and fail with that error immediately. */ readonly shouldRetry?: (error: E) => boolean; } /** * Jittered exponential backoff capped at `maxDelayMs`: the delay before * retry n (1-based) is `min(baseDelayMs * 2^(n-1), maxDelayMs)`, jittered. * Recurs forever; bound it with `Schedule.upTo` or `Schedule.recurs`. */ export declare function exponentialBackoff(options: { readonly baseDelayMs: number; readonly maxDelayMs: number; }): Schedule.Schedule; /** * Jittered fixed spacing that stops once `deadlineMs` has elapsed. The * shape behind every "poll until the deadline" loop: * `Effect.repeat(check, { schedule: spacedUpTo(100, 5000), until: (ok) => ok })` * or `Effect.retry(attempt, spacedUpTo(150, 120_000))`. */ export declare function spacedUpTo(intervalMs: number, deadlineMs: number): Schedule.Schedule; /** * The lock-contention schedule: poll every `pollMs` (default 150 ms, * jittered so competing processes never retry in lockstep) for at most * `timeoutMs`. */ export declare function lockContention(timeoutMs: number, pollMs?: number): Schedule.Schedule; /** * `exponentialBackoff` for at most `maxAttempts` attempts, with a warning * logged before every retry naming the attempt and the failure. Stops early * when `shouldRetry` returns false. */ export declare function retrySchedule(options?: RetryOptions): Schedule.Schedule; /** `Effect.retry` with `retrySchedule(options)`. */ export declare function withRetry(effect: Effect.Effect, options?: RetryOptions): Effect.Effect;