From 01212920ae4954dda339aec7e29d0eb69cfb27b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Tue, 26 Mar 2019 18:47:57 +0100 Subject: [PATCH 01/10] Draft --- app.js | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/app.js b/app.js index f4de15fe..6031a55d 100755 --- a/app.js +++ b/app.js @@ -14,7 +14,7 @@ var logError = console.error.bind(console); // jshint undef:true var nodejsVersion = process.versions.node; -if (!semver.satisfies(nodejsVersion, '>=6.9.0')) { +if (!semver.satisfies(nodejsVersion, '>=10.15.1')) { logError(`Node version ${nodejsVersion} is not supported, please use Node.js 6.9 or higher.`); process.exit(1); } @@ -177,10 +177,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 +227,44 @@ function getGCTypeValue (type) { return value; } + +addHandlers(listener, logger, 45000); + +function addHandlers(listener, logger, killTimeout) { + process.on('uncaughtException', exitProcess(listener, logger, killTimeout)); + process.on('unhandledRejection', 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(() => log4js.shutdown(() => process.exit(1))); + }; +} + +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(); +} From b222dd15c09a3e38c9e2483a2d2b6d8b7629b10b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Tue, 26 Mar 2019 18:54:42 +0100 Subject: [PATCH 02/10] Handle ENOMEM signal emitted by grainstore --- app.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app.js b/app.js index 6031a55d..31db66d5 100755 --- a/app.js +++ b/app.js @@ -233,6 +233,7 @@ addHandlers(listener, 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)); } From b314acf5b52a0f3092a907a42c619b1437b569eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Tue, 26 Mar 2019 18:57:49 +0100 Subject: [PATCH 03/10] PLase jshint --- app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index 31db66d5..ed04bd30 100755 --- a/app.js +++ b/app.js @@ -228,7 +228,7 @@ function getGCTypeValue (type) { return value; } -addHandlers(listener, logger, 45000); +addHandlers(listener, global.logger, 45000); function addHandlers(listener, logger, killTimeout) { process.on('uncaughtException', exitProcess(listener, logger, killTimeout)); @@ -255,7 +255,7 @@ function exitProcess (listener, logger, killTimeout) { } logger.info(`Process is going to exit with code: ${code}`); - listener.close(() => log4js.shutdown(() => process.exit(1))); + listener.close(() => global.log4js.shutdown(() => process.exit(1))); }; } From 7efb8abd97d6ee8129411b0a15cfa11ea68cf431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Tue, 26 Mar 2019 19:06:10 +0100 Subject: [PATCH 04/10] Use code while exiting --- app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.js b/app.js index ed04bd30..e2dd65e7 100755 --- a/app.js +++ b/app.js @@ -255,7 +255,7 @@ function exitProcess (listener, logger, killTimeout) { } logger.info(`Process is going to exit with code: ${code}`); - listener.close(() => global.log4js.shutdown(() => process.exit(1))); + listener.close(() => global.log4js.shutdown(() => process.exit(code))); }; } From 53b19d576c4ecbc71f23a286c6b460c1d2107dad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Tue, 26 Mar 2019 19:14:39 +0100 Subject: [PATCH 05/10] Update dynamic Node.js version check --- app.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index e2dd65e7..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, '>=10.15.1')) { - 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); } From 035acb343e518a9bd77c0e6635aca7dc8d508ed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 27 Mar 2019 11:38:25 +0100 Subject: [PATCH 06/10] Fix uncaught exception: TypeError: Cannot read property 'id' of undefined --- lib/cartodb/models/mapconfig/provider/named-map-provider.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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); } From c30a81acbeebaf1364aa3f8a9074ebee492e0e0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 29 Mar 2019 13:18:40 +0100 Subject: [PATCH 07/10] Update NEWS --- NEWS.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index f690de2d..b8853e06 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,14 +4,19 @@ Released 2019-mm-dd Announcements: +- 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 From c3b1b469b29e699a88f7b0e84e8f8f1f78bec9cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 29 Mar 2019 13:21:35 +0100 Subject: [PATCH 08/10] Update NEWS --- NEWS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.md b/NEWS.md index b8853e06..7e3ffa67 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,7 @@ 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` @@ -18,6 +19,7 @@ Announcements: - Upgrade `grainstore` to version `2.0.0` - Upgrade `torque.js` to version `3.0.0` + ## 7.0.0 Released 2019-02-22 From 5fdc501836d033e836a23bb370089a22114be07d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 29 Mar 2019 13:26:38 +0100 Subject: [PATCH 09/10] Upgrade camshaft to version 0.64.0 --- package-lock.json | 20 ++++++++++---------- package.json | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index d3616e4a..59c87929 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", @@ -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": { diff --git a/package.json b/package.json index b6a87350..c394c05e 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", From 674c276b578b000f01ce0ecad124296d7c818e28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 29 Mar 2019 13:36:16 +0100 Subject: [PATCH 10/10] Upgrade windshaft to version 5 --- package-lock.json | 34 +++++++++++++++++----------------- package.json | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/package-lock.json b/package-lock.json index 59c87929..98a33e68 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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==" } } }, @@ -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 c394c05e..8304b552 100644 --- a/package.json +++ b/package.json @@ -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": {