44 lines
1.6 KiB
JavaScript
44 lines
1.6 KiB
JavaScript
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();
|
|
}
|