import type { LogContext } from '@rocicorp/logger';
import type { PendingQuery, Row } from 'postgres';
import { type PostgresDB, type PostgresTransaction } from '../../types/pg.ts';
import { type ShardID } from '../../types/shards.ts';
import { type CVRFlushStats } from './cvr-store.ts';
import type { CVRSnapshot } from './cvr.ts';
import { type RowsRow } from './schema/cvr.ts';
import { type CVRVersion, type NullableCVRVersion, type RowID, type RowRecord } from './schema/types.ts';
/**
 * The RowRecordCache is an in-memory cache of the `cvr.rows` tables that
 * operates as both a write-through and write-back cache.
 *
 * For "small" CVR updates (i.e. zero or small numbers of rows) the
 * RowRecordCache operates as write-through, executing commits in
 * {@link executeRowUpdates()} before they are {@link apply}-ed to the
 * in-memory state.
 *
 * For "large" CVR updates (i.e. with many rows), the cache switches to a
 * write-back mode of operation, in which {@link executeRowUpdates()} is a
 * no-op, and {@link apply()} initiates a background task to flush the pending
 * row changes to the store. This allows the client poke to be completed and
 * committed on the client without waiting for the heavyweight operation of
 * committing the row records to the CVR store.
 *
 * Note that when the cache is in write-back mode, all updates become
 * write-back (i.e. asynchronously flushed) until the pending update queue is
 * fully flushed. This is required because updates must be applied in version
 * order. As with all pending work systems in zero-cache, multiple pending
 * updates are coalesced to reduce buildup of work.
 *
 * ### High level consistency
 *
 * Note that the above caching scheme only applies to the row data in `cvr.rows`
 * and corresponding `cvr.rowsVersion` tables. CVR metadata and query
 * information, on the other hand, are always committed before completing the
 * client poke. In this manner, the difference between the `version` column in
 * `cvr.instances` and the analogous column in `cvr.rowsVersion` determines
 * whether the data in the store is consistent, or whether it is awaiting a
 * pending update.
 *
 * The logic in {@link CVRStore.load()} takes this into account by loading both
 * the `cvr.instances` version and the `cvr.rowsVersion` version and checking
 * if they are in sync, waiting for a configurable delay until they are.
 *
 * ### Eventual conversion
 *
 * In the event of a continual stream of mutations (e.g. an animation-style
 * app), it is conceivable that the row record data be continually behind
 * the CVR metadata. In order to effect eventual convergence, a new view-syncer
 * signals the current view-syncer to stop updating by writing new `owner`
 * information to the `cvr.instances` row. This effectively stops the mutation
 * processing (in {@link CVRStore.#checkVersionAndOwnership}) so that the row
 * data can eventually catch up, allowing the new view-syncer to take over.
 *
 * Of course, there is the pathological situation in which a view-syncer
 * process crashes before the pending row updates are flushed. In this case,
 * the wait timeout will elapse and the CVR considered invalid.
 */
export declare class RowRecordCache {
    #private;
    constructor(lc: LogContext, db: PostgresDB, shard: ShardID, cvrID: string, failService: (e: unknown) => void, deferredRowFlushThreshold?: number, setTimeoutFn?: typeof setTimeout);
    recordSyncFlushStats(stats: CVRFlushStats, elapsedMs: number): void;
    getRowRecords(): Promise<ReadonlyMap<RowID, RowRecord>>;
    /**
     * Applies the `rowRecords` corresponding to the `rowsVersion`
     * to the cache, indicating whether the corresponding updates
     * (generated by {@link executeRowUpdates}) were `flushed`.
     *
     * If `flushed` is false, the RowRecordCache will flush the records
     * asynchronously.
     *
     * Note that `apply()` indicates that the CVR metadata associated with
     * the `rowRecords` was successfully committed, which essentially means
     * that this process has the unconditional right (and responsibility) of
     * following up with a flush of the `rowRecords`. In particular, the
     * commit of row records are not conditioned on the version or ownership
     * columns of the `cvr.instances` row.
     */
    apply(rowRecords: Map<RowID, RowRecord | null>, rowsVersion: CVRVersion, flushed: boolean): Promise<number>;
    hasPendingUpdates(): boolean;
    /**
     * Returns a promise that resolves when all outstanding row-records
     * have been committed.
     */
    flushed(lc: LogContext): Promise<void>;
    clear(): void;
    catchupRowPatches(lc: LogContext, afterVersion: NullableCVRVersion, upToCVR: CVRSnapshot, current: CVRVersion, excludeQueryHashes?: string[]): AsyncGenerator<RowsRow[], void, undefined>;
    executeRowUpdates(tx: PostgresTransaction, version: CVRVersion, rowUpdates: Map<RowID, RowRecord | null>, mode: 'allow-defer' | 'force'): PendingQuery<Row[]>[];
}
//# sourceMappingURL=row-record-cache.d.ts.map