diff --git a/NEWS.md b/NEWS.md index f690de2d..4dd3f191 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,14 +4,22 @@ Released 2019-mm-dd Announcements: +- Fix uncaught exception: TypeError: Cannot read property 'id' of undefined +- Implements graceful shutdown for: + - system signals `SIGINT` and `SIGTERM` + - events `uncaughtException`, `unhandledRejection` and, `ENOMEM` - Experimental support for listing features in a grid when the map uses the dynamic agregation. - Numeric histogram performance improvement (#1080) - Fix boolean aggregation layer option not working when numbers of rows are above the threshold (#1082) - Update deps: - - windshaft@4.13.5: + - camshat@0.64.0 + - windshaft@5.1.0: - Upgrade `tilelive-mapnik` to version `0.6.18-cdb20` - Upgrade `@carto/tilelive-bridge` to version `2.5.1-cdb12` - - Upgrade `grainstore` to version `1.11.0`, do not hang when child process is not able to generate a Mapnik XML + - Upgrade `grainstore` to version `2.0.0` + - Upgrade `torque.js` to version `3.1.0` + - Upgrade `canvas` to version `2.4.1` + ## 7.0.0 Released 2019-02-22 diff --git a/app.js b/app.js index f4de15fe..2f9bff99 100755 --- a/app.js +++ b/app.js @@ -14,8 +14,9 @@ var logError = console.error.bind(console); // jshint undef:true var nodejsVersion = process.versions.node; -if (!semver.satisfies(nodejsVersion, '>=6.9.0')) { - logError(`Node version ${nodejsVersion} is not supported, please use Node.js 6.9 or higher.`); +const { engines } = require('./package.json'); +if (!semver.satisfies(nodejsVersion, engines.node)) { + logError(`Node version ${nodejsVersion} is not supported, please use Node.js ${engines.node}.`); process.exit(1); } @@ -177,10 +178,6 @@ process.on('SIGHUP', function() { }); }); -process.on('uncaughtException', function(err) { - global.logger.error('Uncaught exception: ' + err.stack); -}); - if (global.gc) { var gcInterval = Number.isFinite(global.environment.gc_interval) ? global.environment.gc_interval : @@ -231,3 +228,45 @@ function getGCTypeValue (type) { return value; } + +addHandlers(listener, global.logger, 45000); + +function addHandlers(listener, logger, killTimeout) { + process.on('uncaughtException', exitProcess(listener, logger, killTimeout)); + process.on('unhandledRejection', exitProcess(listener, logger, killTimeout)); + process.on('ENOMEM', exitProcess(listener, logger, killTimeout)); + process.on('SIGINT', exitProcess(listener, logger, killTimeout)); + process.on('SIGTERM', exitProcess(listener, logger, killTimeout)); +} + +function exitProcess (listener, logger, killTimeout) { + return function exitProcessFn (signal) { + scheduleForcedExit(killTimeout, logger); + + let code = 0; + + if (!['SIGINT', 'SIGTERM'].includes(signal)) { + const err = signal instanceof Error ? signal : new Error(signal); + signal = undefined; + code = 1; + + logger.fatal(err); + } else { + logger.info(`Process has received signal: ${signal}`); + } + + logger.info(`Process is going to exit with code: ${code}`); + listener.close(() => global.log4js.shutdown(() => process.exit(code))); + }; +} + +function scheduleForcedExit (killTimeout, logger) { + // Schedule exit if there is still ongoing work to deal with + const killTimer = setTimeout(() => { + logger.info('Process didn\'t close on time. Force exit'); + process.exit(1); + }, killTimeout); + + // Don't keep the process open just for this + killTimer.unref(); +} diff --git a/lib/cartodb/models/mapconfig/provider/named-map-provider.js b/lib/cartodb/models/mapconfig/provider/named-map-provider.js index 513fb7b7..298920a1 100644 --- a/lib/cartodb/models/mapconfig/provider/named-map-provider.js +++ b/lib/cartodb/models/mapconfig/provider/named-map-provider.js @@ -74,8 +74,8 @@ module.exports = class NamedMapMapConfigProvider extends BaseMapConfigProvider { JSON.parse(this.config) : this.config; } catch (e) { - const error = new Error('malformed config parameter, should be a valid JSON'); - this.err = error; + const err = new Error('malformed config parameter, should be a valid JSON'); + this.err = err; return callback(err); } diff --git a/lib/cartodb/server.js b/lib/cartodb/server.js index 3e1b3c4c..ad998ef9 100644 --- a/lib/cartodb/server.js +++ b/lib/cartodb/server.js @@ -1,6 +1,7 @@ 'use strict'; const _ = require('underscore'); +const semver = require('semver'); const express = require('express'); const windshaft = require('windshaft'); const { mapnik } = windshaft; @@ -82,7 +83,7 @@ function getAndValidateVersions(options) { dependenciesToValidate.forEach(function(depName) { var declaredDependencyVersion = declaredDependencies[depName]; var installedDependencyVersion = installedDependenciesVersions[depName]; - if (declaredDependencyVersion !== installedDependencyVersion) { + if (!semver.satisfies(installedDependencyVersion,declaredDependencyVersion)) { warn( 'Dependency="%s" installed version="%s" does not match declared version="%s". Check your installation.', depName, installedDependencyVersion, declaredDependencyVersion diff --git a/package-lock.json b/package-lock.json index 667facd8..02ae9234 100644 --- a/package-lock.json +++ b/package-lock.json @@ -291,9 +291,9 @@ "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" }, "camshaft": { - "version": "0.63.4", - "resolved": "https://registry.npmjs.org/camshaft/-/camshaft-0.63.4.tgz", - "integrity": "sha512-v6CpIyL2lCjCCUhksTrUSsmCUcDfjn9BD0ULs9lkz0TUwHfEMy3w2Q14NMsBXCCu0OjuiivnbPNm5XGjQe5Awg==", + "version": "0.64.0", + "resolved": "https://registry.npmjs.org/camshaft/-/camshaft-0.64.0.tgz", + "integrity": "sha512-5FPNdrkNlgfqq+1X2KWfc1MlZ/si8sqPmjogUZSLY/RnJIp+XlS80HDIsF3FYKSvmps9GO8k2Qi73fRll0EyGg==", "requires": { "async": "^1.5.2", "bunyan": "1.8.1", @@ -335,10 +335,57 @@ } }, "canvas": { - "version": "github:cartodb/node-canvas#45bd3c7cc5e6f99ba75b0d417b6ac6384b43083d", - "from": "github:cartodb/node-canvas#1.6.2-cdb3", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.4.1.tgz", + "integrity": "sha512-SaFomFqDuuuSTScTHQ7nXc5ea71Ieb8ctvwXjR7vzLsBMfp3euTv2xsTY70zIoC5r4sSQZYXv6tiHiORJ4y1vg==", "requires": { - "nan": "^2.4.0" + "nan": "^2.12.1", + "node-pre-gyp": "^0.11.0" + }, + "dependencies": { + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "nan": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", + "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==" + }, + "node-pre-gyp": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", + "integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==", + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "requires": { + "glob": "^7.1.3" + } + } } }, "carto": { @@ -3852,9 +3899,9 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "torque.js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/torque.js/-/torque.js-3.0.0.tgz", - "integrity": "sha512-xwxRaf3ftq25BoMySqFMB3aHlhC3o0Xj02peILusijFWJzg+ewd7m+9XxAUBbROC11ZUjW7K5d2bZ48j4RmiTQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/torque.js/-/torque.js-3.1.0.tgz", + "integrity": "sha512-xX0BVo/gAy5A2Qx17dbgzjB2cnzuSDwzohdT1hGaKbG0jveL3sKgKE5VyzlN1/l4hP3p6f/m20HvZo3waIawCQ==", "requires": { "carto": "github:cartodb/carto#85881d99dd7fcf2c4e16478b04db67108d27a50c", "d3": "3.5.17", @@ -4059,7 +4106,7 @@ "@carto/cartonik": "github:cartodb/cartonik#89dea6126674fef4e2d6800dc8b86e4cd353ae76", "@carto/mapnik": "3.6.2-carto.11", "abaculus": "github:cartodb/abaculus#3283c523d8bd4bdec78d90166d9c23ff09865ca8", - "canvas": "github:cartodb/node-canvas#45bd3c7cc5e6f99ba75b0d417b6ac6384b43083d", + "canvas": "^2.4.1", "carto": "github:cartodb/carto#85881d99dd7fcf2c4e16478b04db67108d27a50c", "cartodb-psql": "0.13.1", "debug": "3.1.0", @@ -4070,7 +4117,7 @@ "request": "2.87.0", "semver": "5.5.0", "sphericalmercator": "1.0.5", - "torque.js": "^3.0.0", + "torque.js": "^3.1.0", "underscore": "1.6.0" } }, diff --git a/package.json b/package.json index 9850a598..85a302d0 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "@carto/fqdn-sync": "0.2.2", "basic-auth": "2.0.0", "body-parser": "1.18.3", - "camshaft": "0.63.4", + "camshaft": "^0.64.0", "cartodb-psql": "0.13.1", "cartodb-query-tables": "0.4.0", "cartodb-redis": "2.1.0", diff --git a/test/fixtures/blend/blend-filtering-layers-0.3-zxy-1.0.0.png b/test/fixtures/blend/blend-filtering-layers-0.3-zxy-1.0.0.png index 1a8077ab..ae486bc4 100644 Binary files a/test/fixtures/blend/blend-filtering-layers-0.3-zxy-1.0.0.png and b/test/fixtures/blend/blend-filtering-layers-0.3-zxy-1.0.0.png differ diff --git a/test/fixtures/blend/blend-filtering-layers-1.2.5-zxy-1.0.0.png b/test/fixtures/blend/blend-filtering-layers-1.2.5-zxy-1.0.0.png index 7816b1bd..d2fbd612 100644 Binary files a/test/fixtures/blend/blend-filtering-layers-1.2.5-zxy-1.0.0.png and b/test/fixtures/blend/blend-filtering-layers-1.2.5-zxy-1.0.0.png differ diff --git a/test/fixtures/blend/blend-filtering-layers-1.3-zxy-1.0.0.png b/test/fixtures/blend/blend-filtering-layers-1.3-zxy-1.0.0.png index 8ef5c201..6866f948 100644 Binary files a/test/fixtures/blend/blend-filtering-layers-1.3-zxy-1.0.0.png and b/test/fixtures/blend/blend-filtering-layers-1.3-zxy-1.0.0.png differ diff --git a/test/fixtures/blend/blend-plain-torque-2.1.1.png b/test/fixtures/blend/blend-plain-torque-2.1.1.png index efba5f22..f5f8a312 100644 Binary files a/test/fixtures/blend/blend-plain-torque-2.1.1.png and b/test/fixtures/blend/blend-plain-torque-2.1.1.png differ diff --git a/test/fixtures/blend/blend-plain-torque-2.2.1.png b/test/fixtures/blend/blend-plain-torque-2.2.1.png index 74497a48..f401d1c2 100644 Binary files a/test/fixtures/blend/blend-plain-torque-2.2.1.png and b/test/fixtures/blend/blend-plain-torque-2.2.1.png differ diff --git a/test/fixtures/torque/populated_places_simple_reduced-2.1.1.png b/test/fixtures/torque/populated_places_simple_reduced-2.1.1.png index 77b4e93e..daf52d26 100644 Binary files a/test/fixtures/torque/populated_places_simple_reduced-2.1.1.png and b/test/fixtures/torque/populated_places_simple_reduced-2.1.1.png differ diff --git a/test/fixtures/torque/populated_places_simple_reduced-2.2.1.png b/test/fixtures/torque/populated_places_simple_reduced-2.2.1.png index 86d9ac0a..5fe7cdb7 100644 Binary files a/test/fixtures/torque/populated_places_simple_reduced-2.2.1.png and b/test/fixtures/torque/populated_places_simple_reduced-2.2.1.png differ diff --git a/test/fixtures/torque/populated_places_simple_reduced-turbo-carto-2.2.1.png b/test/fixtures/torque/populated_places_simple_reduced-turbo-carto-2.2.1.png index 59f0d5c1..43266f4a 100644 Binary files a/test/fixtures/torque/populated_places_simple_reduced-turbo-carto-2.2.1.png and b/test/fixtures/torque/populated_places_simple_reduced-turbo-carto-2.2.1.png differ