export interface PersistentCacheOptions { /** Maximum entries retained in memory and in the persisted snapshot. */ max?: number; /** Default entry lifetime in milliseconds. Zero means no expiry. */ ttl?: number; /** Set false to prohibit every persistence filesystem operation. */ persistence?: boolean; /** Absolute directory for this cache namespace. */ directory?: string; /** Maximum UTF-8 bytes accepted from or written to the cache file. */ maxFileBytes?: number; } /** * LRU cache backed by `lru-cache` with optional disk persistence. * * - Loads from the private Zynor temporary directory on construction. * - Saves on a debounced timer and on `process.beforeExit`. * - Falls back to in-memory only if the persistence directory is unsafe or * unavailable. */ export declare class PersistentCache { private cache; private readonly filePath; private readonly max; private readonly maxFileBytes; private dirty; private saveTimer; private retryAttempt; private disposed; private readonly ttl; private instanceReference; /** Persistence is delta-based so independent processes merge unrelated * mutations instead of replacing one another's stale snapshots. */ private pendingSets; private pendingDeletes; private pendingClear; private persistedKeys; private mutationVersion; private invalidCacheWarningEmitted; constructor(name: string, options?: PersistentCacheOptions); /** Get a value. Returns undefined on miss/expired. */ get(key: string): T | undefined; /** Set a value with the default TTL. */ set(key: string, value: T, ttlMs?: number): void; /** Check existence (non-expired). */ has(key: string): boolean; /** Delete a key. */ delete(key: string): boolean; /** Clear all entries. */ clear(): void; /** Number of entries. */ get size(): number; /** * Flush pending data and detach this cache from process lifecycle hooks. * * Returns `false` when pending persistence could not be committed. The * pending delta is retained, so the caller may invoke `flush()` again. * The cache remains usable in memory, but mutations after disposal are * intentionally not added to the persistence delta. */ dispose(): boolean; /** * Force one immediate save attempt. * * Returns `true` when there was nothing to persist or the complete * read/merge/write transaction committed. On contention or I/O failure, * returns `false`, retains the pending delta, and schedules an unref'd * bounded-backoff retry while the cache is active. */ flush(): boolean; private flushInternal; private enforcePersistedLimit; /** Oldest/non-local entries are removed first for either bound. */ private persistedEvictionOrder; /** * Serialize under the configured byte ceiling before the fenced write. * Entries are preflighted independently and retained newest/local-first; * the complete hostile payload is never passed to JSON.stringify merely * to discover that it exceeds the ceiling. */ private serializeWithinFileLimit; /** * Acquire once without waiting. * * The canonical gate is a non-empty directory containing both a fixed * lease hard link and the token-specific owner file that will become the * committed cache. Capturing the directory therefore fences the commit * source atomically, even if a delayed remover races with a replacement. */ private acquirePersistenceLock; /** Recover an expired lease without PID-liveness assumptions. */ private recoverStalePersistenceLock; /** * Migrate an abandoned lock from the short-lived flat-file protocol. * Transaction siblings are fenced first so a crashed old owner cannot * later publish after the canonical file is removed. */ private recoverLegacyFileLock; private cleanupLegacyTransactions; /** Best-effort cleanup for already-fenced captures and old temp files. */ private cleanupPersistenceDebris; private recoverLockDirectory; /** * Atomically move the complete lock namespace out of the canonical path. * * A post-check mismatch is deliberately never restored: the rename has * already fenced every commit source inside the captured directory, and * restoring it after another owner acquires would recreate an ABA writer. */ private capturePersistenceLockDirectory; private moveLockDirectory; private cleanupCapturedLockDirectory; /** Capture an exact legacy or failed-acquisition file without restoring. */ private captureLockFile; private verifyPersistenceLockPaths; /** Refresh and verify the descriptor, directory, owner, and lease fence. */ private refreshPersistenceLock; /** * Publish the complete owner inode. The rename is the commit point. * * Closing first supports filesystems that restrict open-file moves. If * recovery captured the directory after the final refresh, the canonical * token-specific source path is gone and rename fails. Once rename * succeeds, no post-commit filesystem check may make the caller replay * this now-committed delta over a newer writer. */ private commitPersistenceLock; private publishOwnerFile; /** Release by capturing the whole namespace; a racing writer is fenced. */ private releasePersistenceLock; private readLockPayload; private isValidLockPayload; private writeLockContents; private load; private readPersistedEntries; private warnInvalidCacheFile; private recordCacheEviction; private scheduleSave; private scheduleRetry; private clearSaveTimer; }