diff --git a/NEWS.md b/NEWS.md index f690de2d..7e3ffa67 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,14 +4,21 @@ 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.0.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.0.0` + ## 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/package-lock.json b/package-lock.json index d3616e4a..98a33e68 100644 --- a/package-lock.json +++ b/package-lock.json @@ -283,9 +283,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", @@ -297,7 +297,7 @@ "dependencies": { "request": { "version": "2.85.0", - "resolved": "http://registry.npmjs.org/request/-/request-2.85.0.tgz", + "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", "requires": { "aws-sign2": "~0.7.0", @@ -1933,9 +1933,9 @@ } }, "generic-pool": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.6.1.tgz", - "integrity": "sha512-iMmD/pY4q0+V+f8o4twE9JPeqfNuX+gJAaIPB3B0W1lFkBOtTxBo6B0HxHPgGhzQA8jego7EWopcYq/UDJO2KA==" + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.7.1.tgz", + "integrity": "sha512-ug6DAZoNgWm6q5KhPFA+hzXfBLFQu5sTXxPpv44DmE0A2g+CiHoq9LTVdkXpZMkYVMoGw83F6W+WT0h0MFMK/w==" }, "get-caller-file": { "version": "1.0.3", @@ -1980,9 +1980,9 @@ "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" }, "grainstore": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/grainstore/-/grainstore-1.11.0.tgz", - "integrity": "sha512-JuEnCHX+qseEgD+Ii5V8SI7VlbSMSE/Jzq0UWC+sdZFi8mFcz15Nj8EKRkF28Rxj2NoWg2tFYMiUb9h8LQEOdg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grainstore/-/grainstore-2.0.0.tgz", + "integrity": "sha512-eDCr8kkpvKaenLqomRnYPQT8ARJZh+QzqtCJ+iHCLyj2pAfGSEnnld6XtCnQdbtCgJsFPrUaaWn12DqCmJiDnQ==", "requires": { "carto": "0.16.3", "debug": "~3.1.0", @@ -2010,9 +2010,9 @@ }, "dependencies": { "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" } } }, @@ -2030,9 +2030,9 @@ }, "dependencies": { "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" } } }, @@ -2170,7 +2170,7 @@ }, "hoek": { "version": "4.2.1", - "resolved": "http://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" }, "hosted-git-info": { @@ -2762,7 +2762,7 @@ }, "ncp": { "version": "2.0.0", - "resolved": "http://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", "optional": true }, @@ -3468,7 +3468,7 @@ }, "rimraf": { "version": "2.4.5", - "resolved": "http://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", "optional": true, "requires": { @@ -3938,9 +3938,9 @@ } }, "torque.js": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/torque.js/-/torque.js-2.17.1.tgz", - "integrity": "sha512-jZuw5P3muNoILsmiN2kaclzczYW6h9HBSQo5riEB1ub/oNzmj7FqvFJOJKG3dbsxuAqOMn0+AwcQUC3Fb0YTRw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/torque.js/-/torque.js-3.0.0.tgz", + "integrity": "sha512-xwxRaf3ftq25BoMySqFMB3aHlhC3o0Xj02peILusijFWJzg+ewd7m+9XxAUBbROC11ZUjW7K5d2bZ48j4RmiTQ==", "requires": { "carto": "github:cartodb/carto#85881d99dd7fcf2c4e16478b04db67108d27a50c", "d3": "3.5.17", @@ -4139,9 +4139,9 @@ "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" }, "windshaft": { - "version": "4.13.5", - "resolved": "https://registry.npmjs.org/windshaft/-/windshaft-4.13.5.tgz", - "integrity": "sha512-e4ZG+ofpuk74hASiqRTD6OqsNpziiXWzr8V5ZAGzcR3ErmlvaM4rEqLplI7AZ9Y3Hx5KUW0H7veCfxf1vhHQEg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/windshaft/-/windshaft-5.0.0.tgz", + "integrity": "sha512-OMjOhiJa7tA8Pty41bTAXf9d6uIlMU3aCyzS2/cZ620MfRF6RhORnOMiTa/iV856KAiqWFjl7U1MJnIs2xe0MQ==", "requires": { "@carto/mapnik": "3.6.2-carto.11", "@carto/tilelive-bridge": "github:cartodb/tilelive-bridge#8ce03ffd995cf0986b9d6ee7ffbbf310908625c9", @@ -4151,7 +4151,7 @@ "cartodb-psql": "0.13.1", "debug": "3.1.0", "dot": "1.1.2", - "grainstore": "^1.11.0", + "grainstore": "^2.0.0", "queue-async": "1.1.0", "redis-mpool": "0.7.0", "request": "2.87.0", @@ -4159,7 +4159,7 @@ "sphericalmercator": "1.0.5", "tilelive": "5.12.3", "tilelive-mapnik": "github:cartodb/tilelive-mapnik#3f2021f6c5fd720bf09114ed4e012579564723c0", - "torque.js": "2.17.1", + "torque.js": "^3.0.0", "underscore": "1.6.0" } }, diff --git a/package.json b/package.json index b6a87350..8304b552 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", @@ -49,7 +49,7 @@ "step-profiler": "0.3.0", "turbo-carto": "0.21.0", "underscore": "1.6.0", - "windshaft": "4.13.5", + "windshaft": "^5.0.0", "yargs": "11.1.0" }, "devDependencies": {