import { getCatalog, catalogFailure } from "./source.js"; import { syncIndex } from "./directory.js"; import { checkCatalog, checkSource } from "./alerts.js"; // The server checks the university's catalog by itself, not only when a request asks: a // republished document is parsed within minutes, the clients' next refresh gets it, and the // owner hears about problems (see alerts.js). An unchanged catalog costs two listings. const INTERVAL = Number(process.env.PSU_WATCH_INTERVAL_MS) || 5 * 60 * 1000; /** For /api/health. */ export const watchStatus = { intervalMinutes: INTERVAL / 60000, lastAt: null, lastError: null }; let running = null; /** One check: the catalog (refreshed), the index of a changed catalog, the messages. */ export function watchOnce() { // A slow university must not stack checks on top of each other. running ||= check().finally(() => { running = null; }); return running; } async function check() { try { const catalog = await getCatalog(true); // A failed crawl answers with the saved catalog: nothing new to read or report then. if (!catalog.stale) await checkCatalog(await syncIndex(catalog), catalog); watchStatus.lastError = catalog.stale ? catalog.error || null : null; } catch (error) { watchStatus.lastError = error.message; } await checkSource(catalogFailure()); watchStatus.lastAt = new Date().toISOString(); } let timer = null; /** Checks every few minutes (PSU_WATCH_INTERVAL_MS) for as long as the process runs. */ export function startWatch() { if (timer) return; timer = setInterval(watchOnce, INTERVAL); timer.unref(); }