/** * Lazy browser-engine acquisition (design D3). When the browser tier is entered * on a machine where the browser executable is not installed, we join a MEMOIZED * install promise instead of hard-failing. The in-call wait is bounded; if the * install has not finished by the budget, the fetch falls back to lower-tier * content (when any exists) with an actionable note, while the install continues * in the background. A failed/timed-out install is memoized so offline machines * stall at most once per retry window. * * Everything here is instance state on a single {@link BrowserAcquirer}; the * router holds ONE acquirer, so memoization and the failure window are shared * across every browser-tier call site. */ /** Result of an acquisition attempt. */ export type AcquireOutcome = 'ready' | 'unavailable'; /** Actionable, capability-language note shown when the browser is still installing. */ export declare const BROWSER_INSTALLING_NOTE = "browser engine installing in background (~1-2 min); retry shortly, or run `wigolo warmup --browser`"; /** Actionable, capability-language error when a fetch cannot proceed without a browser. */ export declare const BROWSER_UNAVAILABLE_ERROR = "browser engine required for this page but not installed; installing in background (~1-2 min) \u2014 retry shortly, or run `wigolo warmup --browser`"; /** * Probe whether the browser executable is present on disk. Cheap — resolves the * bundled Playwright's `executablePath()` and `existsSync`, mirroring * browser-probe.ts's `onDisk` check (no launch smoke-test, which would cost 30s * on the hot fetch path). Never throws. */ export declare function browserInstalledOnDisk(): boolean; export interface BrowserAcquirerDeps { /** Probe for the browser binary on disk. Defaults to {@link browserInstalledOnDisk}. */ isInstalled?: () => boolean; /** Run the install; resolves true on success. Defaults to the warmup driver. */ install?: () => Promise; /** Clock, injectable for fake-timer tests. Defaults to Date.now. */ now?: () => number; /** Directory for the cross-process install lockfile. Defaults to config dataDir. */ dataDir?: string; /** In-call wait budget (ms). Defaults to env WIGOLO_BROWSER_INSTALL_WAIT_MS or 20000. */ waitMs?: number; /** Failure-memoization window (ms). Defaults to env WIGOLO_BROWSER_INSTALL_RETRY_MS or 600000. */ retryMs?: number; } /** * Coordinates lazy browser acquisition for a single router. Holds the memoized * install promise, the failure window, and the cross-process lockfile. */ export declare class BrowserAcquirer { private readonly log; private readonly isInstalled; private readonly install; private readonly now; private readonly deps; /** In-flight (or completed-successfully) install promise, memoized. */ private installPromise; /** Timestamp of the last failed/timed-out install; drives the retry window. */ private lastFailureAt; /** Latched true once a probe (or install) has confirmed the browser present. */ private confirmedInstalled; constructor(deps?: BrowserAcquirerDeps); private get waitMs(); private get retryMs(); private get lockPath(); /** * Ensure the browser engine is available for the caller's fetch. * - Already installed → 'ready' immediately (no installer touched). * - Missing, within the failure window → 'unavailable' immediately (no * second install; offline machines stall at most once per window). * - Missing → join the memoized install and wait up to the budget. If it * finishes 'ok' in time → 'ready'; otherwise 'unavailable' (install keeps * running in the background so a later call joins the same promise). */ ensureBrowser(): Promise; /** * Return the memoized install promise, starting it (once) if idle. On * resolution the promise is cleared on failure (so a later call after the * retry window can retry) and the failure timestamp is stamped; on success it * is left resolved so subsequent joins short-circuit. */ private startOrJoinInstall; /** * Poll for the browser binary to appear (another process is installing it). * Bounded by the lock staleness so a crashed foreign installer can't hang us * forever — the in-call wait budget in ensureBrowser() is the real ceiling. */ private waitForForeignInstall; /** * Acquire the cross-process install lockfile (mirrors the searxng.lock * pattern). Returns true when this process now holds the lock, false when a * live foreign process holds it. Stale locks (dead pid or age past * LOCK_STALE_MS) are reclaimed. */ private acquireLock; private releaseLock; private tryUnlink; } //# sourceMappingURL=browser-acquire.d.ts.map