feat(osm): Phase 6 — proximity materialized views + refresh cron
* `mv_park_nearest_poi` — for each IndustrialPark, the 3 nearest POI of six priority categories (HOSPITAL/BANK/GAS/BUS/METRO/POLICE) within 5km. Refreshed weekly. Pre-aggregated 6,513 rows from the live catalog so the KCN sidebar can render in <50ms instead of running ST_Distance for every page hit. * `mv_poi_density_by_province` — count of POI per (province, category) for analytics heatmaps. * `OsmSyncService.refreshMaterializedViews()` calls `REFRESH MATERIALIZED VIEW CONCURRENTLY` so reads aren't blocked. * New cron entry `weeklyRefreshViews` (Sun 04:00 ICT) and admin endpoint `POST /admin/osm/refresh-views` for on-demand refresh. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -78,6 +78,22 @@ export class OsmSyncService {
|
||||
private readonly logger: LoggerService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Refresh the proximity / density materialized views. Called by the
|
||||
* cron and from the admin "Refresh views" button. Runs concurrently
|
||||
* (`CONCURRENTLY`) so reads aren't blocked.
|
||||
*/
|
||||
async refreshMaterializedViews(): Promise<void> {
|
||||
this.logger.log('Refreshing materialized views', 'OsmSyncService');
|
||||
await this.prisma.$executeRawUnsafe(
|
||||
`REFRESH MATERIALIZED VIEW CONCURRENTLY "mv_park_nearest_poi"`,
|
||||
);
|
||||
await this.prisma.$executeRawUnsafe(
|
||||
`REFRESH MATERIALIZED VIEW "mv_poi_density_by_province"`,
|
||||
);
|
||||
this.logger.log('Materialized views refreshed', 'OsmSyncService');
|
||||
}
|
||||
|
||||
/** Look up a sync layer by its (layer, category) tuple. */
|
||||
findLayer(layer: string, category?: string | null): OsmSyncLayerDef | undefined {
|
||||
return SYNC_LAYERS.find(
|
||||
|
||||
Reference in New Issue
Block a user