SPB Git forge

spb/vrai-prix

Public

Vrai-Prix — l'évaluation du vrai prix des propriétés résidentielles au Québec.

60commits 1branches 0releases
12.3 MBsize
maindefault branch
17 days agolast push
TypeScript 90.2% JavaScript 3.5% Python 3.4% CSS 1.9% HTML 0.6%
1.5 KB · 41 lines typescript
Raw Blame History
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2/**3 * Cache mémoire simple (par processus) pour les lectures coûteuses de la base4 * de coûts : aperçu, assemblages, indices. Invalidé par TTL et par la clé5 * `last_ingest` (cost_meta) mise à jour à chaque ingestion.6 */7import { metaGet } from "./db";89interface Entry<T> { value: T; expires: number; ingest: string | null }10const store = new Map<string, Entry<unknown>>();1112export function cached<T>(key: string, ttlMs: number, compute: () => T): T {13  let ingest: string | null = null;14  try { ingest = metaGet("last_ingest"); } catch { /* base indisponible */ }15  const e = store.get(key) as Entry<T> | undefined;16  if (e && e.expires > Date.now() && e.ingest === ingest) return e.value;17  const value = compute();18  store.set(key, { value, expires: Date.now() + ttlMs, ingest });19  return value;20}2122export function invalidateCache(): void {23  store.clear();24}2526/** Limiteur de débit en mémoire (par clé, fenêtre glissante). */27const hits = new Map<string, number[]>();28export function rateLimit(key: string, max: number, windowMs: number): boolean {29  const now = Date.now();30  const arr = (hits.get(key) ?? []).filter((t) => now - t < windowMs);31  if (arr.length >= max) { hits.set(key, arr); return false; }32  arr.push(now);33  hits.set(key, arr);34  return true;35}3637export function clientKey(req: Request): string {38  const xff = req.headers.get("x-forwarded-for");39  return (xff ? xff.split(",").pop()!.trim() : req.headers.get("x-real-ip")) ?? "local";40}41