← back to Wallco Ai

scripts/dw-stale-urls-head-check.js

58 lines

// HEAD-verify all swap candidates in parallel (concurrency=20)
// Persists head_check_status + head_checked_at to staging table.
const { Client } = require('pg');

const CONCURRENCY = 20;
const TIMEOUT_MS = 8000;

async function headCheck(url) {
  const ctrl = new AbortController();
  const t = setTimeout(() => ctrl.abort(), TIMEOUT_MS);
  try {
    let res = await fetch(url, { method: 'HEAD', signal: ctrl.signal, redirect: 'follow' });
    // Some CDNs reject HEAD with 405 — fall back to GET range
    if (res.status === 405 || res.status === 403) {
      const ctrl2 = new AbortController();
      const t2 = setTimeout(() => ctrl2.abort(), TIMEOUT_MS);
      try {
        res = await fetch(url, { method: 'GET', signal: ctrl2.signal, redirect: 'follow', headers: { Range: 'bytes=0-0' } });
      } finally { clearTimeout(t2); }
    }
    return res.status;
  } catch (e) {
    return 0; // network/timeout failure
  } finally {
    clearTimeout(t);
  }
}

async function worker(client, queue, progress) {
  while (queue.length > 0) {
    const row = queue.shift();
    if (!row) break;
    const status = await headCheck(row.new_url);
    await client.query(
      'UPDATE image_url_swap_proposals_2026_05_19 SET head_check_status=$1, head_checked_at=NOW() WHERE id=$2',
      [status, row.id]
    );
    progress.done++;
    if (status === 200) progress.ok++;
    if (progress.done % 25 === 0) console.log(`[${progress.done}/${progress.total}] ok=${progress.ok}`);
  }
}

(async () => {
  const client = new Client();
  await client.connect();
  const { rows } = await client.query(
    "SELECT id, new_url FROM image_url_swap_proposals_2026_05_19 WHERE new_url IS NOT NULL AND head_check_status IS NULL"
  );
  console.log(`To check: ${rows.length}`);
  const queue = [...rows];
  const progress = { done: 0, ok: 0, total: rows.length };
  const workers = Array.from({ length: CONCURRENCY }, () => worker(client, queue, progress));
  await Promise.all(workers);
  console.log(`DONE: ${progress.done} checked, ${progress.ok} returned 200`);
  await client.end();
})().catch(e => { console.error(e); process.exit(1); });