const { parentPort, workerData } = require('node:worker_threads'); const Database = require('better-sqlite3'); try { const db = new Database(workerData.databasePath, { readonly: true, fileMustExist: true }); const counts = db.prepare(` SELECT COALESCE((SELECT seq FROM sqlite_sequence WHERE name='articles'), 0) AS total, (SELECT COUNT(*) FROM article_embedding_meta) AS withContent, (SELECT COUNT(*) FROM article_embedding_meta) AS withEmbedding, COALESCE((SELECT seq FROM sqlite_sequence WHERE name='events'), 0) AS eventCount, (SELECT COUNT(*) FROM articles WHERE ingested_at >= datetime('now', '-1 hour')) AS ingestedPerHour, (SELECT COUNT(*) FROM article_embedding_meta WHERE embedded_at >= datetime('now', '-1 hour')) AS contentPerHour `).get(); const bySource = db.prepare(` SELECT DISTINCT source FROM articles ORDER BY source `).all(); // Avoid scanning the 3.7 GB article table for legacy content-status values. // Readiness is the useful operational distinction and is available from the // compact embedding metadata table. const byStatus = [ { status: 'ready', n: counts.withEmbedding }, { status: 'unprocessed', n: Math.max(0, counts.total - counts.withEmbedding) }, ]; let embeddingsPerHour = 0; try { embeddingsPerHour = db.prepare(` SELECT COUNT(*) AS n FROM article_embedding_meta WHERE embedded_at >= datetime('now', '-1 hour') `).get().n; } catch (_) {} db.close(); parentPort.postMessage({ value: { ...counts, bySource, byStatus, embeddingsPerHour } }); } catch (error) { parentPort.postMessage({ error: error.message }); }