From d30027e9926c51b4543e0b88fc2052889dc6e41b Mon Sep 17 00:00:00 2001 From: Petr Sloup Date: Wed, 10 May 2017 08:51:26 +0200 Subject: [PATCH] Modify all `serve_*` modules to return a Promise (preparation for #140) --- src/serve_data.js | 32 +++++++++------ src/serve_font.js | 25 +++++++----- src/serve_rendered.js | 34 +++++++++------- src/serve_style.js | 4 +- src/server.js | 93 +++++++++++++++++++++++++++---------------- test/setup.js | 1 + 6 files changed, 119 insertions(+), 70 deletions(-) diff --git a/src/serve_data.js b/src/serve_data.js index 0f76f0e..2195d53 100644 --- a/src/serve_data.js +++ b/src/serve_data.js @@ -34,20 +34,24 @@ module.exports = function(options, repo, params, id, styles) { if (!mbtilesFileStats.isFile() || mbtilesFileStats.size == 0) { throw Error('Not valid MBTiles file: ' + mbtilesFile); } - var source = new mbtiles(mbtilesFile, function(err) { - source.getInfo(function(err, info) { - tileJSON['name'] = id; - tileJSON['format'] = 'pbf'; + var source; + var sourceInfoPromise = new Promise(function(resolve, reject) { + source = new mbtiles(mbtilesFile, function(err) { + source.getInfo(function(err, info) { + tileJSON['name'] = id; + tileJSON['format'] = 'pbf'; - Object.assign(tileJSON, info); + Object.assign(tileJSON, info); - tileJSON['tilejson'] = '2.0.0'; - delete tileJSON['filesize']; - delete tileJSON['mtime']; - delete tileJSON['scheme']; + tileJSON['tilejson'] = '2.0.0'; + delete tileJSON['filesize']; + delete tileJSON['mtime']; + delete tileJSON['scheme']; - Object.assign(tileJSON, params.tilejson || {}); - utils.fixTileJSONCenter(tileJSON); + Object.assign(tileJSON, params.tilejson || {}); + utils.fixTileJSONCenter(tileJSON); + resolve(); + }); }); }); @@ -161,5 +165,9 @@ module.exports = function(options, repo, params, id, styles) { return res.send(info); }); - return app; + return new Promise(function(resolve, reject) { + sourceInfoPromise.then(function() { + resolve(app); + }); + }); }; diff --git a/src/serve_font.js b/src/serve_font.js index 954476b..8374709 100644 --- a/src/serve_font.js +++ b/src/serve_font.js @@ -15,16 +15,19 @@ module.exports = function(options, allowedFonts) { var fontPath = options.paths.fonts; var existingFonts = {}; - fs.readdir(options.paths.fonts, function(err, files) { - files.forEach(function(file) { - fs.stat(path.join(fontPath, file), function(err, stats) { - if (!err) { - if (stats.isDirectory() && - fs.existsSync(path.join(fontPath, file, '0-255.pbf'))) { - existingFonts[path.basename(file)] = true; + var fontListingPromise = new Promise(function(resolve, reject) { + fs.readdir(options.paths.fonts, function(err, files) { + files.forEach(function(file) { + fs.stat(path.join(fontPath, file), function(err, stats) { + if (!err) { + if (stats.isDirectory() && + fs.existsSync(path.join(fontPath, file, '0-255.pbf'))) { + existingFonts[path.basename(file)] = true; + } } - } + }); }); + resolve(); }); }); @@ -55,5 +58,9 @@ module.exports = function(options, allowedFonts) { ); }); - return app; + return new Promise(function(resolve, reject) { + fontListingPromise.then(function() { + resolve(app); + }); + }); }; diff --git a/src/serve_rendered.js b/src/serve_rendered.js index 2b5aa60..1b94d54 100644 --- a/src/serve_rendered.js +++ b/src/serve_rendered.js @@ -1,7 +1,6 @@ 'use strict'; -var async = require('async'), - advancedPool = require('advanced-pool'), +var advancedPool = require('advanced-pool'), fs = require('fs'), path = require('path'), util = require('util'), @@ -59,15 +58,18 @@ module.exports = function(options, repo, params, id, dataResolver) { }; var existingFonts = {}; - fs.readdir(options.paths.fonts, function(err, files) { - files.forEach(function(file) { - fs.stat(path.join(options.paths.fonts, file), function(err, stats) { - if (!err) { - if (stats.isDirectory()) { - existingFonts[path.basename(file)] = true; + var fontListingPromise = new Promise(function(resolve, reject) { + fs.readdir(options.paths.fonts, function(err, files) { + files.forEach(function(file) { + fs.stat(path.join(options.paths.fonts, file), function(err, stats) { + if (!err) { + if (stats.isDirectory()) { + existingFonts[path.basename(file)] = true; + } } - } + }); }); + resolve(); }); }); @@ -223,7 +225,7 @@ module.exports = function(options, repo, params, id, dataResolver) { } } - queue.push(function(callback) { + queue.push(new Promise(function(resolve, reject) { mbtilesFile = path.resolve(options.paths.mbtiles, mbtilesFile); var mbtilesFileStats = fs.statSync(mbtilesFile); if (!mbtilesFileStats.isFile() || mbtilesFileStats.size == 0) { @@ -279,14 +281,14 @@ module.exports = function(options, repo, params, id, dataResolver) { } tileJSON.attribution += source.attribution; } - callback(null); + resolve(); }); }); - }); + })); } }); - async.parallel(queue, function(err, results) { + var renderersReadyPromise = Promise.all(queue).then(function() { // TODO: make pool sizes configurable for (var s = 1; s <= maxScaleFactor; s++) { var minPoolSize = 2; @@ -692,5 +694,9 @@ module.exports = function(options, repo, params, id, dataResolver) { return res.send(info); }); - return app; + return new Promise(function(resolve, reject) { + Promise.all([fontListingPromise, renderersReadyPromise]).then(function() { + resolve(app); + }); + }); }; diff --git a/src/serve_style.js b/src/serve_style.js index 11ab57a..aa793ef 100644 --- a/src/serve_style.js +++ b/src/serve_style.js @@ -117,5 +117,7 @@ module.exports = function(options, repo, params, id, reportTiles, reportFont) { }); }); - return app; + return new Promise(function(resolve, reject) { + resolve(app); + }); }; diff --git a/src/server.js b/src/server.js index f903321..1ebd59c 100644 --- a/src/server.js +++ b/src/server.js @@ -76,6 +76,8 @@ function start(opts) { paths.sprites = path.resolve(paths.root, paths.sprites || ''); paths.mbtiles = path.resolve(paths.root, paths.mbtiles || ''); + var startupPromises = []; + var checkPath = function(type) { if (!fs.existsSync(paths[type])) { console.error('The specified path for "' + type + '" does not exist (' + paths[type] + ').'); @@ -101,7 +103,7 @@ function start(opts) { } if (item.serve_data !== false) { - app.use('/styles/', serve_style(options, serving.styles, item, id, + startupPromises.push(serve_style(options, serving.styles, item, id, function(mbtiles, fromData) { var dataItemId; Object.keys(data).forEach(function(id) { @@ -130,28 +132,38 @@ function start(opts) { } }, function(font) { serving.fonts[font] = true; + }).then(function(sub) { + app.use('/styles/', sub); })); } if (item.serve_rendered !== false) { if (serve_rendered) { - app.use('/styles/' + id + '/', - serve_rendered(options, serving.rendered, item, id, - function(mbtiles) { - var mbtilesFile; - Object.keys(data).forEach(function(id) { - if (id == mbtiles) { - mbtilesFile = data[id].mbtiles; + startupPromises.push( + serve_rendered(options, serving.rendered, item, id, + function(mbtiles) { + var mbtilesFile; + Object.keys(data).forEach(function(id) { + if (id == mbtiles) { + mbtilesFile = data[id].mbtiles; + } + }); + return mbtilesFile; } - }); - return mbtilesFile; - })); + ).then(function(sub) { + app.use('/styles/' + id + '/', sub); + }) + ); } else { item.serve_rendered = false; } } }); - app.use('/', serve_font(options, serving.fonts)); + startupPromises.push( + serve_font(options, serving.fonts).then(function(sub) { + app.use('/', sub); + }) + ); Object.keys(data).forEach(function(id) { var item = data[id]; @@ -160,7 +172,11 @@ function start(opts) { return; } - app.use('/data/', serve_data(options, serving.data, item, id, serving.styles)); + startupPromises.push( + serve_data(options, serving.data, item, id, serving.styles).then(function(sub) { + app.use('/data/', sub); + }) + ); }); app.get('/styles.json', function(req, res, next) { @@ -221,28 +237,32 @@ function start(opts) { templateFile = path.resolve(paths.root, options.frontPage); } } - fs.readFile(templateFile, function(err, content) { - if (err) { - console.error('Template not found:', err); - } - var compiled = handlebars.compile(content.toString()); - - app.use(urlPath, function(req, res, next) { - var data = {}; - if (dataGetter) { - data = dataGetter(req); - if (!data) { - return res.status(404).send('Not found'); - } + startupPromises.push(new Promise(function(resolve, reject) { + fs.readFile(templateFile, function(err, content) { + if (err) { + console.error('Template not found:', err); + reject(err); } - data['server_version'] = packageJson.name + ' v' + packageJson.version; - data['is_light'] = isLight; - data['key_query_part'] = - req.query.key ? 'key=' + req.query.key + '&' : ''; - data['key_query'] = req.query.key ? '?key=' + req.query.key : ''; - return res.status(200).send(compiled(data)); + var compiled = handlebars.compile(content.toString()); + + app.use(urlPath, function(req, res, next) { + var data = {}; + if (dataGetter) { + data = dataGetter(req); + if (!data) { + return res.status(404).send('Not found'); + } + } + data['server_version'] = packageJson.name + ' v' + packageJson.version; + data['is_light'] = isLight; + data['key_query_part'] = + req.query.key ? 'key=' + req.query.key + '&' : ''; + data['key_query'] = req.query.key ? '?key=' + req.query.key : ''; + return res.status(200).send(compiled(data)); + }); + resolve(); }); - }); + })); }; serveTemplate('/$', 'index', function(req) { @@ -355,6 +375,10 @@ function start(opts) { return data; }); + var startupPromise = Promise.all(startupPromises).then(function() { + console.log('Startup complete'); + }); + var server = app.listen(process.env.PORT || opts.port, process.env.BIND || opts.bind, function() { var address = this.address().address; if (address.indexOf('::') === 0) { @@ -368,7 +392,8 @@ function start(opts) { return { app: app, - server: server + server: server, + startupPromise: startupPromise }; } diff --git a/test/setup.js b/test/setup.js index b752949..963bb26 100644 --- a/test/setup.js +++ b/test/setup.js @@ -12,6 +12,7 @@ before(function() { }); global.app = running.app; global.server = running.server; + return running.startupPromise; }); after(function() {