fix: avoid synchronous calls where possible
Signed-off-by: Aarni Koskela <akx@iki.fi>
This commit is contained in:
parent
f64f95f80b
commit
c89bd385e7
6 changed files with 46 additions and 28 deletions
18
src/main.js
18
src/main.js
|
@ -3,6 +3,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
|
import fsp from 'node:fs/promises';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
@ -23,6 +24,7 @@ if (args.length >= 3 && args[2][0] !== '-') {
|
||||||
}
|
}
|
||||||
|
|
||||||
import { program } from 'commander';
|
import { program } from 'commander';
|
||||||
|
import { existsP } from './promises.js';
|
||||||
program
|
program
|
||||||
.description('tileserver-gl startup options')
|
.description('tileserver-gl startup options')
|
||||||
.usage('tileserver-gl [mbtiles] [options]')
|
.usage('tileserver-gl [mbtiles] [options]')
|
||||||
|
@ -95,7 +97,7 @@ const startWithInputFile = async (inputFile) => {
|
||||||
inputFile = path.resolve(process.cwd(), inputFile);
|
inputFile = path.resolve(process.cwd(), inputFile);
|
||||||
inputFilePath = path.dirname(inputFile);
|
inputFilePath = path.dirname(inputFile);
|
||||||
|
|
||||||
const inputFileStats = fs.statSync(inputFile);
|
const inputFileStats = await fsp.stat(inputFile);
|
||||||
if (!inputFileStats.isFile() || inputFileStats.size === 0) {
|
if (!inputFileStats.isFile() || inputFileStats.size === 0) {
|
||||||
console.log(`ERROR: Not a valid input file: `);
|
console.log(`ERROR: Not a valid input file: `);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
@ -140,11 +142,11 @@ const startWithInputFile = async (inputFile) => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = fs.readdirSync(path.resolve(styleDir, 'styles'));
|
const styles = await fsp.readdir(path.resolve(styleDir, 'styles'));
|
||||||
for (const styleName of styles) {
|
for (const styleName of styles) {
|
||||||
const styleFileRel = styleName + '/style.json';
|
const styleFileRel = styleName + '/style.json';
|
||||||
const styleFile = path.resolve(styleDir, 'styles', styleFileRel);
|
const styleFile = path.resolve(styleDir, 'styles', styleFileRel);
|
||||||
if (fs.existsSync(styleFile)) {
|
if (await existsP(styleFile)) {
|
||||||
config['styles'][styleName] = {
|
config['styles'][styleName] = {
|
||||||
style: styleFileRel,
|
style: styleFileRel,
|
||||||
tilejson: {
|
tilejson: {
|
||||||
|
@ -189,7 +191,7 @@ const startWithInputFile = async (inputFile) => {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.getInfo((err, info) => {
|
instance.getInfo(async (err, info) => {
|
||||||
if (err || !info) {
|
if (err || !info) {
|
||||||
console.log('ERROR: Metadata missing in the MBTiles.');
|
console.log('ERROR: Metadata missing in the MBTiles.');
|
||||||
console.log(
|
console.log(
|
||||||
|
@ -207,11 +209,11 @@ const startWithInputFile = async (inputFile) => {
|
||||||
mbtiles: path.basename(inputFile),
|
mbtiles: path.basename(inputFile),
|
||||||
};
|
};
|
||||||
|
|
||||||
const styles = fs.readdirSync(path.resolve(styleDir, 'styles'));
|
const styles = await fsp.readdir(path.resolve(styleDir, 'styles'));
|
||||||
for (const styleName of styles) {
|
for (const styleName of styles) {
|
||||||
const styleFileRel = styleName + '/style.json';
|
const styleFileRel = styleName + '/style.json';
|
||||||
const styleFile = path.resolve(styleDir, 'styles', styleFileRel);
|
const styleFile = path.resolve(styleDir, 'styles', styleFileRel);
|
||||||
if (fs.existsSync(styleFile)) {
|
if (await existsP(styleFile)) {
|
||||||
config['styles'][styleName] = {
|
config['styles'][styleName] = {
|
||||||
style: styleFileRel,
|
style: styleFileRel,
|
||||||
tilejson: {
|
tilejson: {
|
||||||
|
@ -254,10 +256,10 @@ fs.stat(path.resolve(opts.config), async (err, stats) => {
|
||||||
return startWithInputFile(inputFile);
|
return startWithInputFile(inputFile);
|
||||||
} else {
|
} else {
|
||||||
// try to find in the cwd
|
// try to find in the cwd
|
||||||
const files = fs.readdirSync(process.cwd());
|
const files = await fsp.readdir(process.cwd());
|
||||||
for (const filename of files) {
|
for (const filename of files) {
|
||||||
if (filename.endsWith('.mbtiles') || filename.endsWith('.pmtiles')) {
|
if (filename.endsWith('.mbtiles') || filename.endsWith('.pmtiles')) {
|
||||||
const inputFilesStats = fs.statSync(filename);
|
const inputFilesStats = await fsp.stat(filename);
|
||||||
if (inputFilesStats.isFile() && inputFilesStats.size > 0) {
|
if (inputFilesStats.isFile() && inputFilesStats.size > 0) {
|
||||||
inputFile = filename;
|
inputFile = filename;
|
||||||
break;
|
break;
|
||||||
|
|
14
src/promises.js
Normal file
14
src/promises.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import util from 'node:util';
|
||||||
|
import fsp from 'node:fs/promises';
|
||||||
|
import zlib from 'zlib';
|
||||||
|
|
||||||
|
export const gzipP = util.promisify(zlib.gzip);
|
||||||
|
export const gunzipP = util.promisify(zlib.gunzip);
|
||||||
|
export const existsP = async (path) => {
|
||||||
|
try {
|
||||||
|
await fsp.access(path); // Defaults to F_OK: indicating that the file is visible to the calling process
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,8 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import fs from 'node:fs';
|
import fsp from 'node:fs/promises';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import zlib from 'zlib';
|
|
||||||
|
|
||||||
import clone from 'clone';
|
import clone from 'clone';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
|
@ -10,12 +9,13 @@ import MBTiles from '@mapbox/mbtiles';
|
||||||
import Pbf from 'pbf';
|
import Pbf from 'pbf';
|
||||||
import { VectorTile } from '@mapbox/vector-tile';
|
import { VectorTile } from '@mapbox/vector-tile';
|
||||||
|
|
||||||
import { getTileUrls, isValidHttpUrl, fixTileJSONCenter } from './utils.js';
|
import { fixTileJSONCenter, getTileUrls, isValidHttpUrl } from './utils.js';
|
||||||
import {
|
import {
|
||||||
openPMtiles,
|
|
||||||
getPMtilesInfo,
|
getPMtilesInfo,
|
||||||
getPMtilesTile,
|
getPMtilesTile,
|
||||||
|
openPMtiles,
|
||||||
} from './pmtiles_adapter.js';
|
} from './pmtiles_adapter.js';
|
||||||
|
import { gunzipP, gzipP } from './promises.js';
|
||||||
|
|
||||||
export const serve_data = {
|
export const serve_data = {
|
||||||
init: (options, repo) => {
|
init: (options, repo) => {
|
||||||
|
@ -89,12 +89,12 @@ export const serve_data = {
|
||||||
headers['Content-Encoding'] = 'gzip';
|
headers['Content-Encoding'] = 'gzip';
|
||||||
res.set(headers);
|
res.set(headers);
|
||||||
|
|
||||||
data = zlib.gzipSync(data);
|
data = await gzipP(data);
|
||||||
|
|
||||||
return res.status(200).send(data);
|
return res.status(200).send(data);
|
||||||
}
|
}
|
||||||
} else if (item.sourceType === 'mbtiles') {
|
} else if (item.sourceType === 'mbtiles') {
|
||||||
item.source.getTile(z, x, y, (err, data, headers) => {
|
item.source.getTile(z, x, y, async (err, data, headers) => {
|
||||||
let isGzipped;
|
let isGzipped;
|
||||||
if (err) {
|
if (err) {
|
||||||
if (/does not exist/.test(err.message)) {
|
if (/does not exist/.test(err.message)) {
|
||||||
|
@ -114,7 +114,7 @@ export const serve_data = {
|
||||||
data.slice(0, 2).indexOf(Buffer.from([0x1f, 0x8b])) === 0;
|
data.slice(0, 2).indexOf(Buffer.from([0x1f, 0x8b])) === 0;
|
||||||
if (options.dataDecoratorFunc) {
|
if (options.dataDecoratorFunc) {
|
||||||
if (isGzipped) {
|
if (isGzipped) {
|
||||||
data = zlib.unzipSync(data);
|
data = await gunzipP(data);
|
||||||
isGzipped = false;
|
isGzipped = false;
|
||||||
}
|
}
|
||||||
data = options.dataDecoratorFunc(id, 'data', data, z, x, y);
|
data = options.dataDecoratorFunc(id, 'data', data, z, x, y);
|
||||||
|
@ -126,7 +126,7 @@ export const serve_data = {
|
||||||
headers['Content-Type'] = 'application/json';
|
headers['Content-Type'] = 'application/json';
|
||||||
|
|
||||||
if (isGzipped) {
|
if (isGzipped) {
|
||||||
data = zlib.unzipSync(data);
|
data = await gunzipP(data);
|
||||||
isGzipped = false;
|
isGzipped = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ export const serve_data = {
|
||||||
res.set(headers);
|
res.set(headers);
|
||||||
|
|
||||||
if (!isGzipped) {
|
if (!isGzipped) {
|
||||||
data = zlib.gzipSync(data);
|
data = await gzipP(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status(200).send(data);
|
return res.status(200).send(data);
|
||||||
|
@ -212,7 +212,7 @@ export const serve_data = {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!isValidHttpUrl(inputFile)) {
|
if (!isValidHttpUrl(inputFile)) {
|
||||||
const inputFileStats = fs.statSync(inputFile);
|
const inputFileStats = await fsp.stat(inputFile);
|
||||||
if (!inputFileStats.isFile() || inputFileStats.size === 0) {
|
if (!inputFileStats.isFile() || inputFileStats.size === 0) {
|
||||||
throw Error(`Not valid input file: "${inputFile}"`);
|
throw Error(`Not valid input file: "${inputFile}"`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ import fs from 'node:fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import url from 'url';
|
import url from 'url';
|
||||||
import util from 'util';
|
import util from 'util';
|
||||||
import zlib from 'zlib';
|
|
||||||
import sharp from 'sharp';
|
import sharp from 'sharp';
|
||||||
import clone from 'clone';
|
import clone from 'clone';
|
||||||
import Color from 'color';
|
import Color from 'color';
|
||||||
|
@ -42,6 +41,8 @@ import {
|
||||||
getPMtilesTile,
|
getPMtilesTile,
|
||||||
} from './pmtiles_adapter.js';
|
} from './pmtiles_adapter.js';
|
||||||
import { renderOverlay, renderWatermark, renderAttribution } from './render.js';
|
import { renderOverlay, renderWatermark, renderAttribution } from './render.js';
|
||||||
|
import fsp from 'node:fs/promises';
|
||||||
|
import { gunzipP } from './promises.js';
|
||||||
|
|
||||||
const FLOAT_PATTERN = '[+-]?(?:\\d+|\\d+.?\\d+)';
|
const FLOAT_PATTERN = '[+-]?(?:\\d+|\\d+.?\\d+)';
|
||||||
const PATH_PATTERN =
|
const PATH_PATTERN =
|
||||||
|
@ -943,7 +944,7 @@ export const serve_rendered = {
|
||||||
callback(null, response);
|
callback(null, response);
|
||||||
}
|
}
|
||||||
} else if (sourceType === 'mbtiles') {
|
} else if (sourceType === 'mbtiles') {
|
||||||
source.getTile(z, x, y, (err, data, headers) => {
|
source.getTile(z, x, y, async (err, data, headers) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (options.verbose)
|
if (options.verbose)
|
||||||
console.log('MBTiles error, serving empty', err);
|
console.log('MBTiles error, serving empty', err);
|
||||||
|
@ -962,7 +963,7 @@ export const serve_rendered = {
|
||||||
|
|
||||||
if (format === 'pbf') {
|
if (format === 'pbf') {
|
||||||
try {
|
try {
|
||||||
response.data = zlib.unzipSync(data);
|
response.data = await gunzipP(data);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(
|
console.log(
|
||||||
'Skipping incorrect header for tile mbtiles://%s/%s/%s/%s.pbf',
|
'Skipping incorrect header for tile mbtiles://%s/%s/%s/%s.pbf',
|
||||||
|
@ -1039,7 +1040,7 @@ export const serve_rendered = {
|
||||||
const styleFile = params.style;
|
const styleFile = params.style;
|
||||||
const styleJSONPath = path.resolve(options.paths.styles, styleFile);
|
const styleJSONPath = path.resolve(options.paths.styles, styleFile);
|
||||||
try {
|
try {
|
||||||
styleJSON = JSON.parse(fs.readFileSync(styleJSONPath));
|
styleJSON = JSON.parse(await fsp.readFile(styleJSONPath));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Error parsing style file');
|
console.log('Error parsing style file');
|
||||||
return false;
|
return false;
|
||||||
|
@ -1145,7 +1146,7 @@ export const serve_rendered = {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isValidHttpUrl(inputFile)) {
|
if (!isValidHttpUrl(inputFile)) {
|
||||||
const inputFileStats = fs.statSync(inputFile);
|
const inputFileStats = await fsp.stat(inputFile);
|
||||||
if (!inputFileStats.isFile() || inputFileStats.size === 0) {
|
if (!inputFileStats.isFile() || inputFileStats.size === 0) {
|
||||||
throw Error(`Not valid PMTiles file: "${inputFile}"`);
|
throw Error(`Not valid PMTiles file: "${inputFile}"`);
|
||||||
}
|
}
|
||||||
|
@ -1187,9 +1188,9 @@ export const serve_rendered = {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
queue.push(
|
queue.push(
|
||||||
new Promise((resolve, reject) => {
|
new Promise(async (resolve, reject) => {
|
||||||
inputFile = path.resolve(options.paths.mbtiles, inputFile);
|
inputFile = path.resolve(options.paths.mbtiles, inputFile);
|
||||||
const inputFileStats = fs.statSync(inputFile);
|
const inputFileStats = await fsp.stat(inputFile);
|
||||||
if (!inputFileStats.isFile() || inputFileStats.size === 0) {
|
if (!inputFileStats.isFile() || inputFileStats.size === 0) {
|
||||||
throw Error(`Not valid MBTiles file: "${inputFile}"`);
|
throw Error(`Not valid MBTiles file: "${inputFile}"`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ export const serve_style = {
|
||||||
|
|
||||||
let styleFileData;
|
let styleFileData;
|
||||||
try {
|
try {
|
||||||
styleFileData = fs.readFileSync(styleFile);
|
styleFileData = fs.readFileSync(styleFile); // TODO: could be made async if this function was
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Error reading style file');
|
console.log('Error reading style file');
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -2,9 +2,10 @@
|
||||||
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fsPromises from 'fs/promises';
|
import fsPromises from 'fs/promises';
|
||||||
import fs, { existsSync } from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import clone from 'clone';
|
import clone from 'clone';
|
||||||
import { combine } from '@jsse/pbfont';
|
import { combine } from '@jsse/pbfont';
|
||||||
|
import { existsP } from './promises.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restrict user input to an allowed set of options.
|
* Restrict user input to an allowed set of options.
|
||||||
|
@ -225,7 +226,7 @@ export const listFonts = async (fontPath) => {
|
||||||
const stats = await fsPromises.stat(path.join(fontPath, file));
|
const stats = await fsPromises.stat(path.join(fontPath, file));
|
||||||
if (
|
if (
|
||||||
stats.isDirectory() &&
|
stats.isDirectory() &&
|
||||||
existsSync(path.join(fontPath, file, '0-255.pbf'))
|
(await existsP(path.join(fontPath, file, '0-255.pbf')))
|
||||||
) {
|
) {
|
||||||
existingFonts[path.basename(file)] = true;
|
existingFonts[path.basename(file)] = true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue