feat: geçmiş arşiv dolumu + arşiv sayacı
- scheduler: arşiv eşiğin altındaysa geniş geçmiş dolumu (180 gün/1500 kayıt), doluysa artımlı günlük tarama; ilk tur 90 sn sonra - LiveStatsBar: 'Sonuç Arşivi' sayacı (kazanan firma kayıt sayısı) - KİK: HTML entity çözümü tamamlandı
This commit is contained in:
+24
-5
@@ -12,20 +12,39 @@
|
|||||||
import { spawn } from 'node:child_process';
|
import { spawn } from 'node:child_process';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
|
import { historyStats } from './history-store.mjs';
|
||||||
|
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
||||||
let calisiyor = false;
|
let calisiyor = false;
|
||||||
|
|
||||||
|
// Arşiv boş/küçükse geniş geçmiş dolumu, doluysa artımlı günlük tarama.
|
||||||
|
function tarataParams() {
|
||||||
|
const s = historyStats();
|
||||||
|
const mevcut = s.available ? (s.toplam || 0) : 0;
|
||||||
|
const esik = Number(process.env.SCAN_BACKFILL_ESIK || 2000);
|
||||||
|
if (mevcut < esik) {
|
||||||
|
return {
|
||||||
|
gun: process.env.SCAN_BACKFILL_GUN || '180',
|
||||||
|
limit: process.env.SCAN_BACKFILL_LIMIT || '1500',
|
||||||
|
tip: `geçmiş dolumu (arşivde ${mevcut} kayıt)`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
gun: process.env.SCAN_GUN || '3',
|
||||||
|
limit: process.env.SCAN_LIMIT || '300',
|
||||||
|
tip: `artımlı güncelleme (arşivde ${mevcut} kayıt)`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function tara() {
|
function tara() {
|
||||||
if (calisiyor) {
|
if (calisiyor) {
|
||||||
console.log('[scheduler] önceki tarama sürüyor, bu tur atlandı');
|
console.log('[scheduler] önceki tarama sürüyor, bu tur atlandı');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
calisiyor = true;
|
calisiyor = true;
|
||||||
const gun = process.env.SCAN_GUN || '3';
|
const { gun, limit, tip } = tarataParams();
|
||||||
const limit = process.env.SCAN_LIMIT || '300';
|
console.log(`[scheduler] EKAP sonuç taraması — ${tip}: son ${gun} gün, limit ${limit}`);
|
||||||
console.log(`[scheduler] EKAP sonuç taraması başlıyor (son ${gun} gün, limit ${limit})`);
|
|
||||||
|
|
||||||
const p = spawn(process.execPath, [path.join(__dirname, 'ekap-scan.mjs'), '--gun', gun, '--limit', limit], {
|
const p = spawn(process.execPath, [path.join(__dirname, 'ekap-scan.mjs'), '--gun', gun, '--limit', limit], {
|
||||||
stdio: ['ignore', 'pipe', 'pipe'],
|
stdio: ['ignore', 'pipe', 'pipe'],
|
||||||
@@ -50,7 +69,7 @@ export function startScheduler() {
|
|||||||
const saat = Number(process.env.SCAN_INTERVAL_SAAT || 6);
|
const saat = Number(process.env.SCAN_INTERVAL_SAAT || 6);
|
||||||
const ms = Math.max(1, saat) * 3600 * 1000;
|
const ms = Math.max(1, saat) * 3600 * 1000;
|
||||||
console.log(`[scheduler] geçmiş sonuç taraması her ${saat} saatte bir çalışacak`);
|
console.log(`[scheduler] geçmiş sonuç taraması her ${saat} saatte bir çalışacak`);
|
||||||
// Açılıştan 2 dk sonra ilk tur (sunucu ısınsın), sonra periyodik
|
// Açılıştan 90 sn sonra ilk tur (sunucu ısınsın), sonra periyodik
|
||||||
setTimeout(tara, 2 * 60 * 1000).unref?.();
|
setTimeout(tara, 90 * 1000).unref?.();
|
||||||
setInterval(tara, ms).unref?.();
|
setInterval(tara, ms).unref?.();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useApp } from '../context/AppContext';
|
import { useApp } from '../context/AppContext';
|
||||||
import { Database, PlusCircle, Eye, Layers } from 'lucide-react';
|
import { Database, PlusCircle, Eye, Layers, Trophy } from 'lucide-react';
|
||||||
|
|
||||||
export const LiveStatsBar = () => {
|
export const LiveStatsBar = () => {
|
||||||
const { liveStats, tenders } = useApp();
|
const { liveStats, tenders } = useApp();
|
||||||
@@ -14,6 +14,7 @@ export const LiveStatsBar = () => {
|
|||||||
{ deger: yukluIhale, etiket: 'Yüklü İhale', renk: 'text-white', icon: Database, iconRenk: 'text-blue-400' },
|
{ deger: yukluIhale, etiket: 'Yüklü İhale', renk: 'text-white', icon: Database, iconRenk: 'text-blue-400' },
|
||||||
{ deger: liveStats.bugunEklenen, etiket: 'Bugün Eklenen', renk: 'text-emerald-400', icon: PlusCircle, iconRenk: 'text-emerald-400' },
|
{ deger: liveStats.bugunEklenen, etiket: 'Bugün Eklenen', renk: 'text-emerald-400', icon: PlusCircle, iconRenk: 'text-emerald-400' },
|
||||||
{ deger: kalemSayisi, etiket: 'Kalem', renk: 'text-white', icon: Layers, iconRenk: 'text-indigo-400' },
|
{ deger: kalemSayisi, etiket: 'Kalem', renk: 'text-white', icon: Layers, iconRenk: 'text-indigo-400' },
|
||||||
|
{ deger: liveStats.arsiv, etiket: 'Sonuç Arşivi', renk: 'text-white', icon: Trophy, iconRenk: 'text-emerald-400' },
|
||||||
{ deger: takibimdeki, etiket: 'Takibimdeki', renk: 'text-white', icon: Eye, iconRenk: 'text-amber-400' },
|
{ deger: takibimdeki, etiket: 'Takibimdeki', renk: 'text-white', icon: Eye, iconRenk: 'text-amber-400' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export const AppProvider = ({ children }) => {
|
|||||||
return saved ? JSON.parse(saved) : [];
|
return saved ? JSON.parse(saved) : [];
|
||||||
});
|
});
|
||||||
|
|
||||||
const [liveStats, setLiveStats] = useState({ toplamIhale: 0, bugunEklenen: 0 });
|
const [liveStats, setLiveStats] = useState({ toplamIhale: 0, bugunEklenen: 0, arsiv: 0 });
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
const [searchQuery, setSearchQuery] = useState('');
|
||||||
const [selectedCity, setSelectedCity] = useState('');
|
const [selectedCity, setSelectedCity] = useState('');
|
||||||
const [selectedAlimTuru, setSelectedAlimTuru] = useState('');
|
const [selectedAlimTuru, setSelectedAlimTuru] = useState('');
|
||||||
@@ -60,6 +60,7 @@ export const AppProvider = ({ children }) => {
|
|||||||
setLiveStats({
|
setLiveStats({
|
||||||
toplamIhale: data.totalCount ?? 0,
|
toplamIhale: data.totalCount ?? 0,
|
||||||
bugunEklenen: data.todayCount ?? 0,
|
bugunEklenen: data.todayCount ?? 0,
|
||||||
|
arsiv: data.historyCount ?? 0,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setLiveDataError(err.message);
|
setLiveDataError(err.message);
|
||||||
|
|||||||
Reference in New Issue
Block a user