// scripts/mines-drain.mjs
//
// One-off fast drainer for the heartbeat queue. The standard worker loop runs
// one task per 30s tick (lib/heartbeat-worker.js), which is far too slow to
// clear a bulk Mines import (thousands of tasks). This runs N concurrent
// workers in a tight loop (no inter-task sleep) until the queue is empty.
//
// Each task is claimed under its own lease, so concurrent workers never
// double-process. Run with the in-proc daemon disabled (avoids two processes
// writing the same node:sqlite file):
//   MADARX_DISABLE_INPROC_DAEMON=1 node scripts/mines-drain.mjs [concurrency]
//
// Keep concurrency low: tabular loaders parse whole workbooks into memory, so
// several large spreadsheets in flight at once can exhaust the V8 heap. Default
// is 2; raise only for queues of small/cheap tasks.

import { loadProjectEnv } from '../lib/load-env.js';
loadProjectEnv();

const { runHeartbeatWorkerOnce } = await import('../lib/heartbeat-worker.js');
const { newId } = await import('../lib/db.js');

const CONCURRENCY = Number(process.argv[2]) || 2;
const EMPTY_STREAK_DONE = 4; // consecutive empty claims (per worker) → done

let processed = 0;
let failed = 0;
let lastLog = Date.now();

async function workerLoop(workerId) {
  let emptyStreak = 0;
  while (emptyStreak < EMPTY_STREAK_DONE) {
    const res = await runHeartbeatWorkerOnce({ workerId });
    if (!res.worked) { emptyStreak++; await new Promise(r => setTimeout(r, 250)); continue; }
    emptyStreak = 0;
    processed++;
    if (res.ok === false) failed++;
    if (Date.now() - lastLog > 5000) {
      lastLog = Date.now();
      console.log(`[drain] processed=${processed} failed=${failed}`);
    }
  }
}

const t0 = Date.now();
await Promise.all(Array.from({ length: CONCURRENCY }, () => workerLoop(newId('drain'))));
console.log(`[drain] DONE processed=${processed} failed=${failed} in ${((Date.now() - t0) / 1000).toFixed(1)}s`);
process.exit(0);
