feat(devices): hourly scan-cycle orchestration + cron

This commit is contained in:
root
2026-06-08 20:58:52 +10:00
parent 2ca2adc485
commit e9c1fb17ac
3 changed files with 58 additions and 0 deletions

View File

@@ -5,6 +5,7 @@ import { enqueue } from '../jobs/queue.js';
import { checkAll } from '../health/checker.js';
import * as statusRepo from '../db/repos/service_status.js';
import * as services from '../db/repos/monitored_services.js';
import { runDeviceScanCycle } from '../infra/scan_cycle.js';
export function startCron() {
// Daily at 03:00 local time
@@ -35,5 +36,11 @@ export function startCron() {
} catch (e) { log.error({ err: e }, 'health check failed'); }
});
// Hourly LAN device scan (staggered off the :00 speedtest)
cron.schedule('7 * * * *', async () => {
try { await runDeviceScanCycle(); }
catch (e) { log.error({ err: e }, 'device scan cycle failed'); }
});
log.info('cron started');
}

19
lib/infra/scan_cycle.js Normal file
View File

@@ -0,0 +1,19 @@
// One discovery cycle: scan → upsert → mark-absent → prune. Deps injected for
// tests. Prune only runs after a successful, non-empty scan, so a failed scan
// can never reap rows.
import { runScan } from './scan.js';
import * as devices from '../db/repos/lan_devices.js';
import { log } from '../log.js';
export async function runDeviceScanCycle({ scan = runScan, repo = devices } = {}) {
const rows = await scan();
if (!rows.length) {
log.warn('device scan returned no hosts; skipping upsert/prune');
return { seen: 0 };
}
await repo.upsertScan(rows);
await repo.markAbsent(rows.map(r => r.mac));
const pruned = await repo.prune();
log.info({ seen: rows.length, pruned }, 'device scan cycle complete');
return { seen: rows.length, pruned };
}