diff --git a/server/index.js b/server/index.js index 052114e..b49d38c 100644 --- a/server/index.js +++ b/server/index.js @@ -292,11 +292,14 @@ function ilanlariBirlestir(mevcut, yeniAds) { return eklenen; } -// Kalan sayfaları arka planda çeker; kullanıcı beklemez, havuz zamanla dolar. -async function arkaPlandaTamamla(numFound) { +// Kalan sayfaları arka planda çeker. Yeni liste ayrı kurulur ve TAMAMLANINCA +// atomik olarak devreye alınır; böylece yenileme sırasında kullanıcı hiçbir +// zaman eksik listeye düşmez (önceden her yenilemede 120 kayda iniyordu). +async function arkaPlandaTamamla(numFound, ilkListe) { if (arkaPlanDoluyor) return; arkaPlanDoluyor = true; try { + const yeni = [...ilkListe]; const gerekliSayfa = Math.min(MAX_PAGES, Math.ceil(numFound / LIST_SIZE)); let page = ILK_PARTI; while (page < gerekliSayfa) { @@ -304,15 +307,17 @@ async function arkaPlandaTamamla(numFound) { const sonuclar = await ilanSayfalari(page, grup); const ads = sonuclar.flatMap((r) => r.ads || []); if (!ads.length) break; - const eklenen = ilanlariBirlestir(cache.tenders, ads); - if (eklenen.length) cache.tenders = [...cache.tenders, ...eklenen]; + const eklenen = ilanlariBirlestir(yeni, ads); + if (eklenen.length) yeni.push(...eklenen); page += grup; - if (page % 60 === 0) { - console.log(`[ihaleist-api] arka plan: ${cache.tenders.length}/${numFound} ilan yüklendi`); - } await new Promise((r) => setTimeout(r, 120)); // kaynağı yormamak için } - console.log(`[ihaleist-api] havuz dolduruldu: ${cache.tenders.length}/${numFound} ilan`); + // Yalnızca daha zengin bir liste elde ettiysek devreye al + if (yeni.length >= cache.tenders.length) { + cache.tenders = yeni; + cache.todayCount = yeni.filter((t) => t.isYeni).length; + } + console.log(`[ihaleist-api] havuz hazır: ${cache.tenders.length}/${numFound} ilan`); } catch (e) { console.warn('[ihaleist-api] arka plan doldurma hatası:', e.message); } finally { @@ -324,24 +329,29 @@ async function getTenders(force = false) { const fresh = cache.tenders && Date.now() - cache.fetchedAt < CACHE_TTL_MS; if (fresh && !force) return cache; - // İlk parti: paralel, hızlı — kullanıcı bunu bekler const ilk = await ilanSayfalari(0, ILK_PARTI); const numFound = ilk.find((r) => r.numFound)?.numFound || 0; const ads = ilk.flatMap((r) => r.ads || []); const seen = new Set(); - cache.tenders = ads + const ilkListe = ads .filter((ad) => (seen.has(ad.id) ? false : seen.add(ad.id))) .map(mapAd); - cache.totalCount = numFound || cache.tenders.length; - cache.todayCount = cache.tenders.filter((t) => t.isYeni).length; - cache.fetchedAt = Date.now(); - console.log(`[ihaleist-api] ${cache.tenders.length} ihale yüklendi (havuz: ${cache.totalCount}) — kalanı arka planda`); - // Kalanı arka planda doldur (yanıtı bloklamaz) - if (cache.totalCount > cache.tenders.length) { - arkaPlandaTamamla(cache.totalCount); + cache.totalCount = numFound || ilkListe.length; + cache.fetchedAt = Date.now(); + + // İlk yükleme: elde hiçbir şey yoksa ilk partiyi hemen göster. + // Yenileme: eldeki dolu listeyi KORU, yenisi arka planda hazırlansın. + if (!cache.tenders || cache.tenders.length === 0) { + cache.tenders = ilkListe; + cache.todayCount = ilkListe.filter((t) => t.isYeni).length; + console.log(`[ihaleist-api] ilk yükleme: ${ilkListe.length} ilan (havuz ${cache.totalCount}) — kalanı arka planda`); + } else { + console.log(`[ihaleist-api] yenileme başladı (mevcut ${cache.tenders.length} ilan sunulmaya devam ediyor)`); } + + if (cache.totalCount > ilkListe.length) arkaPlandaTamamla(cache.totalCount, ilkListe); return cache; }