/** * Copyright (c) 2025 Elara AI Pty Ltd * Licensed under BSL 1.1. See LICENSE for details. */ import { type LockState, type LockOperation } from '@elaraai/e3-types'; import { type LockHolderInfo } from '../../errors.js'; import type { LockHandle, LockService } from '../interfaces.js'; /** * Handle to a held workspace lock. * Call release() when done to free the lock. */ export interface WorkspaceLockHandle { readonly resource: string; readonly workspace: string; readonly lockPath: string; release(): Promise; } /** * Options for acquiring a workspace lock. */ export interface AcquireLockOptions { /** If true, wait for the lock to become available. Default: false */ wait?: boolean; /** Timeout in milliseconds when wait=true. Default: 30000 */ timeout?: number; /** Lock mode. Default: 'exclusive' */ mode?: 'shared' | 'exclusive'; } /** Path to the exclusive lock file for a workspace. */ export declare function workspaceLockPath(repoPath: string, workspace: string): string; export declare function lockStateToHolderInfo(state: LockState): LockHolderInfo; /** * Defense-in-depth grace before a present-but-empty/undecodable lock file is * reclaimed as stale. * * Exclusive locks are created *atomically with their content* (see * {@link atomicCreateLockFile}), so a held exclusive lock is never observed empty * and this branch does not fire for them. The grace still guards two residual * sources of a transiently-empty lock file: the O_EXCL+write *fallback* used on * filesystems without hardlink support, and shared `.slock` files (written * non-atomically). Reclaiming such a file mid-creation would admit a second holder * — a silent lost update under the record compare-and-swap in `writeIf`. The grace * covers a create→write window generously while staying far below the 30s * lock-wait timeout, so a genuinely crashed-mid-create remnant is still reclaimed * promptly. Exported so tests can pin the boundary without sleeping. */ export declare const EMPTY_LOCK_GRACE_MS = 1000; export declare function isLockHolderAlive(holderStr: string): Promise; /** * Acquire an exclusive or shared lock on a workspace. * * Uses atomic O_CREAT|O_EXCL file creation (exclusive) or per-holder slock * files (shared). Works on Linux, macOS, and Windows without external commands. * * @throws {WorkspaceLockError} If the lock cannot be acquired */ export declare function acquireWorkspaceLock(repoPath: string, workspace: string, operation: LockOperation, options?: AcquireLockOptions): Promise; export declare function getWorkspaceLockState(repoPath: string, workspace: string): Promise; export declare function getWorkspaceLockHolder(repoPath: string, workspace: string): Promise; export declare class LocalLockService implements LockService { acquire(repo: string, resource: string, operation: LockOperation, options?: { wait?: boolean; timeout?: number; mode?: 'shared' | 'exclusive'; }): Promise; getState(repo: string, resource: string): Promise; isHolderAlive(holder: string): Promise; } //# sourceMappingURL=LocalLockService.d.ts.map