/** * Background poller for GitHub ↔ MC task sync. * Lazy singleton — call startSyncPoller() to begin. */ import { getDatabase } from '@/lib/db' import { logger } from '@/lib/logger' import { pullFromGitHub } from '@/lib/github-sync-engine' const INTERVAL_MS = parseInt(process.env.GITHUB_SYNC_INTERVAL_MS || '60000', 10) let intervalHandle: ReturnType | null = null let lastRun: number | undefined export function startSyncPoller(): void { if (intervalHandle) return logger.info({ intervalMs: INTERVAL_MS }, 'Starting GitHub sync poller') intervalHandle = setInterval(async () => { await runSyncTick() }, INTERVAL_MS) // Run immediately on start runSyncTick().catch(() => {}) } export function stopSyncPoller(): void { if (intervalHandle) { clearInterval(intervalHandle) intervalHandle = null logger.info('GitHub sync poller stopped') } } export function getSyncPollerStatus(): { running: boolean; interval: number; lastRun?: number } { return { running: intervalHandle !== null, interval: INTERVAL_MS, lastRun, } } async function runSyncTick(): Promise { try { const db = getDatabase() const projects = db.prepare(` SELECT id, github_repo, github_sync_enabled, github_default_branch, workspace_id FROM projects WHERE github_sync_enabled = 1 AND github_repo IS NOT NULL AND status = 'active' `).all() as Array<{ id: number github_repo: string github_sync_enabled: number github_default_branch: string | null workspace_id: number }> for (const project of projects) { try { await pullFromGitHub(project, project.workspace_id) } catch (err) { logger.error({ err, projectId: project.id, repo: project.github_repo }, 'Sync poller: project sync failed') } } lastRun = Math.floor(Date.now() / 1000) } catch (err) { logger.error({ err }, 'Sync poller tick failed') } }