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:
@@ -12,16 +12,34 @@ function profilDegistiginiYayinla(): void {
|
||||
window.dispatchEvent(new Event(PROFIL_DEGISTI_EVENT));
|
||||
}
|
||||
|
||||
// tercihProfiliOku 18 farklı yerden çağrılıyor ve tek bir "+" tıklaması bile
|
||||
// 3 kez okuyabiliyor; her çağrıda localStorage + JSON.parse + şema doğrulama
|
||||
// yapmamak için modül seviyesi cache (js-cache-storage). Geçersizleme iki
|
||||
// kanaldan: aynı sekmede PROFIL_DEGISTI_EVENT, diğer sekmelerde "storage".
|
||||
// undefined = henüz okunmadı, null = okundu ve profil yok.
|
||||
let profilCache: TercihProfili | null | undefined;
|
||||
if (typeof window !== "undefined") {
|
||||
window.addEventListener(PROFIL_DEGISTI_EVENT, () => {
|
||||
profilCache = undefined;
|
||||
});
|
||||
window.addEventListener("storage", (e) => {
|
||||
if (e.key === SIHIRBAZ_STORAGE_KEY || e.key === null) {
|
||||
profilCache = undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Client'ta SIHIRBAZ_STORAGE_KEY'den doğrulanmış profil okur. */
|
||||
export function tercihProfiliOku(): TercihProfili | null {
|
||||
if (typeof window === "undefined") return null;
|
||||
if (profilCache !== undefined) return profilCache;
|
||||
try {
|
||||
const ham = localStorage.getItem(SIHIRBAZ_STORAGE_KEY);
|
||||
if (!ham) return null;
|
||||
return tercihProfiliDogrula(JSON.parse(ham));
|
||||
profilCache = ham ? tercihProfiliDogrula(JSON.parse(ham)) : null;
|
||||
} catch {
|
||||
return null;
|
||||
profilCache = null;
|
||||
}
|
||||
return profilCache;
|
||||
}
|
||||
|
||||
/** Ortak profili yazar; hero ve Yapay Zeka sihirbazıyla aynı anahtarı kullanır. */
|
||||
@@ -32,6 +50,7 @@ export function tercihProfiliYaz(profil: TercihProfili): void {
|
||||
try {
|
||||
localStorage.setItem(SIHIRBAZ_STORAGE_KEY, JSON.stringify(dogru));
|
||||
} catch {}
|
||||
profilCache = dogru;
|
||||
profilDegistiginiYayinla();
|
||||
}
|
||||
|
||||
@@ -41,6 +60,7 @@ export function tercihProfiliSil(): void {
|
||||
try {
|
||||
localStorage.removeItem(SIHIRBAZ_STORAGE_KEY);
|
||||
} catch {}
|
||||
profilCache = null;
|
||||
profilDegistiginiYayinla();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user