perf: istemci istek cache'i (dedup+TTL) ve profil cache (Faz 5)

- lib/istek-cache: modül seviyesi in-flight dedup + 5dk TTL cache (SWR
  bağımlılığı olmadan); caller iptali paylaşılan fetch'i düşürmez
- /api/facetler'in 5 çağrı yeri (hero, cta, kapı, sihirbaz adımları, demo)
  ve /api/katalog-ara cache'e bağlandı — sihirbazda 2↔3 adım geçişi ve
  tekrarlanan aramalar artık ağa çıkmıyor; /api/soru GET dedup-only (ttl 0)
- katalog-arama: elle yukleniyor state'i kalktı, "cevaplanmamış sorgu"
  türetmesi + startTransition; rehber puanlaması Schwartzian; ⌘K listener'ı
  useEffectEvent ile tek sefer bağlanıyor
- sihirbaz-adimlar: il sort/filter useMemo (çip başına 81 eleman kopyalanıp
  sıralanıyordu, harita dizisi referansı sabitlendi)
- sohbet-client: stream chunk güncellemeleri startTransition'da — cevap
  akarken input yazımı bloklanmıyor
- sihirbaz-profil: modül cache + event/storage geçersizlemesi (tek "+"
  tıklamasında 3 localStorage okuma + JSON.parse vardı)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-08-08 14:11:05 +03:00
parent 90ac590737
commit 668568b5b5
9 changed files with 174 additions and 57 deletions

View File

@@ -19,6 +19,7 @@ import { ArrowRight } from "lucide-react";
import { useTercihProfili } from "@/features/liste/hooks/use-tercih-profili";
import { PUAN_TURU_ETIKET, sonucHref } from "@/features/sihirbaz/sihirbaz-sabitler";
import type { DilimKey, SihirbazFacetleri } from "@/types/yokatlas";
import { onbellekliJsonGetir } from "@/lib/istek-cache";
export type DemoVeri = {
facetler: SihirbazFacetleri;
@@ -48,12 +49,11 @@ async function facetGetir(
): Promise<{ facetler: SihirbazFacetleri; dilimToplam?: Record<DilimKey, number> } | null> {
const params = new URLSearchParams({ sira: String(sira), tur, dilimler: "1" });
try {
const res = await fetch(`/api/facetler?${params}`, { signal });
if (!res.ok) return null;
return (await res.json()) as {
// Demo slider'ı aynı sıraya dönünce cache'ten okur (dedup+TTL)
return await onbellekliJsonGetir<{
facetler: SihirbazFacetleri;
dilimToplam?: Record<DilimKey, number>;
};
}>(`/api/facetler?${params}`, { signal });
} catch {
return null;
}