Analytics: Heatmap-Endpunkt nachgeschaerft

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-01 09:59:48 +00:00
1 parent 28c7a90d8b
commit add7fa4add
4 files changed
+97 -13

No files matched your search

+13 -6
View File
@@ -103,17 +103,24 @@ export function nextRunAt(now, hour = 2, minute = 30) {
}
// Plant runNightly täglich 02:30 Berlin und einmal kurz nach dem Start; stop() beendet alle Timer.
export function scheduleNightly(db, { startDelayMs = 60000, log = console } = {}) {
// Test-Hooks: now, timers ({ setTimeout, clearTimeout }) und job (statt runNightly).
export function scheduleNightly(db, { startDelayMs = 60000, log = console, now = Date.now, timers = { setTimeout, clearTimeout }, job = runNightly } = {}) {
let timer = null;
let stopped = false;
const run = () => {
try {
const r = runNightly(db, { now: Date.now() });
const r = job(db, { now: now() });
log.log(`Analytics-Nachtjob: ${r.aggregated} Tage verdichtet, ${r.sitesDeleted} Websites gelöscht`);
} catch (e) { log.error('Analytics-Nachtjob:', e.message); }
};
const arm = (delay, fn) => { if (!stopped) timer = setTimeout(fn, delay); };
const daily = () => { run(); arm(nextRunAt(Date.now()) - Date.now(), daily); };
arm(startDelayMs, () => { run(); arm(nextRunAt(Date.now()) - Date.now(), daily); });
return { stop: () => { stopped = true; clearTimeout(timer); } };
const arm = (delay, fn) => { if (!stopped) timer = timers.setTimeout(fn, delay); };
// Ein Timer kann früh feuern (Uhrsprung, Timer-Ungenauigkeit): dann nur neu auf den Zielzeitpunkt setzen,
// nie vorzeitig laufen. Nach dem Lauf strikt hinter das Ziel planen, damit 02:30 nie doppelt läuft.
const planDaily = (target) => arm(Math.max(0, target - now()), () => {
if (now() < target) return planDaily(target);
run();
planDaily(nextRunAt(Math.max(now(), target) + 1000));
});
arm(startDelayMs, () => { run(); planDaily(nextRunAt(now())); });
return { stop: () => { stopped = true; timers.clearTimeout(timer); } };
}