/** * File locking using proper-lockfile. * Prevents concurrent modifications to CLEO data files. * @epic T4454 * @task T4457 */ /** A release function returned by acquireLock. */ export type ReleaseFn = () => Promise; /** * Acquire an exclusive lock on a file. * Returns a release function that must be called when done. */ export declare function acquireLock(filePath: string, options?: { stale?: number; retries?: number; onCompromised?: (err: Error) => void; }): Promise; /** * A held lock that can be released, or abandoned when it may no longer be * ours (T13299). */ export interface AbandonableLock { /** Release the lock: stop refreshing it and remove its directory. */ release: ReleaseFn; /** * Stop holding the lock WITHOUT removing its directory: for a lock that was * lost or outlasted its stale window, which another process may have taken * since. proper-lockfile's release and its exit hook remove the directory * without checking who owns it; after `abandon` neither touches it. A * directory that was still ours is already stale, so the next taker * reclaims it. Never throws. */ abandon: ReleaseFn; } /** * {@link acquireLock}, returning a lock that can also be abandoned (see * {@link AbandonableLock}). The lock's file operations go through node's fs, * with the directory removal skipped once the lock is abandoned. * * @param filePath - The file to lock (the lock is `.lock`). * @param options - As for {@link acquireLock}. * @returns The held lock. * @throws CleoError (LOCK_TIMEOUT) when the lock cannot be acquired. * @task T13299 */ export declare function acquireAbandonableLock(filePath: string, options?: { stale?: number; retries?: number; onCompromised?: (err: Error) => void; }): Promise; /** * Check if a file is currently locked. * * @param filePath - The locked file. * @param options - `stale` must match the holder's `stale` (ms): a holder * refreshes its lock every `stale / 2`, so checking with a shorter window * reports a live long-running holder as unlocked. */ export declare function isLocked(filePath: string, options?: { stale?: number; }): Promise; /** * Execute a function while holding an exclusive lock on a file. * The lock is automatically released when the function completes (or throws). */ export declare function withLock(filePath: string, fn: () => Promise, options?: { stale?: number; retries?: number; onCompromised?: (err: Error) => void; }): Promise; /** * Run `fn` holding an exclusive cross-process lock on `filePath`, without * yielding: for read-modify-write of a small file from synchronous code (a * store open). Waits up to `waitMs` for another holder; a lock whose holder * stopped refreshing it for `stale` ms is taken over. The file need not exist. * * @param filePath - The file to lock (the lock is `.lock`). * @param fn - Runs while the lock is held; the lock is released when it returns or throws. * @param options - Wait budget and stale age. * @returns What `fn` returns. * * @task T12908 */ export declare function withLockSync(filePath: string, fn: () => T, options?: { waitMs?: number; stale?: number; label?: string; }): T; /** The compromise state of one long-held lock ({@link lockCompromiseTracker}). */ export interface LockCompromiseTracker { /** Pass as `onCompromised`: records the loss instead of throwing from a timer. */ readonly onCompromised: (err: Error) => void; /** Why the holder lost the lock (another process took it as stale), or null. */ readonly reason: () => string | null; } /** * Track whether a long-held lock was compromised (T12785). proper-lockfile * refreshes a held lock every `stale / 2` from a timer; a holder whose event * loop is blocked longer than `stale` (one long synchronous transaction) can * have the lock taken by another process, and the default `onCompromised` * then throws from that timer, an uncaught exception. The tracker records the * loss instead, so the holder can stop at its next safe point and roll back. */ export declare function lockCompromiseTracker(): LockCompromiseTracker; //# sourceMappingURL=lock.d.ts.map