import { SyncCookie } from '@towns-protocol/proto';
import { StreamRpcClient } from './makeStreamRpcClient';
import { UnpackEnvelopeOpts } from './sign';
import { SyncedStreamEvents } from './streamEvents';
import TypedEmitter from 'typed-emitter';
import { ParsedEvent, ParsedSnapshot, ParsedStreamResponse } from './types';
export declare enum SyncState {
    Canceling = "Canceling",// syncLoop, maybe syncId if was syncing, not is was starting or retrying
    NotSyncing = "NotSyncing",// no syncLoop
    Retrying = "Retrying",// syncLoop set, no syncId
    Starting = "Starting",// syncLoop set, no syncId
    Syncing = "Syncing"
}
/**
 * Valid state transitions:
 * - [*] -\> NotSyncing
 * - NotSyncing -\> Starting
 * - Starting -\> Syncing
 * - Starting -\> Canceling: failed / stop sync
 * - Starting -\> Retrying: connection error
 * - Syncing -\> Canceling: connection aborted / stop sync
 * - Syncing -\> Retrying: connection error
 * - Syncing -\> Syncing: resync
 * - Retrying -\> Canceling: stop sync
 * - Retrying -\> Syncing: resume
 * - Retrying -\> Retrying: still retrying
 * - Canceling -\> NotSyncing
 * @see https://www.notion.so/herenottherelabs/RFC-Sync-hardening-e0552a4ed68a4d07b42ae34c69ee1bec?pvs=4#861081756f86423ea668c62b9eb76f4b
 */
export declare const stateConstraints: Record<SyncState, Set<SyncState>>;
export interface ISyncedStream {
    syncCookie?: SyncCookie;
    stop(): void;
    initializeFromResponse(response: ParsedStreamResponse): Promise<void>;
    appendEvents(events: ParsedEvent[], nextSyncCookie: SyncCookie, snapshot: ParsedSnapshot | undefined, cleartexts: Record<string, Uint8Array | string> | undefined): Promise<void>;
    resetUpToDate(): void;
}
interface NonceStats {
    sequence: number;
    nonce: string;
    pingAt: number;
    receivedAt?: number;
    duration?: number;
}
interface Nonces {
    [nonce: string]: NonceStats;
}
export interface PingInfo {
    nonces: Nonces;
    currentSequence: number;
    pingTimeout?: NodeJS.Timeout;
}
export declare class SyncedStreamsLoop {
    readonly unpackEnvelopeOpts: UnpackEnvelopeOpts | undefined;
    private highPriorityIds;
    private streamOpts;
    private readonly streams;
    private readonly logSync;
    private readonly logDebug;
    private readonly logError;
    private readonly clientEmitter;
    private syncLoop?;
    private syncId?;
    private rpcClient;
    private _syncState;
    private releaseRetryWait;
    private currentRetryCount;
    private forceStopSyncStreams;
    private interruptSync;
    private isMobileSafariBackgrounded;
    private responsesQueue;
    private inProgressTick?;
    private pendingSyncCookies;
    private inFlightSyncCookies;
    private pendingStreamsToDelete;
    private lastLogInflightAt;
    private syncStartedAt;
    private processedStreamCount;
    private streamSyncStalled;
    private readonly MAX_IN_FLIGHT_COOKIES;
    private readonly MIN_IN_FLIGHT_COOKIES;
    private readonly MAX_IN_FLIGHT_STREAMS_TO_DELETE;
    pingInfo: PingInfo;
    constructor(clientEmitter: TypedEmitter<SyncedStreamEvents>, rpcClient: StreamRpcClient, streams: {
        syncCookie: SyncCookie;
        stream: ISyncedStream;
    }[], logNamespace: string, unpackEnvelopeOpts: UnpackEnvelopeOpts | undefined, highPriorityIds: Set<string>, streamOpts: {
        useModifySync?: boolean;
        useSharedSyncer?: boolean;
    } | undefined);
    get syncState(): SyncState;
    stats(): {
        syncState: SyncState;
        streams: number;
        syncId: string | undefined;
        queuedResponses: number;
    };
    getSyncId(): string | undefined;
    start(): void;
    stop(): Promise<void>;
    addStreamToSync(streamId: string, syncCookie: SyncCookie, stream: ISyncedStream): void;
    removeStreamFromSync(inStreamId: string | Uint8Array): Promise<void>;
    setHighPriorityStreams(streamIds: string[]): void;
    onNetworkStatusChanged(isOnline: boolean): void;
    private createSyncLoop;
    private onMobileSafariBackgrounded;
    private checkStartTicking;
    private tick;
    private waitForSyncingState;
    private setSyncState;
    private attemptRetry;
    private syncStarted;
    private syncDown;
    private syncClosed;
    private onUpdate;
    private sendKeepAlivePings;
    private stopPing;
    private printNonces;
    private logInvalidStateAndReturnError;
    private log;
}
export {};
//# sourceMappingURL=syncedStreamsLoop.d.ts.map