/** * Cross-Platform File Locking for NotebookLM MCP Server * * Provides advisory file locking to prevent race conditions when * multiple concurrent sessions access shared state files. * * Features: * - Cross-platform (Linux, macOS, Windows) * - Stale lock detection and cleanup * - Timeout with retry * - Process ID tracking * * Used for: * - Quota file updates (prevent concurrent increment race) * - Auth state save/load (prevent corruption) * - Browser context creation (prevent parallel recreations) */ /** * Lock options */ export interface LockOptions { /** Max time to wait for lock (ms) */ timeout?: number; /** Time between retry attempts (ms) */ retryInterval?: number; /** Lock considered stale after this time (ms) */ staleThreshold?: number; } /** * Single shared stale-lock threshold (L15). * * The async FileLock util and the synchronous shutdown-flush path in * audit-logger.ts (writeWithSyncLock) lock the SAME audit-*.jsonl files, so they * MUST agree on when a lock is stale. They previously diverged (900_000ms here vs * a hardcoded 30_000ms in the sync path): the sync path could steal a lock at 30s * that the async owner still considered live (900s), and both would then write the * same audit file concurrently — corrupting the very log the lock protects. * * Unified UP to 900_000ms (15 min): losing a best-effort shutdown flush (the sync * path only waits 10s total anyway) is strictly less bad than corrupting the audit * log. Overridable via NLMCP_LOCK_STALE_MS. */ export declare const STALE_LOCK_THRESHOLD_MS: number; /** * File Lock Class * * Simple cross-platform file locking using lock files. * Works on Linux, macOS, and Windows. */ export declare class FileLock { private lockPath; private acquired; private lockId; constructor(filePath: string); /** * Acquire lock with retry and timeout */ acquire(options?: LockOptions): Promise; /** * Release lock */ release(): void; /** * Check if lock is acquired */ isAcquired(): boolean; } /** * Execute operation with file lock * * Acquires lock, executes operation, releases lock. * Ensures lock is always released even if operation throws. * * @param filePath - Path to the file to lock (lock file will be filePath + ".lock") * @param operation - Async operation to execute while holding lock * @param options - Lock options * @returns Result of the operation * @throws Error if lock cannot be acquired within timeout */ export declare function withLock(filePath: string, operation: () => Promise, options?: LockOptions): Promise; /** * Check if a file is currently locked * * Note: This is a point-in-time check and may be stale immediately after. * Only use for informational purposes. */ export declare function isLocked(filePath: string, staleThreshold?: number): boolean; /** * Force remove a lock file (use with caution) * * Only use when you're certain the lock is orphaned. */ export declare function forceUnlock(filePath: string): boolean;