import * as Express from 'express'; import { DyFM_Log } from '@futdevpro/fsm-dynamo'; import { DyNTS_global_settings } from './global-settings.const'; import { DyNTS_MemoryGuard } from '../_services/core/memory-guard.service'; /** * Auto-load-shed Express-middleware (BFR-OVERSEER-009 maradék — a MemoryGuard self-heal rétege). * * CRITICAL memória-nyomásnál (`DyNTS_MemoryGuard.shouldShedLoad()` — heap-% VAGY GC-thrash küszöb * felett) az új, NEM-esszenciális kéréseket gyors **503 + Retry-After**-rel ejti, mielőtt azok * tovább terhelnék a heap-et — a GC levegőhöz jut, a death-spiral (2026-07-05 Overseer-eset: * GC 100%, event-loop blokk, restart-immún wedge) megelőzhető. * * - **Opt-in:** csak `memoryGuard.loadShedEnabled: true` esetén mountolódik (ops-döntés). * - **Esszenciális-kivétel:** a `loadShedExemptPathParts` path-részekre (healthcheck/readiness/ * status/diag) SOSEM shed-el — különben a restart-policy health-probe-ját ölné meg (öngól). * - A shed-döntés kérésenként olcsó (in-memory pressure-olvasás, nincs I/O). */ export function DyNTS_createLoadShedMiddleware(): Express.Handler { const exemptParts: string[] = DyNTS_global_settings.memoryGuard?.loadShedExemptPathParts ?? ['/health', '/readiness', '/status', '/diag']; let lastShedLogAt: number = 0; return (req: Express.Request, res: Express.Response, next: Express.NextFunction): void => { // esszenciális útvonal → soha nem shed-elünk if (exemptParts.some((part: string): boolean => req.path.includes(part))) { next(); return; } if (DyNTS_MemoryGuard.getInstance().shouldShedLoad()) { // log-throttle: shed-viharban sem árasztjuk el a logot (10s-enként egy jelzés) const now: number = Date.now(); if (now - lastShedLogAt > 10000) { lastShedLogAt = now; DyFM_Log.warn( `[load-shed] CRITICAL memory pressure — shedding non-essential requests (503). path: ${req.path}` ); } res.status(503).setHeader('Retry-After', '10'); res.send({ message: 'Server is under critical memory pressure. Retry shortly.' }); return; } next(); }; }