/** * Deadline guards for filesystem work that can land on a network mount. * * Inside the agent container `/skaile/workspace` **is** an rclone FUSE mount * (SharePoint / OneDrive / WebDAV). When the host rclone process wedges, a * filesystem call against that path parks in an uninterruptible kernel wait. * A **synchronous** call there stops the entire single-threaded event loop — * the whole `skaile serve` process stops serving, and the platform reads the * session as dead or idle. A hang is not an error, so `try/catch` never fires. * * Two rules follow, and both matter: * * 1. **Never touch a mount synchronously.** Async `node:fs/promises` keeps the * loop free, so a wedged mount degrades to one stuck request instead of a * dead session. This is the actual fix. * 2. **Bound the wait.** {@link withFsDeadline} converts an unbounded wait into * a bounded failure so the requester gets an error rather than nothing. * * `withFsDeadline` does **not** cancel the underlying operation — Node cannot * abort a syscall already in the kernel. The losing promise stays pending until * the mount recovers or the process exits. That is acceptable precisely because * rule 1 holds: a pending promise costs one handle, not the event loop. * * Modelled on `connectors/src/fleet-utils.ts` (`ensureFleetMounted`), which * already does async-stat-with-deadline correctly. */ /** Default deadline for a single filesystem operation on a possibly-networked mount. */ export declare const DEFAULT_FS_DEADLINE_MS = 15000; /** * Env override for {@link DEFAULT_FS_DEADLINE_MS}, in milliseconds. * * A cloud-backed mount over a slow link can legitimately need longer than the * default; operators raise this rather than patching call sites. */ export declare const FS_DEADLINE_ENV_VAR = "SKAILE_FS_DEADLINE_MS"; /** * Thrown when a filesystem operation misses its deadline. * * Distinct from a plain `Error` so callers can tell "the mount is wedged" apart * from "the file does not exist" and surface the right message to the frontend. */ export declare class FsDeadlineError extends Error { readonly timeoutMs: number; readonly operation: string; constructor(operation: string, timeoutMs: number); } /** * Resolve the effective filesystem deadline. * * Reads {@link FS_DEADLINE_ENV_VAR} on every call rather than caching it: the * runner mutates `process.env` while wiring a session, so a module-load-time * snapshot would pin the value set before configuration ran. * * @param fallback - Deadline to use when the env var is absent or unusable. * @returns The deadline in milliseconds. */ export declare function fsDeadlineMs(fallback?: number): number; /** * Run an async filesystem operation under a deadline. * * @param operation - Short label used in the timeout message (e.g. `"readdir /skaile/workspace"`). * @param fn - Thunk performing the operation. Called immediately. * @param timeoutMs - Deadline override; defaults to {@link fsDeadlineMs}. * @returns The operation's result. * @throws {FsDeadlineError} when the deadline elapses first. * @throws Whatever `fn` rejects with, unchanged, when it loses no race. * @docLink packages/core/api-reference#with-fs-deadline */ export declare function withFsDeadline(operation: string, fn: () => Promise, timeoutMs?: number): Promise; /** * Run an async filesystem operation under a deadline, mapping every failure to * `fallback`. * * For best-effort probes that previously used `existsSync` — a missing file, an * unreadable file, and a wedged mount are all "nothing usable here", and the * caller has no better move than to continue without it. * * @param operation - Short label used in the timeout message. * @param fn - Thunk performing the operation. * @param fallback - Value returned when `fn` rejects or the deadline elapses. * @param timeoutMs - Deadline override; defaults to {@link fsDeadlineMs}. */ export declare function tryWithFsDeadline(operation: string, fn: () => Promise, fallback: T, timeoutMs?: number): Promise; //# sourceMappingURL=fs-deadline.d.ts.map