Merge d5765328ec
into 9d222c1dec
This commit is contained in:
commit
6319bdfdaa
5 changed files with 80 additions and 0 deletions
|
@ -37,6 +37,7 @@ Example:
|
|||
"pbfAlias": "pbf",
|
||||
"serveAllFonts": false,
|
||||
"serveAllStyles": false,
|
||||
"watchMbtiles": false,
|
||||
"serveStaticMaps": true,
|
||||
"allowRemoteMarkerIcons": true,
|
||||
"allowInlineMarkerImages": true,
|
||||
|
@ -171,6 +172,13 @@ If this option is enabled, all the styles from the ``paths.styles`` will be serv
|
|||
The process will also watch for changes in this directory and remove/add more styles dynamically.
|
||||
It is recommended to also use the ``serveAllFonts`` option when using this option.
|
||||
|
||||
``watchMbtiles``
|
||||
------------------------
|
||||
|
||||
If this option is enabled, all the opened Mbtiles are watched for changes and automatically reloaded.
|
||||
The new data is then severed immediately. There is a small downtime for rendered endpoints.
|
||||
Mbtiles have to be replaced atomically. i.e. moving the file from the same filesystem. Modifying an existing file will crash the server.
|
||||
|
||||
``serveStaticMaps``
|
||||
------------------------
|
||||
|
||||
|
|
|
@ -111,6 +111,7 @@ const startWithInputFile = async (inputFile) => {
|
|||
|
||||
const config = {
|
||||
options: {
|
||||
watchMbtiles: true,
|
||||
paths: {
|
||||
root: styleDir,
|
||||
fonts: 'fonts',
|
||||
|
|
|
@ -365,6 +365,9 @@ export const serve_data = {
|
|||
|
||||
return app;
|
||||
},
|
||||
remove: (repo, id) => {
|
||||
delete repo[id];
|
||||
},
|
||||
add: async (options, repo, params, id, publicUrl) => {
|
||||
let inputFile;
|
||||
let inputType;
|
||||
|
|
|
@ -883,6 +883,7 @@ export const serve_rendered = {
|
|||
renderersStatic: [],
|
||||
sources: {},
|
||||
sourceTypes: {},
|
||||
styleFile: '',
|
||||
};
|
||||
|
||||
let styleJSON;
|
||||
|
@ -1080,6 +1081,7 @@ export const serve_rendered = {
|
|||
};
|
||||
|
||||
const styleFile = params.style;
|
||||
map.styleFile = styleFile;
|
||||
const styleJSONPath = path.resolve(options.paths.styles, styleFile);
|
||||
try {
|
||||
styleJSON = JSON.parse(await fsp.readFile(styleJSONPath));
|
||||
|
@ -1300,6 +1302,9 @@ export const serve_rendered = {
|
|||
item.map.renderersStatic.forEach((pool) => {
|
||||
pool.close();
|
||||
});
|
||||
Object.entries(item.map.sources).forEach(([key, source]) => {
|
||||
delete item.map.sources[key];
|
||||
});
|
||||
}
|
||||
delete repo[id];
|
||||
},
|
||||
|
|
|
@ -292,6 +292,69 @@ function start(opts) {
|
|||
startupPromises.push(
|
||||
serve_data.add(options, serving.data, item, id, opts.publicUrl),
|
||||
);
|
||||
|
||||
if (options.watchMbtiles) {
|
||||
console.log(`Watching Mbtile "${item.mbtiles}" for changes...`);
|
||||
|
||||
const watcher = chokidar.watch(
|
||||
path.join(options.paths.mbtiles, item.mbtiles),
|
||||
{
|
||||
ignoreInitial: true,
|
||||
// wait 10 seconds after the last change before updating. Otherwise, cases where a file is constantly replaced
|
||||
// will create race conditions and can crash the server
|
||||
awaitWriteFinish: { stabilityThreshold: 10000 },
|
||||
},
|
||||
);
|
||||
|
||||
watcher.on('all', (eventType, filename) => {
|
||||
if (filename) {
|
||||
if (eventType === 'add' || eventType === 'change') {
|
||||
console.log(`MBTiles "${filename}" changed, updating...`);
|
||||
|
||||
serve_data.remove(serving.data, id);
|
||||
let newItem = {
|
||||
mbtiles: filename,
|
||||
};
|
||||
serve_data.add(options, serving.data, newItem, id, opts.publicUrl);
|
||||
|
||||
if (!isLight) {
|
||||
Object.entries(serving.rendered).forEach(
|
||||
([serving_key, serving_value]) => {
|
||||
// check if source is used in serving
|
||||
Object.values(serving_value.map.sources).forEach(
|
||||
(source_value) => {
|
||||
const newFileInode = fs.statSync(filename).ino;
|
||||
// we check if the filename is the same and the inode has changed
|
||||
// the inode check is necessary because it could be that multiple mbtiles
|
||||
// were changed and we already changed to the new file. This can lead to race-conditions
|
||||
if (
|
||||
source_value.filename === filename &&
|
||||
source_value._stat.ino !== newFileInode
|
||||
) {
|
||||
// remove from serving and add back
|
||||
serve_style.remove(serving.styles, serving_key);
|
||||
serve_rendered.remove(serving.rendered, serving_key);
|
||||
|
||||
const item = {
|
||||
style: serving_value.map.styleFile,
|
||||
};
|
||||
addStyle(serving_key, item, false, false);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
// we intentionally don't handle the 'unlink' event here. If the file is deleted, the file descriptor is still valid,
|
||||
// everything will continue to work
|
||||
}
|
||||
});
|
||||
|
||||
watcher.on('error', (error) => {
|
||||
console.error(`Failed to watch file: ${error}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (options.serveAllStyles) {
|
||||
|
|
Loading…
Reference in a new issue