← back to Nationalrealestate
src/jobs/refresh_all.ts
38 lines
/**
* Monthly refresh orchestrator (launchd com.steve.usre-refresh):
* zillow -> redfin -> fhfa -> acs -> derive -> score -> alerts.
* Every job is an idempotent upsert, so re-running any month is safe; jobs run
* as child processes because each script owns its pool lifecycle (pool.end()).
* A failed job logs + continues (per-source failure shows red in ingest_runs;
* one dead source must not starve the others).
*/
import { execFileSync } from 'node:child_process';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const ROOT = join(__dirname, '..', '..');
const JOBS: Array<[string, string]> = [
['zillow', 'src/ingest/zillow_research.ts'],
['redfin', 'src/ingest/redfin_tracker.ts'],
['fhfa', 'src/ingest/fhfa_hpi.ts'],
['acs', 'src/ingest/census_acs.ts'],
['derive', 'src/ingest/derive_metrics.ts'],
['score', 'src/score/opportunity.ts'],
['alerts', 'src/jobs/alerts_check.ts'],
];
let failed = 0;
for (const [name, script] of JOBS) {
console.log(`\n[refresh] ── ${name} ──`);
try {
execFileSync('npx', ['tsx', script], { cwd: ROOT, stdio: 'inherit', timeout: 45 * 60_000 });
} catch (e: any) {
failed++;
console.error(`[refresh] ${name} FAILED: ${e.message}`);
}
}
console.log(`\n[refresh] complete, ${failed} job(s) failed`);
process.exit(failed > 0 ? 1 : 0);