Use dynamic pool of map instances to reduce waiting times (issue #3)
This commit is contained in:
parent
4f9b8c1a1b
commit
dc096012ef
2 changed files with 76 additions and 78 deletions
|
@ -12,11 +12,11 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "1.5.2",
|
"async": "1.5.2",
|
||||||
"async-lock": "0.3.8",
|
"advanced-pool": "0.3.1",
|
||||||
"clone": "1.0.2",
|
"clone": "1.0.2",
|
||||||
"cors": "2.7.1",
|
"cors": "2.7.1",
|
||||||
"express": "4.13.4",
|
"express": "4.13.4",
|
||||||
"mapbox-gl-native": "3.0.2-earcut",
|
"mapbox-gl-native": "3.0.2",
|
||||||
"mbtiles": "0.8.2",
|
"mbtiles": "0.8.2",
|
||||||
"morgan": "1.7.0",
|
"morgan": "1.7.0",
|
||||||
"nomnom": "1.8.1",
|
"nomnom": "1.8.1",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var async = require('async'),
|
var async = require('async'),
|
||||||
asyncLock = require('async-lock'),
|
advancedPool = require('advanced-pool'),
|
||||||
crypto = require('crypto'),
|
crypto = require('crypto'),
|
||||||
fs = require('fs'),
|
fs = require('fs'),
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
|
@ -32,8 +32,6 @@ mbgl.on('message', function(e) {
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = function(maps, options, prefix) {
|
module.exports = function(maps, options, prefix) {
|
||||||
var lock = new asyncLock();
|
|
||||||
|
|
||||||
var app = express().disable('x-powered-by'),
|
var app = express().disable('x-powered-by'),
|
||||||
domains = options.domains,
|
domains = options.domains,
|
||||||
tilePath = '/{z}/{x}/{y}.{format}';
|
tilePath = '/{z}/{x}/{y}.{format}';
|
||||||
|
@ -46,9 +44,11 @@ module.exports = function(maps, options, prefix) {
|
||||||
sources: {},
|
sources: {},
|
||||||
tileJSON: {}
|
tileJSON: {}
|
||||||
};
|
};
|
||||||
if (!maps[prefix]) {
|
|
||||||
var createRenderer = function(ratio) {
|
var styleJSON;
|
||||||
return new mbgl.Map({
|
var createPool = function(ratio, min, max) {
|
||||||
|
var createRenderer = function(ratio, createCallback) {
|
||||||
|
var renderer = new mbgl.Map({
|
||||||
ratio: ratio,
|
ratio: ratio,
|
||||||
request: function(req, callback) {
|
request: function(req, callback) {
|
||||||
var protocol = req.url.split(':')[0];
|
var protocol = req.url.split(':')[0];
|
||||||
|
@ -115,60 +115,66 @@ module.exports = function(maps, options, prefix) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
renderer.load(styleJSON);
|
||||||
|
createCallback(null, renderer);
|
||||||
};
|
};
|
||||||
map.renderers[1] = createRenderer(1);
|
return new advancedPool.Pool({
|
||||||
map.renderers[2] = createRenderer(2);
|
min: min,
|
||||||
map.renderers[3] = createRenderer(3);
|
max: max,
|
||||||
|
create: createRenderer.bind(null, ratio),
|
||||||
var styleJSON = require(path.join(rootPath, styleUrl));
|
destroy: function(renderer) {
|
||||||
|
renderer.release();
|
||||||
map.tileJSON = {
|
|
||||||
'tilejson': '2.0.0',
|
|
||||||
'name': styleJSON.name,
|
|
||||||
'basename': prefix.substr(1),
|
|
||||||
'minzoom': 0,
|
|
||||||
'maxzoom': 20,
|
|
||||||
'bounds': [-180, -85.0511, 180, 85.0511],
|
|
||||||
'format': 'png',
|
|
||||||
'type': 'baselayer'
|
|
||||||
};
|
|
||||||
Object.assign(map.tileJSON, options.options || {});
|
|
||||||
|
|
||||||
var queue = [];
|
|
||||||
Object.keys(styleJSON.sources).forEach(function(name) {
|
|
||||||
var source = styleJSON.sources[name];
|
|
||||||
var url = source.url;
|
|
||||||
if (url.lastIndexOf('mbtiles:', 0) === 0) {
|
|
||||||
// found mbtiles source, replace with info from local file
|
|
||||||
delete source.url;
|
|
||||||
|
|
||||||
queue.push(function(callback) {
|
|
||||||
var mbtilesUrl = url.substring('mbtiles://'.length);
|
|
||||||
map.sources[name] = new mbtiles(path.join(rootPath, mbtilesUrl), function(err) {
|
|
||||||
map.sources[name].getInfo(function(err, info) {
|
|
||||||
Object.assign(source, info);
|
|
||||||
source.basename = name;
|
|
||||||
source.tiles = [
|
|
||||||
// meta url which will be detected when requested
|
|
||||||
'mbtiles://' + name + tilePath.replace('{format}', 'pbf')
|
|
||||||
];
|
|
||||||
callback(null);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
async.parallel(queue, function(err, results) {
|
styleJSON = require(path.join(rootPath, styleUrl));
|
||||||
map.renderers.forEach(function(renderer) {
|
|
||||||
renderer.load(styleJSON);
|
map.tileJSON = {
|
||||||
|
'tilejson': '2.0.0',
|
||||||
|
'name': styleJSON.name,
|
||||||
|
'basename': prefix.substr(1),
|
||||||
|
'minzoom': 0,
|
||||||
|
'maxzoom': 20,
|
||||||
|
'bounds': [-180, -85.0511, 180, 85.0511],
|
||||||
|
'format': 'png',
|
||||||
|
'type': 'baselayer'
|
||||||
|
};
|
||||||
|
Object.assign(map.tileJSON, options.options || {});
|
||||||
|
|
||||||
|
var queue = [];
|
||||||
|
Object.keys(styleJSON.sources).forEach(function(name) {
|
||||||
|
var source = styleJSON.sources[name];
|
||||||
|
var url = source.url;
|
||||||
|
if (url.lastIndexOf('mbtiles:', 0) === 0) {
|
||||||
|
// found mbtiles source, replace with info from local file
|
||||||
|
delete source.url;
|
||||||
|
|
||||||
|
queue.push(function(callback) {
|
||||||
|
var mbtilesUrl = url.substring('mbtiles://'.length);
|
||||||
|
map.sources[name] = new mbtiles(path.join(rootPath, mbtilesUrl), function(err) {
|
||||||
|
map.sources[name].getInfo(function(err, info) {
|
||||||
|
Object.assign(source, info);
|
||||||
|
source.basename = name;
|
||||||
|
source.tiles = [
|
||||||
|
// meta url which will be detected when requested
|
||||||
|
'mbtiles://' + name + tilePath.replace('{format}', 'pbf')
|
||||||
|
];
|
||||||
|
callback(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
|
||||||
maps[prefix] = map;
|
async.parallel(queue, function(err, results) {
|
||||||
} else {
|
// TODO: make pool sizes configurable
|
||||||
map = maps[prefix];
|
map.renderers[1] = createPool(1, 2, 8);
|
||||||
}
|
map.renderers[2] = createPool(2, 2, 4);
|
||||||
|
map.renderers[3] = createPool(3, 2, 4);
|
||||||
|
});
|
||||||
|
|
||||||
|
maps[prefix] = map;
|
||||||
|
|
||||||
var tilePattern = tilePath
|
var tilePattern = tilePath
|
||||||
.replace(/\.(?!.*\.)/, ':scale(' + SCALE_PATTERN + ')?.')
|
.replace(/\.(?!.*\.)/, ':scale(' + SCALE_PATTERN + ')?.')
|
||||||
|
@ -186,29 +192,21 @@ module.exports = function(maps, options, prefix) {
|
||||||
return res.status(404).send('Invalid format');
|
return res.status(404).send('Invalid format');
|
||||||
}
|
}
|
||||||
|
|
||||||
var mbglZ = Math.max(0, z - 1);
|
var pool = map.renderers[scale];
|
||||||
var renderer = map.renderers[scale];
|
pool.acquire(function(err, renderer) {
|
||||||
var params = {
|
var mbglZ = Math.max(0, z - 1);
|
||||||
/*
|
var params = {
|
||||||
debug: {
|
zoom: mbglZ,
|
||||||
tileBorders: true,
|
center: [lon, lat],
|
||||||
parseStatus: true,
|
width: width,
|
||||||
timestamps: true,
|
height: height
|
||||||
collision: true
|
};
|
||||||
},
|
if (z == 0) {
|
||||||
*/
|
params.width *= 2;
|
||||||
zoom: mbglZ,
|
params.height *= 2;
|
||||||
center: [lon, lat],
|
}
|
||||||
width: width,
|
|
||||||
height: height
|
|
||||||
};
|
|
||||||
if (z == 0) {
|
|
||||||
params.width *= 2;
|
|
||||||
params.height *= 2;
|
|
||||||
}
|
|
||||||
lock.acquire(renderer, function(done) {
|
|
||||||
renderer.render(params, function(err, data) {
|
renderer.render(params, function(err, data) {
|
||||||
done();
|
pool.release(renderer);
|
||||||
if (err) console.log(err);
|
if (err) console.log(err);
|
||||||
|
|
||||||
var image = sharp(data, {
|
var image = sharp(data, {
|
||||||
|
|
Loading…
Reference in a new issue