import { applyVersionCheck, listAutoCheckApplications } from '../models/applicationModel.js'; import { fetchLatestVersion } from './appVersionService.js'; import { logger } from './logger.js'; // Background upstream-version checker for catalog applications that opted in via // `autoCheck`. The runner is dependency-injected (fetcher) so it can be tested // without network access; the scheduler wires in the real fetchLatestVersion. export async function runCatalogChecks({ fetcher = fetchLatestVersion } = {}) { const apps = listAutoCheckApplications(); const summary = { checked: 0, updated: 0, errors: 0 }; for (const app of apps) { summary.checked += 1; try { const result = await fetcher(app); const next = result.version || ''; const changed = next && next !== app.latestKnownVersion; applyVersionCheck(app.id, { latestKnownVersion: next || app.latestKnownVersion, message: result.message || '' }); if (changed) summary.updated += 1; } catch (error) { summary.errors += 1; applyVersionCheck(app.id, { latestKnownVersion: app.latestKnownVersion, message: error.message }); } } return summary; } let timer = null; // Start the recurring worker. Disabled unless CATALOG_CHECK_INTERVAL_MINUTES > 0 // so installs never make surprise outbound calls. export function startCatalogWorker() { const minutes = Number(process.env.CATALOG_CHECK_INTERVAL_MINUTES || 0); if (!Number.isFinite(minutes) || minutes <= 0) return null; const intervalMs = minutes * 60 * 1000; timer = setInterval(() => { runCatalogChecks() .then((summary) => logger.info('catalog auto-check complete', summary)) .catch((error) => logger.error('catalog auto-check failed', { error: error.message })); }, intervalMs); timer.unref?.(); logger.info(`catalog auto-check scheduled every ${minutes} minute(s)`); return timer; } export function stopCatalogWorker() { if (timer) clearInterval(timer); timer = null; }