Files
MaashkinoozheandClaude Opus 5.5 b2bb34174c Fold the sentinel into the scraper and drop the sentinel service (BL-0046)
The stall watchdog now runs inside the scraper (ScraperService.checkStalls,
every 30 s from the work loop): same rule as before, one checkpoint-safe
restart, quarantine on the second stall, missing checkpoint is no evidence,
and paused time no longer counts. Stalls are recorded as scraper incidents
(failure.kind 'stall'). The private /api/recovery endpoint is gone.

Dropped with the service: reader/scraper-unreachable incidents (supervisor
and Docker handle crashes; the health page shows "Scraper: unreachable"),
duplicate job-failure incidents and the unused /metrics endpoint.
The stack is now reader + scraper (+ optional peer-gateway).
The supervisor test moved to runtime/test (npm run test:runtime stays).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 22:58:03 +02:00

24 lines
1.1 KiB
JavaScript

#!/usr/bin/env node
'use strict';
const fs = require('fs'), path = require('path');
const { Supervisor } = require('../runtime/supervisor');
const root = path.resolve(__dirname, '..');
const lock = path.resolve(process.env.SCRAPER_DATA || path.join(process.env.DATA || path.join(root, 'data'), 'scraper'), 'supervisor.lock');
fs.mkdirSync(path.dirname(lock), { recursive: true });
if (fs.existsSync(lock)) {
const pid = Number(fs.readFileSync(lock, 'utf8'));
try { process.kill(pid, 0); throw new Error(`Supervisor already alive (PID ${pid})`); }
catch (e) { if (e.code !== 'ESRCH') throw e; fs.unlinkSync(lock); }
}
fs.writeFileSync(lock, String(process.pid), { flag: 'wx' });
const supervisors = ['reader', 'scraper'].map(name => new Supervisor(name, { root }));
supervisors.forEach(service => service.start());
const keepalive = setInterval(() => {}, 60000);
let closing = false;
for (const signal of ['SIGINT', 'SIGTERM']) process.on(signal, async () => {
if (closing) return; closing = true; clearInterval(keepalive);
await Promise.all(supervisors.map(service => service.close()));
fs.unlinkSync(lock); process.exit(0);
});