import type { FunctionCfg } from './cfg.js'; /** One persisted overlay row, with its CFG already in the exact form the table stores. */ export interface CfgSpillRow { functionId: string; filePath: string; cfgJson: string; } /** * Test-only: lower the overflow threshold so a small fixture crosses it, exercising the on-disk * path without a multi-megabyte overlay. Returns the previous value so callers can restore it. */ export declare function _setOverflowThresholdBytesForTesting(n: number): number; /** * Filename prefix for a spill. Exported so the bundle exporter can refuse to ship one and the * sweep can recognise a leaked one: a build killed mid-flight (an OOM-kill, a Ctrl-C) leaves the * file behind, and it holds the entire overlay. */ export declare const CFG_SPILL_PREFIX = ".cfg-spill-"; /** * Test-only: shrink the drain chunk so a small fixture straddles it. * * Without this, exercising the partial-line carry — the only subtle part of the reader — needs a * spill larger than 4 MB, which is slow enough to destabilize neighbouring tests. Returns the * previous value so callers can restore it. */ export declare function _setDrainChunkBytesForTesting(n: number): number; export declare class CfgSpill { readonly path: string; private buffer; private bufferedBytes; private mode; private fd; private fileCreated; private rows; private disposed; private constructor(); /** * Bind a spill to its output directory. No file is created here — the overlay starts in memory * and a file is opened lazily only if it overflows, so a repository whose overlay fits the * threshold never touches the disk. Never fails: an unwritable directory surfaces at overflow, * where it degrades to a disclosed missing overlay rather than a failed analysis. */ static open(outputDir: string): Promise; /** * Did a write fail? A failed spill must be discarded whole, never persisted in part — the * consumer skips it and the overlay degrades to a disclosed function-granularity answer. */ get failed(): boolean; /** How many rows have been accepted. */ get count(): number; /** * Record one file's overlay. Serializes here, at the point the CFGs are still warm, so the CFG * objects become collectable as soon as the caller drops its reference to them — the in-memory * buffer holds the compact serialized form, not the live object graph (issue #304). */ write(filePath: string, cfgs: Iterable<[string, FunctionCfg]>): void; /** * Move the accumulated buffer to a file and switch to streaming subsequent rows there. Attempted * AT MOST ONCE: if it fails the spill latches `failed` and no later write reopens the file. A * per-write retry reopened and rewrote the whole buffer for every function past the threshold — * measured 5× slower on a large repository (issue #306). */ private overflow; /** Write the pending buffer to the open file in bounded sub-batches, then clear it. */ private flushToDisk; /** * Latch the failed state: drop the buffer, close and remove any partial file so a truncated spill * is never left for the drain or the bundle exporter to find. */ private latchFailed; /** Flush and close. Must be awaited before {@link drain}. A no-op while the overlay is in memory. */ finish(): Promise; /** * Read the spilled rows back, one at a time. From memory when the overlay never overflowed; * otherwise from the file, never holding more than one chunk plus the partial line straddling it. */ drain(): AsyncGenerator; /** Remove the spill file, if one was ever created. Idempotent, and never throws. */ dispose(): Promise; } /** * Remove spill files left by builds that died before they could clean up. * * Only files whose owning process is gone are removed: a spill belongs to a live analysis until * that analysis ends, and a long build on a large repository can legitimately run for hours, so * age alone is not a safe signal. `kill(pid, 0)` tests liveness without signalling. * * Best effort throughout — a sweep that cannot run must never stop an analysis. */ export declare function sweepLeakedCfgSpills(outputDir: string): Promise; //# sourceMappingURL=cfg-spill.d.ts.map