Public Access
1
0
Files
leads4less/db/scripts/build-postal-neighbors.ts
T
pguerrerox dc7686f507 chore: improve postal data import observability
Add progress logging and a status script for postal imports and neighbor builds, and ignore local raw and generated postal datasets.
2026-04-12 23:22:36 +00:00

86 lines
2.9 KiB
TypeScript

import { getDbPool } from '../../server/src/db/pool.js';
import { createScriptLogger } from './postal-logging.js';
async function logPostalAreaCounts() {
const pool = getDbPool();
const result = await pool.query<{ country_code: string; area_count: string }>(`
select country_code, count(*)::text as area_count
from public.postal_areas
group by country_code
order by country_code asc
`);
return result.rows;
}
async function buildNeighborsForCountry(countryCode: 'US' | 'CA') {
const pool = getDbPool();
const logger = createScriptLogger(`postal-neighbors:${countryCode.toLowerCase()}`);
const sourceCountResult = await pool.query<{ area_count: string }>(
`select count(*)::text as area_count from public.postal_areas where country_code = $1`,
[countryCode],
);
const areaCount = sourceCountResult.rows[0]?.area_count ?? '0';
logger.info(`Starting neighbor build for ${countryCode} with ${areaCount} postal areas.`);
await pool.query(
`
insert into public.postal_area_neighbors (postal_area_id, neighbor_postal_area_id)
select source.id, neighbor.id
from public.postal_areas source
join public.postal_areas neighbor
on source.country_code = neighbor.country_code
and source.id <> neighbor.id
and ST_Touches(source.geom, neighbor.geom)
where source.country_code = $1
`,
[countryCode],
);
const neighborCountResult = await pool.query<{ neighbor_count: string }>(
`
select count(*)::text as neighbor_count
from public.postal_area_neighbors link
join public.postal_areas area on area.id = link.postal_area_id
where area.country_code = $1
`,
[countryCode],
);
logger.info(`Completed neighbor build for ${countryCode}. Built ${neighborCountResult.rows[0]?.neighbor_count ?? '0'} adjacency links.`);
}
async function run() {
const logger = createScriptLogger('postal-neighbors');
const pool = getDbPool();
const client = await pool.connect();
try {
logger.info('Gathering postal area counts before neighbor build.');
const counts = await logPostalAreaCounts();
counts.forEach((row) => logger.info(`Found ${row.area_count} postal areas for ${row.country_code}.`));
await client.query('begin');
logger.info('Clearing existing postal adjacency links.');
await client.query('truncate table public.postal_area_neighbors');
await client.query('commit');
await buildNeighborsForCountry('US');
await buildNeighborsForCountry('CA');
const summary = await pool.query<{ count: string }>('select count(*)::text as count from public.postal_area_neighbors');
logger.info(`Finished building postal neighbors. Total adjacency links: ${summary.rows[0]?.count ?? '0'}.`);
} catch (error) {
await client.query('rollback');
logger.error('Neighbor build failed.');
throw error;
} finally {
client.release();
await pool.end();
}
}
await run();