Files
claw-apply/lib/search_progress.mjs

62 lines
1.7 KiB
JavaScript

/**
* search_progress.mjs — Track which searches have completed
* Enables resume on restart without re-running finished searches
*/
import { readFileSync, writeFileSync, existsSync, unlinkSync } from 'fs';
let progressPath = null;
let progress = null;
export function initProgress(dataDir, lookbackDays) {
progressPath = `${dataDir}/search_progress.json`;
if (existsSync(progressPath)) {
const saved = JSON.parse(readFileSync(progressPath, 'utf8'));
// Only resume if same lookback window
if (saved.lookback_days === lookbackDays) {
progress = saved;
const done = progress.completed.length;
if (done > 0) {
console.log(`🔁 Resuming — skipping already-completed: ${progress.completed.join(', ')}\n`);
}
return progress;
}
console.log(`🆕 New lookback window (${lookbackDays}d), starting fresh\n`);
}
// Fresh start
progress = {
lookback_days: lookbackDays,
started_at: Date.now(),
completed: [],
pending: [],
};
save();
return progress;
}
export function isCompleted(platform, track) {
if (!progress) return false;
return progress.completed.includes(`${platform}:${track}`);
}
export function markComplete(platform, track, stats) {
if (!progress) return;
const key = `${platform}:${track}`;
progress.pending = progress.pending.filter(k => k !== key);
if (!progress.completed.includes(key)) progress.completed.push(key);
progress[`stats:${key}`] = { ...stats, completed_at: Date.now() };
save();
}
export function clearProgress() {
try { if (progressPath) unlinkSync(progressPath); } catch {}
progress = null;
}
function save() {
if (progressPath && progress) {
writeFileSync(progressPath, JSON.stringify(progress, null, 2));
}
}