pr-monitor/server/index.ts
2026-07-29 09:38:17 +00:00

50 lines
1.5 KiB
TypeScript

import { loadConfig } from './config.js';
import { Db } from './db.js';
import { runPoll } from './poller.js';
import { getLastRateLimit } from './github/client.js';
import { createApp, buildSyncPayload } from './routes.js';
import { broadcast } from './sse.js';
const config = loadConfig();
const db = new Db({ muteRules: config.timeline.mute });
let polling = false;
async function poll(): Promise<void> {
if (polling) return;
polling = true;
try {
const result = await runPoll(config, db);
console.log(
`[poll] ${result.prCount} PRs, ${result.changedPrIds.length} changed, ${result.newEventCount} new events`,
);
broadcast(buildSyncPayload(db, result.changedPrIds, result.newEventCount));
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
console.error(`[poll] failed: ${message}`);
db.setMeta('last_sync_error', message);
broadcast(buildSyncPayload(db));
} finally {
polling = false;
}
}
function scheduleNext(): void {
// Back off to 5 minutes when the rate-limit budget runs low.
const remaining = getLastRateLimit()?.remaining;
const intervalMs =
remaining !== undefined && remaining < 500 ? 5 * 60_000 : config.pollIntervalSeconds * 1000;
setTimeout(async () => {
await poll();
scheduleNext();
}, intervalMs);
}
const app = createApp({ db, user: config.user, triggerSync: poll });
app.listen(config.port, config.host, () => {
console.log(`pr-monitor listening on http://${config.host}:${config.port}`);
});
await poll();
scheduleNext();