UNPKG

carthorse

Version:

A geospatial trail data processing pipeline for building 3D trail databases with elevation data

88 lines 4.88 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.RouteCacheService = void 0; const crypto_1 = __importDefault(require("crypto")); class RouteCacheService { constructor(pgClient, cacheSchema) { this.pg = pgClient; this.cacheSchema = cacheSchema; } async ensureSchemaAndTables() { // Create schema and tables with indexes if not exist await this.pg.query(`CREATE SCHEMA IF NOT EXISTS ${this.cacheSchema}`); await this.pg.query(` CREATE TABLE IF NOT EXISTS ${this.cacheSchema}.ksp_paths_cache ( graph_sig TEXT NOT NULL, start_node INTEGER NOT NULL, end_node INTEGER NOT NULL, k INTEGER NOT NULL, constraints_sig TEXT NOT NULL, paths JSONB NOT NULL, created_at TIMESTAMP DEFAULT NOW(), PRIMARY KEY(graph_sig, start_node, end_node, k, constraints_sig) ) `); await this.pg.query(`CREATE INDEX IF NOT EXISTS idx_${this.cacheSchema}_ksp_paths_start ON ${this.cacheSchema}.ksp_paths_cache(start_node)`); await this.pg.query(`CREATE INDEX IF NOT EXISTS idx_${this.cacheSchema}_ksp_paths_end ON ${this.cacheSchema}.ksp_paths_cache(end_node)`); await this.pg.query(`CREATE INDEX IF NOT EXISTS idx_${this.cacheSchema}_ksp_paths_graph ON ${this.cacheSchema}.ksp_paths_cache(graph_sig)`); await this.pg.query(` CREATE TABLE IF NOT EXISTS ${this.cacheSchema}.reachable_nodes_cache ( graph_sig TEXT NOT NULL, start_node INTEGER NOT NULL, max_distance_km REAL NOT NULL, results JSONB NOT NULL, created_at TIMESTAMP DEFAULT NOW(), PRIMARY KEY(graph_sig, start_node, max_distance_km) ) `); await this.pg.query(`CREATE INDEX IF NOT EXISTS idx_${this.cacheSchema}_reachable_start ON ${this.cacheSchema}.reachable_nodes_cache(start_node)`); await this.pg.query(`CREATE INDEX IF NOT EXISTS idx_${this.cacheSchema}_reachable_graph ON ${this.cacheSchema}.reachable_nodes_cache(graph_sig)`); } async computeGraphSignature(stagingSchema, region, bbox) { // Use edge count, vertex count, sum(length_km) as a compact signature of the routing graph const stats = await this.pg.query(` WITH e AS ( SELECT COUNT(*)::bigint AS edges, COALESCE(SUM(length_km), 0)::double precision AS total_len FROM ${stagingSchema}.ways_noded ), v AS ( SELECT COUNT(*)::bigint AS vertices FROM ${stagingSchema}.ways_noded_vertices_pgr ) SELECT e.edges, v.vertices, e.total_len FROM e, v `); const row = stats.rows[0] || { edges: 0, vertices: 0, total_len: 0 }; const bboxPart = bbox ? bbox.join(',') : 'nobbox'; const raw = `${region}|${bboxPart}|${row.edges}|${row.vertices}|${row.total_len}`; return crypto_1.default.createHash('md5').update(raw).digest('hex'); } async getKspPaths(graphSig, startNode, endNode, k, constraintsSig) { const res = await this.pg.query(`SELECT paths FROM ${this.cacheSchema}.ksp_paths_cache WHERE graph_sig = $1 AND start_node = $2 AND end_node = $3 AND k = $4 AND constraints_sig = $5`, [graphSig, startNode, endNode, k, constraintsSig]); if (res.rows.length === 0) return null; return { paths: res.rows[0].paths }; } async setKspPaths(graphSig, startNode, endNode, k, constraintsSig, paths) { await this.pg.query(`INSERT INTO ${this.cacheSchema}.ksp_paths_cache (graph_sig, start_node, end_node, k, constraints_sig, paths) VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT (graph_sig, start_node, end_node, k, constraints_sig) DO UPDATE SET paths = EXCLUDED.paths, created_at = NOW()`, [graphSig, startNode, endNode, k, constraintsSig, JSON.stringify(paths)]); } async getReachableNodes(graphSig, startNode, maxDistanceKm) { const res = await this.pg.query(`SELECT results FROM ${this.cacheSchema}.reachable_nodes_cache WHERE graph_sig = $1 AND start_node = $2 AND max_distance_km = $3`, [graphSig, startNode, maxDistanceKm]); if (res.rows.length === 0) return null; return { results: res.rows[0].results }; } async setReachableNodes(graphSig, startNode, maxDistanceKm, results) { await this.pg.query(`INSERT INTO ${this.cacheSchema}.reachable_nodes_cache (graph_sig, start_node, max_distance_km, results) VALUES ($1, $2, $3, $4) ON CONFLICT (graph_sig, start_node, max_distance_km) DO UPDATE SET results = EXCLUDED.results, created_at = NOW()`, [graphSig, startNode, maxDistanceKm, JSON.stringify(results)]); } } exports.RouteCacheService = RouteCacheService; //# sourceMappingURL=route-cache.js.map