/** * Locking and id allocation for a project's tickets folder * (specs/2026-09-28-project-tickets.md §2 "Concurrency"). * * Two layers, because writers live in more than one process (the backend, * a `crewly tickets migrate` run, a second backend on the same machine): * - an in-process operation lock keyed on the folder, so concurrent async * callers in one process queue up instead of polling the lockfile; * - a lockfile created with `O_EXCL` (`wx`), so other processes wait too. A * lockfile older than {@link PROJECT_TICKET_CONSTANTS.LOCK_STALE_MS} was left * by a crashed writer and is taken over. * * @module services/project-tickets/ticket-folder-lock */ /** Counter file shape. */ export interface TicketCounter { prefix: string; next: number; } /** * Run `fn` while holding the folder's in-process and cross-process locks. * Creates the folder (and its own `.gitignore` for the lock and temp files) * when missing. * * @param dir - Absolute tickets folder * @param fn - Critical section * @returns Whatever `fn` returns * @throws When the lock cannot be taken, or whatever `fn` throws * * @example * ```typescript * await withTicketFolderLock(dir, async () => writeTicket(...)); * ``` */ export declare function withTicketFolderLock(dir: string, fn: () => Promise): Promise; /** * Derive a ticket id prefix from a project name: up to four letters/digits, * preferring word initials for multi-word names. * * @param projectName - Project display name * @returns Uppercase prefix (never empty) * * @example * ```typescript * derivePrefix('crewly'); // 'CREW' * derivePrefix('Steam Fun Portal'); // 'SFP' * ``` */ export declare function derivePrefix(projectName: string): string; /** * Read the counter file (missing or corrupt → null). * * @param dir - Tickets folder * @returns Counter, or null */ export declare function readCounter(dir: string): Promise; /** * Allocate the next ticket id. MUST be called while holding * {@link withTicketFolderLock} for the same folder. * * Takes `max(counter.next, highest used + 1)` so ids that arrive through a * git merge are never reused, then advances the counter. * * @param dir - Tickets folder * @param projectName - Used to derive the prefix the first time * @returns The new id, e.g. `CREW-13` */ export declare function allocateTicketId(dir: string, projectName: string): Promise; //# sourceMappingURL=ticket-folder-lock.d.ts.map