import type TypedEventEmitter from 'typed-emitter';
import type { Middleware } from '../../api/generated/default';
import { DiscoveryNodeSelectorService, DiscoveryNodeSelectorServiceConfig, ServiceSelectionEvents, DiscoveryNode } from './types';
export declare class DiscoveryNodeSelector implements DiscoveryNodeSelectorService {
    /**
     * List of services to select from
     */
    private services;
    /**
     * Currently selected discovery node
     */
    private selectedNode;
    /**
     * Configuration passed in by consumer (with defaults)
     */
    private config;
    /**
     * Whether or not we are using a backup, meaning we were
     * unable to select a discovery node that was up-to-date and healthy.
     * Clients may want to consider blocking writes as service may be degraded
     */
    private _isBehind;
    get isBehind(): boolean;
    private set isBehind(value);
    /**
     * During selection, services that fail health check will be put in this list
     * so that we try different nodes on new rounds of selection
     */
    private unhealthyServices;
    /**
     * List of services that were found to be unhealthy but still usable in a pinch
     */
    private backupServices;
    /**
     * Reference to a setTimeout for removing services from the unhealthy list so they can be retried
     */
    private unhealthyCleanupTimeout;
    /**
     * Reference to a setTimeout for removing services from the backup list so they can be retried
     */
    private backupCleanupTimeout;
    private reselectLock;
    /**
     * Composed EventEmitter for alerting listeners of reselections
     */
    private readonly eventEmitter;
    /**
     * Proxy to the event emitter addListener
     */
    addEventListener: <E extends keyof ServiceSelectionEvents>(event: E, listener: ServiceSelectionEvents[E]) => TypedEventEmitter<ServiceSelectionEvents>;
    /**
     * Proxy to the event emitter removeListener
     */
    removeEventListener: <E extends keyof ServiceSelectionEvents>(event: E, listener: ServiceSelectionEvents[E]) => TypedEventEmitter<ServiceSelectionEvents>;
    private readonly logger;
    constructor(config?: DiscoveryNodeSelectorServiceConfig);
    /**
     * Updates the config.
     * Note that setting the initial node or bootstrap nodes here does nothing as the service is already initialized.
     * Will force reselections if health check thresholds change (as that might cause the current node to be considered unhealthy)
     * or if the selected node is excluded per allow/blocklists
     */
    updateConfig(config: Exclude<DiscoveryNodeSelectorServiceConfig, 'initialSelectedNode' | 'bootstrapServices'>): void;
    /**
     * Returns a middleware that reselects if the current discovery node is behind
     * @returns the middleware
     */
    createMiddleware(): Middleware;
    /**
     * Selects a discovery node or returns the existing selection
     * @returns a discovery node endpoint
     */
    getSelectedEndpoint(): Promise<string | null>;
    getUniquelyOwnedEndpoints(nodeCount: number, excludeOwners?: string[]): Promise<string[]>;
    /**
     * Gets the list of services
     */
    getServices(): Promise<DiscoveryNode[]>;
    /**
     * Finds a healthy discovery node
     * @returns a healthy discovery node endpoint
     */
    private select;
    /**
     * Checks to see if any of the endpoints are healthy, returning the first one that is.
     * Cancels the remaining promises.
     * Uses the configured timeout.
     * Any unhealthy or behind services found are placed into the unhealthy and backup lists respectively
     *
     * @param endpoints the endpoints to race
     * @returns the fastest healthy endpoint or null if none are healthy
     */
    private anyHealthyEndpoint;
    private refreshServiceList;
    /**
     * Checks the given endpoint's health check and reselects if necessary.
     * @param endpoint the endpoint to health_check
     * @returns a new discovery node if reselect was necessary, or the existing endpoint if reselect unnecessary
     */
    private reselectIfNecessary;
    /**
     * Sets (or resets) a setTimeout to reset the backup and unhealthy service lists
     */
    private triggerCleanup;
    /**
     * First try to get a node that's got a healthy blockdiff, but a behind version.
     * If that fails, get the node with the lowest blockdiff on the most up to date version
     */
    private selectFromBackups;
    private reselectAndRetry;
    triggerReselection(): Promise<void>;
}
