import type { CircuitBreakerOptions, CircuitBreakerState } from './types';
/**
 * Generic circuit breaker built on {@link StateMachine}.
 *
 * - **closed**: requests are allowed; failures are counted.
 * - **open**: requests are rejected until {@link resetTimeoutMs} elapses.
 * - **half-open**: the recovery-probe state. After the open timeout, the breaker admits exactly ONE
 *   probe request: success means the dependency recovered, so the circuit closes. Failure means it's
 *   still down, so the circuit reopens. This single-request probe prevents a "thundering herd" where
 *   every caller fails loudly when the service hasn't recovered yet.
 *
 * Subclasses implement the failure-counting policy by overriding {@link recordFailureInClosed} (and
 * friends) — e.g. counting consecutive failures, or failures within a rolling time window, or any
 * combination of those.
 *
 * @example
 * class MyBreaker extends AbstractCircuitBreaker {
 *     private failures = 0;
 *     protected recordFailureInClosed() {
 *         this.failures += 1;
 *         return this.failures >= 3 ? `${this.failures} failures` : null;
 *     }
 *     protected recordSuccessInClosed() { this.failures = 0; }
 *     protected resetFailureState() { this.failures = 0; }
 * }
 *
 * const breaker = new MyBreaker({resetTimeoutMs: 30_000});
 * if (breaker.isAllowed()) {
 *     try {
 *         doWork();
 *         breaker.recordSuccess();
 *     } catch {
 *         breaker.recordFailure();
 *     }
 * }
 */
declare abstract class AbstractCircuitBreaker {
    private machine;
    private openedAt;
    private isProbeInFlight;
    private readonly resetTimeoutMs;
    private readonly onTrip?;
    private readonly onClose?;
    constructor(options?: CircuitBreakerOptions);
    /** Record a failure while the circuit is closed. Returns a trip reason when the threshold is exceeded. */
    protected abstract recordFailureInClosed(): string | null;
    /** Update failure state after a successful request while the circuit is closed. */
    protected abstract recordSuccessInClosed(): void;
    /** Clear accumulated failure state without changing circuit state. */
    protected abstract resetFailureState(): void;
    /**
     * Whether a request may proceed.
     *
     * Returns `false` while open. In half-open, the FIRST caller is admitted as the recovery probe and
     * `isProbeInFlight` is latched so every subsequent caller is rejected until that probe resolves
     * (via {@link recordSuccess} → close, or {@link recordFailure} → reopen). That single-probe gate is
     * the whole point of half-open: it tests recovery with one request instead of letting a herd of
     * waiting callers stampede a dependency that may still be down.
     */
    isAllowed(): boolean;
    /**
     * Record a failed request. May open the circuit from closed or half-open.
     * @returns `true` when the circuit is open after recording (the request must not proceed).
     */
    recordFailure(): boolean;
    /** Record a successful request. Closes the circuit from half-open and clears failure counts. */
    recordSuccess(): void;
    /**
     * The current state WITHOUT advancing recovery — a pure query, safe to call without side effects.
     * The open→half-open transition is applied only at the admission point ({@link isAllowed}); by the
     * time a caller queries state after being admitted, that transition has already happened.
     */
    peekState(): CircuitBreakerState;
    /**
     * Force the circuit back to closed from ANY state. This is a reset, not a transition, so it
     * deliberately bypasses the transition graph (and does not fire {@link onClose}). Use only to wipe
     * all state — e.g. between tests or sessions.
     */
    protected hardReset(): void;
    private getCurrentState;
    private trip;
    private close;
    /**
     * Lazily advance open → half-open once the reset timeout has elapsed. This is checked on read
     * (via {@link getCurrentState}) rather than on a timer, so there's nothing to schedule or clean up:
     * the transition simply becomes visible to the next caller after the window. Entering half-open
     * clears `isProbeInFlight` so the next admitted request becomes the recovery probe.
     */
    private maybeRecover;
}
export default AbstractCircuitBreaker;
