Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 13 additions & 22 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@
"path": "^0.12.7",
"pg": "^8.11.5",
"pmtiles": "3.0.3",
"sharp": "^0.33.2",
"xmldom": "^0.6.0"
"sharp": "^0.33.2"
},
"devDependencies": {
"@babel/core": "^7.23.9",
Expand Down
31 changes: 23 additions & 8 deletions src/azure_queue_service.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { QueueServiceClient } from "@azure/storage-queue";
import { Client } from "pg";
import pg from "pg";

import {
parseListToFloat,
Expand All @@ -10,7 +10,8 @@ import { initiateRendering } from "./initiate.js";

// Make db connection
const connectionString = process.env["CONNECTION_STRING"];
const client = new Client({

const client = new pg.Client({
connectionString: connectionString,
});
client.connect();
Expand Down Expand Up @@ -58,6 +59,7 @@ const processQueueMessages = async () => {
outputDir,
outputFilename;
let boundsArray = [];
let requestId;

// Decode, parse, and validate the message
try {
Expand All @@ -84,6 +86,8 @@ const processQueueMessages = async () => {
outputFilename = "output",
} = options);

requestId = options.requestId;

boundsArray = parseListToFloat(bounds);

validateInputOptions(
Expand All @@ -101,7 +105,7 @@ const processQueueMessages = async () => {
);
} catch (error) {
renderResult = handleError(error, "badRequest");
await writeRenderResult(renderResult, message);
await writeRenderResult(renderResult, message, requestId);
continue;
}

Expand All @@ -127,13 +131,19 @@ const processQueueMessages = async () => {
} catch (error) {
renderResult = handleError(error, "internalServerError");
} finally {
await writeRenderResult(renderResult, message);
await writeRenderResult(renderResult, message, requestId);
}
}
};

const writeRenderResult = async (renderResult, message) => {
function camelToSnakeCase(str) {
return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
}

const writeRenderResult = async (renderResult, message, requestId) => {
if (renderResult) {
console.log(`Writing render result to database..`);

let updateDbRenderRequest = `UPDATE ${db_table} SET `;
let params = [];
let count = 1;
Expand All @@ -143,8 +153,9 @@ const writeRenderResult = async (renderResult, message) => {
// add a clause to the SQL query to update the corresponding column
// and add the property value to the parameters array
if (renderResult[key] !== null && renderResult[key] !== undefined) {
// All keys converted to lowercase match the db column names
updateDbRenderRequest += `${key.toLowerCase()} = $${count}, `;
// Convert camelCase to snake_case for db column names
let snakeCaseKey = camelToSnakeCase(key);
updateDbRenderRequest += `${snakeCaseKey} = $${count}, `;
params.push(renderResult[key]);
count++;
}
Expand All @@ -153,9 +164,13 @@ const writeRenderResult = async (renderResult, message) => {
// Remove space and comma from last column
updateDbRenderRequest = updateDbRenderRequest.slice(0, -2);
updateDbRenderRequest += ` WHERE id = $${count}`;
params.push(message.requestId);
params.push(requestId);

await client.query(updateDbRenderRequest, params);

console.log(
`Render result has successfully been successfully to database!`,
);
}
// Delete message from queue
await sourceQueueClient.deleteMessage(message.messageId, message.popReceipt);
Expand Down
49 changes: 26 additions & 23 deletions src/download_resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import path from "path";
import axios from "axios";
import pLimit from "p-limit";
import osmtogeojson from "osmtogeojson";
import xmldom from "xmldom";

import {
convertCoordinatesToTiles,
Expand Down Expand Up @@ -331,30 +330,34 @@ export const requestOpenStreetMapData = async (bounds, tempDir) => {
console.log(`OpenStreetMap data already exists: ${osmFile}`);
}

console.log(`OpenStreetMap data downloaded!`);
console.log(`OpenStreetMap data downloaded! Converting to GeoJSON...`);

// Convert OSM XML data to OSM JSON using xmldom
// In the future, we might want to use a more robust OSM parser like
// https://github.com/tyrasd/osmtogeojson/blob/gh-pages/parse_osmxml.js
const parser = new xmldom.DOMParser();
const osmData = parser.parseFromString(
fs.readFileSync(`${outputDir}/data.osm`, "utf-8"),
);

// Convert OSM JSON to GeoJSON
const geojson = osmtogeojson(osmData);

// Filter out lines and points only
geojson.features = geojson.features.filter(
(feature) =>
feature.geometry.type === "LineString" ||
feature.geometry.type === "Point",
);
try {
// Convert OSM XML data to OSM JSON using parse_osmxml
const parse_osmxml = (await import("osmtogeojson/parse_osmxml.js")).default;
const osmData = fs.readFileSync(`${outputDir}/data.osm`, "utf-8");

// Use the parser's method to parse the XML string
parse_osmxml.parseFromString(osmData);
const osmJson = parse_osmxml.getJSON();

// Convert OSM JSON to GeoJSON
const geojson = osmtogeojson(osmJson);

// Filter out lines and points only
geojson.features = geojson.features.filter(
(feature) =>
feature.geometry.type === "LineString" ||
feature.geometry.type === "Point",
);

fs.writeFileSync(
`${outputDir}/openstreetmap.geojson`,
JSON.stringify(geojson, null, 4),
);
fs.writeFileSync(
`${outputDir}/openstreetmap.geojson`,
JSON.stringify(geojson, null, 4),
);
} catch (error) {
throw new Error(`Error converting OpenStreetMap data to GeoJSON: ${error}`);
}
console.log(
`\x1b[32mOpenStreetMap data successfully downloaded and converted to GeoJSON!\x1b[0m`,
);
Expand Down
8 changes: 5 additions & 3 deletions src/generate_resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ export const generateMBTiles = async (
outputDir,
outputFilename,
) => {
const tempPath = `${tempDir}/${outputFilename}.mbtiles`;
const outputMBTiles = `${outputFilename}.mbtiles`;
const tempPath = `${tempDir}/${outputMBTiles}`;
console.log(`Generating MBTiles file...`);

let numberOfTiles = 0;
Expand Down Expand Up @@ -211,7 +212,7 @@ export const generateMBTiles = async (
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
const outputPath = `${outputDir}/${outputFilename}.mbtiles`;
const outputPath = `${outputDir}/${outputMBTiles}`;

try {
const readStream = fs.createReadStream(tempPath);
Expand Down Expand Up @@ -240,7 +241,8 @@ export const generateMBTiles = async (
// Return with success status
return {
errorMessage: null,
fileLocation: outputPath,
fileLocation: outputDir,
filename: outputMBTiles,
fileSize: fileSize,
numberOfTiles,
};
Expand Down
1 change: 1 addition & 0 deletions src/initiate.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ export const initiateRendering = async (
status: "SUCCEEDED",
errorMessage: generateResult.errorMessage,
fileLocation: generateResult.fileLocation,
filename: generateResult.filename,
fileSize: generateResult.fileSize,
numberOfTiles: generateResult.numberOfTiles,
workBegun,
Expand Down