import { IEventEmitter, ILogger, StorageCapabilities, StorageType, WorkerStorageConfig } from '../storage.interface';
import { StorageKeyType } from '../utils/storage-key';
import { AsyncBaseStorage } from './async-base-storage.service';
/**
 * Асинхронное хранилище поверх общего key-value стора внутри SharedWorker.
 *
 * Это тот же принцип, что у {@link MemoryStorage} (данные в `Map`), но `Map` живёт
 * ВНУТРИ SharedWorker и потому разделяется между вкладками. Если SharedWorker
 * недоступен (тесты/SSR/CSP), {@link WorkerChannel} прозрачно откатывается на
 * in-process `Map` — round-trip идентичен MemoryStorage, но БЕЗ межвкладочного
 * шеринга (это даёт только настоящий SharedWorker).
 *
 * Все `do*` реализованы через RPC к стору ({@link WorkerChannel.request}) и повторяют
 * маппинг ключей/путей MemoryStorage (те же `getValueByPath`/`setValueByPath`/
 * `removeValueByPath`), поэтому поведение совпадает с MemoryStorage «ключ-в-ключ».
 *
 * Записи атомарны на уровне ключа (per-key `set`/`update`/`delete`), поэтому
 * конкурентные вкладки не затирают чужие ключи. После мутации из другой вкладки
 * стор рассылает уведомление — адаптер обновляет свой кэш и будит подписчиков.
 */
export declare class WorkerCacheStorage<T extends Record<string, any>> extends AsyncBaseStorage<T> {
    protected static readonly STORAGE_TYPE: StorageType;
    readonly type: StorageType;
    /** Живой кэш; `shared` честно отражает, реально ли работает кросс-табный SharedWorker. */
    readonly capabilities: StorageCapabilities;
    private readonly channelName;
    private readonly backend;
    private unsubscribeMutation?;
    private refreshInFlight;
    private refreshDirty;
    constructor(config: WorkerStorageConfig<T>, eventEmitter?: IEventEmitter, logger?: ILogger);
    static create<T extends Record<string, any>>(config: WorkerStorageConfig<T>, eventEmitter?: IEventEmitter, logger?: ILogger): WorkerCacheStorage<T>;
    protected doInitialize(): Promise<this>;
    /**
     * Подписка на мутации из ДРУГИХ вкладок/экземпляров. Воркер рассылает STORE_MUTATION
     * после каждой мутирующей операции; payload несёт только `{op}`, поэтому мы просто
     * перечитываем полное состояние, обновляем `_stateCache` и будим подписчиков (как
     * при локальной записи). Без этого хука `subscribe()` и tagIndex в QueryStorage
     * устаревали бы для записей, сделанных другими вкладками.
     */
    private subscribeToStoreMutations;
    /**
     * Сериализует refresh'и: пока один в полёте, следующие мутации лишь взводят `dirty`,
     * и после завершения текущего прогоняется ровно один догоняющий refresh. Так каждый
     * refresh диффит против актуального `_stateCache`, а не против устаревшего снапшота —
     * нет дублей уведомлений подписчиков одними и теми же значениями.
     */
    private scheduleRefresh;
    private runRefreshLoop;
    private refreshFromRemoteMutation;
    protected doGet(key: StorageKeyType): Promise<any>;
    protected doSet(key: StorageKeyType, value: any): Promise<void>;
    protected doUpdate(updates: Array<{
        key: StorageKeyType;
        value: any;
    }>): Promise<void>;
    protected doDelete(key: StorageKeyType): Promise<boolean>;
    protected doClear(): Promise<void>;
    protected doKeys(): Promise<string[]>;
    protected doHas(key: StorageKeyType): Promise<boolean>;
    /**
     * Живой кэш НЕ очищается при destroy: данные живут в воркере и разделяются между
     * вкладками — уничтожение адаптера одной вкладкой не должно стирать общий кэш.
     * Поэтому переопределяем performCleanup (как IndexedDBStorage), пропуская doClear(),
     * но ОБЯЗАТЕЛЬНО прогоняя cleanup мидлвар (иначе их каналы/таймеры текут — R8).
     */
    protected performCleanup(): Promise<void>;
    protected doDestroy(): Promise<void>;
}
