/**
 * Process-level crash policy for `serve`.
 *
 * `uncaughtException` keeps fail-fast shutdown: a synchronous throw can leave
 * shared state mid-mutation, and Node documents resuming after one as unsafe.
 *
 * Unhandled REJECTIONS are a different population in practice: they are
 * overwhelmingly request-scoped async failures that escaped a reply lifecycle.
 * The motivating outage (1.3.48-next.224): a non-ASCII asset filename in an
 * ETag made Node throw ERR_INVALID_CHAR at header-send time, which surfaced as
 * an unhandledRejection — and ONE share-page font request took the whole
 * workspace down for every user until the platform restarted it. Exiting
 * trades one request's bug for a tenant-wide outage; a request-scoped failure
 * should cost that request a failed response, not the tenant its server.
 *
 * Policy: log loudly and keep serving — UNLESS rejections arrive in a storm
 * (≥ stormMax within stormWindowMs), which indicates systemic breakage (a
 * poisoned event loop, corrupted shared state, a tight failing retry loop)
 * rather than an isolated bad request. A storm fails fast exactly like the
 * old policy; every crash path stays recoverable on next boot (sessions
 * persist on markDirty, recoverOnBoot replays).
 */
export const REJECTION_STORM_MAX = 5;
export const REJECTION_STORM_WINDOW_MS = 30_000;
/** Build the `process.on('unhandledRejection')` listener implementing the
 *  log-and-continue-with-storm-breaker policy above. Pure factory (no process
 *  wiring) so the policy is unit-testable without spawning a server. */
export function createUnhandledRejectionHandler(options) {
    const { onFatal, log = (message, err) => console.error(message, err), now = Date.now, stormMax = REJECTION_STORM_MAX, stormWindowMs = REJECTION_STORM_WINDOW_MS, } = options;
    const recent = [];
    return (err) => {
        const t = now();
        recent.push(t);
        while (recent.length > 0 && t - recent[0] > stormWindowMs)
            recent.shift();
        if (recent.length >= stormMax) {
            log(`[serve] unhandledRejection storm (${recent.length} in ${stormWindowMs / 1000}s) — systemic failure, shutting down:`, err);
            onFatal(err);
            return;
        }
        log('[serve] unhandledRejection (continuing — an isolated rejection must not cost the workspace):', err);
    };
}
//# sourceMappingURL=process-guards.js.map