import type { LogContext } from '@rocicorp/logger';
import { type JSONObject } from '../../../../shared/src/bigint-json.ts';
import { type ReadonlyJSONValue } from '../../../../shared/src/json.ts';
import type { AST } from '../../../../zero-protocol/src/ast.ts';
import type { ClientSchema } from '../../../../zero-protocol/src/client-schema.ts';
import type { LexiVersion } from '../../types/lexi-version.ts';
import { type ShardID } from '../../types/shards.ts';
import type { PatchToVersion } from './client-handler.ts';
import { type CVRFlushStats, type CVRStore } from './cvr-store.ts';
import { type ClientRecord, type CVRVersion, type InternalQueryRecord, type QueryRecord, type RowID } from './schema/types.ts';
import { type TTLClock } from './ttl-clock.ts';
export type RowUpdate = {
    version?: string;
    contents?: JSONObject;
    refCounts: {
        [hash: string]: number;
    };
};
/** Internally used mutable CVR type. */
export type CVR = {
    id: string;
    version: CVRVersion;
    lastActive: number;
    ttlClock: TTLClock;
    replicaVersion: string | null;
    clients: Record<string, ClientRecord>;
    queries: Record<string, QueryRecord>;
    clientSchema: ClientSchema | null;
    profileID: string | null;
};
/** Exported immutable CVR type. */
export type CVRSnapshot = {
    readonly id: string;
    readonly version: CVRVersion;
    readonly lastActive: number;
    readonly ttlClock: TTLClock;
    readonly replicaVersion: string | null;
    readonly clients: Readonly<Record<string, ClientRecord>>;
    readonly queries: Readonly<Record<string, QueryRecord>>;
    readonly clientSchema: ClientSchema | null;
    readonly profileID: string | null;
};
export declare function getMutationResultsQuery(upstreamSchema: string, clientGroupID: string): InternalQueryRecord;
/**
 * The base CVRUpdater contains logic common to the {@link CVRConfigDrivenUpdater} and
 * {@link CVRQueryDrivenUpdater}. The CVRUpdater class itself is exported for updating
 * the `lastActive` time of the CVR in the absence of any changes to the CVR contents.
 * Although activity is automatically tracked when the CVR contents change, there may be
 * edge cases in which a client actively connects to a CVR that doesn't itself change.
 * Calling `new CVRUpdater(...).flush()` will explicitly update the active index and
 * prevent the CVR from being garbage collected.
 */
export declare class CVRUpdater {
    protected readonly _orig: CVRSnapshot;
    protected readonly _cvr: CVR;
    protected readonly _cvrStore: CVRStore;
    /**
     * @param cvrStore The CVRStore to use for storage
     * @param cvr The current CVR
     */
    constructor(cvrStore: CVRStore, cvr: CVRSnapshot, replicaVersion: string | null);
    protected _setVersion(version: CVRVersion): {
        configVersion?: number | undefined;
        stateVersion: string;
    };
    /**
     * Ensures that the new CVR has a higher version than the original.
     * This method is idempotent in that it will always return the same
     * (possibly bumped) version.
     */
    protected _ensureNewVersion(): CVRVersion;
    flush(lc: LogContext, lastConnectTime: number, lastActive: number, ttlClock: TTLClock): Promise<{
        cvr: CVRSnapshot;
        flushed: CVRFlushStats | false;
    }>;
}
/**
 * A {@link CVRConfigDrivenUpdater} is used for updating a CVR with config-driven
 * changes. Note that this may result in row deletion (e.g. if queries get dropped),
 * but the `stateVersion` of the CVR does not change.
 */
export declare class CVRConfigDrivenUpdater extends CVRUpdater {
    #private;
    constructor(cvrStore: CVRStore, cvr: CVRSnapshot, shard: ShardID);
    ensureClient(id: string): ClientRecord;
    setClientSchema(lc: LogContext, clientSchema: ClientSchema): void;
    setProfileID(lc: LogContext, profileID: string): void;
    putDesiredQueries(clientID: string, queries: Readonly<{
        hash: string;
        ast?: AST | undefined;
        name?: string | undefined;
        args?: readonly ReadonlyJSONValue[] | undefined;
        ttl?: number | undefined;
    }>[]): PatchToVersion[];
    markDesiredQueriesAsInactive(clientID: string, queryHashes: string[], ttlClock: TTLClock): PatchToVersion[];
    deleteDesiredQueries(clientID: string, queryHashes: string[]): PatchToVersion[];
    clearDesiredQueries(clientID: string): PatchToVersion[];
    deleteClient(clientID: string, ttlClock: TTLClock): PatchToVersion[];
}
type Hash = string;
export type Column = string;
export type RefCounts = Record<Hash, number>;
/**
 * A {@link CVRQueryDrivenUpdater} is used for updating a CVR after making queries.
 * The caller should invoke:
 *
 * * {@link trackQueries} for queries that are being executed or removed.
 * * {@link received} for all rows received from the executed queries
 * * {@link deleteUnreferencedRows} to remove any rows that have
 *       fallen out of the query result view.
 * * {@link flush}
 *
 * After flushing, the caller should perform any necessary catchup of
 * config and row patches for clients that are behind. See
 * {@link CVRStore.catchupConfigPatches} and {@link CVRStore.catchupRowPatches}.
 */
export declare class CVRQueryDrivenUpdater extends CVRUpdater {
    #private;
    /**
     * @param stateVersion The `stateVersion` at which the queries were executed.
     */
    constructor(cvrStore: CVRStore, cvr: CVRSnapshot, stateVersion: LexiVersion, replicaVersion: string);
    /**
     * Initiates the tracking of the specified `executed` and `removed` queries.
     * This kicks of a lookup of existing {@link RowRecord}s currently associated
     * with those queries, which will be used to reconcile the rows to keep
     * after all rows have been {@link received()}.
     *
     * "transformed" queries are queries that are currently
     * gotten and running in the pipeline driver but
     * received a new transformation hash due to an auth token
     * update.
     *
     * @returns The new CVRVersion to be used when all changes are committed.
     */
    trackQueries(lc: LogContext, executed: {
        id: string;
        transformationHash: string;
    }[], removed: {
        id: string;
    }[]): {
        newVersion: CVRVersion;
        queryPatches: PatchToVersion[];
    };
    updatedVersion(): CVRVersion;
    /**
     * Tracks rows received from executing queries. This will update row records
     * and row patches if the received rows have a new version. The method also
     * returns (put) patches to be returned to update their state, versioned by
     * patchVersion so that only the patches new to the clients are sent.
     */
    received(_lc: LogContext, rows: Map<RowID, RowUpdate>): Promise<PatchToVersion[]>;
    /**
     * Computes and updates the row records based on:
     * * The {@link #executed} queries
     * * The {@link #removed} queries
     * * The {@link received} rows
     *
     * Returns the final delete and patch ops that must be sent to the client
     * to delete rows that are no longer referenced by any query.
     *
     * This is Step [5] of the
     * [CVR Sync Algorithm](https://www.notion.so/replicache/Sync-and-Client-View-Records-CVR-a18e02ec3ec543449ea22070855ff33d?pvs=4#7874f9b80a514be2b8cd5cf538b88d37).
     */
    deleteUnreferencedRows(lc?: LogContext): Promise<PatchToVersion[]>;
}
/**
 * The query must be inactive for all clients to be considered inactive.
 * This is because expiration is defined that way: a query is expired for a client group
 * only if it is expired for all clients in the group.
 *
 * If all clients have inactivated the query, we return
 * the one with the expiration furthest in the future.
 */
export declare function getInactiveQueries(cvr: CVR): {
    hash: string;
    inactivatedAt: TTLClock;
    ttl: number;
}[];
export declare function nextEvictionTime(cvr: CVR): TTLClock | undefined;
export {};
//# sourceMappingURL=cvr.d.ts.map