CartoDB-SQL-API/app.js

161 lines
4.7 KiB
JavaScript
Raw Normal View History

#!/usr/bin/env node
/*
* SQL API loader
* ===============
*
* node app [environment]
*
* environments: [development, test, production]
*
*/
2015-05-12 23:33:41 +08:00
var fs = require('fs');
var path = require('path');
const fqdn = require('@carto/fqdn-sync');
var argv = require('yargs')
.usage('Usage: $0 <environment> [options]')
.help('h')
.example(
2016-09-15 06:40:25 +08:00
'$0 production -c /etc/sql-api/config.js',
'start server in production environment with /etc/sql-api/config.js as config file'
)
.alias('h', 'help')
.alias('c', 'config')
.nargs('c', 1)
.describe('c', 'Load configuration from path')
.argv;
var environmentArg = argv._[0] || process.env.NODE_ENV || 'development';
var configurationFile = path.resolve(argv.config || './config/environments/' + environmentArg + '.js');
if (!fs.existsSync(configurationFile)) {
console.error('Configuration file "%s" does not exist', configurationFile);
process.exit(1);
2015-05-12 23:33:41 +08:00
}
global.settings = require(configurationFile);
var ENVIRONMENT = argv._[0] || process.env.NODE_ENV || global.settings.environment;
2016-09-15 05:10:14 +08:00
process.env.NODE_ENV = ENVIRONMENT;
2015-05-12 23:33:41 +08:00
var availableEnvironments = ['development', 'production', 'test', 'staging'];
// sanity check arguments
2016-09-15 05:10:14 +08:00
if (availableEnvironments.indexOf(ENVIRONMENT) === -1) {
console.error("node app.js [environment]");
console.error("Available environments: " + availableEnvironments.join(', '));
process.exit(1);
}
global.settings.api_hostname = fqdn.hostname();
2014-03-13 18:52:40 +08:00
2015-05-12 23:33:41 +08:00
global.log4js = require('log4js');
var log4jsConfig = {
appenders: [],
replaceConsole: true
2014-03-13 18:52:40 +08:00
};
2016-09-15 03:02:56 +08:00
if ( global.settings.log_filename ) {
var logFilename = path.resolve(global.settings.log_filename);
var logDirectory = path.dirname(logFilename);
if (!fs.existsSync(logDirectory)) {
console.error("Log filename directory does not exist: " + logDirectory);
process.exit(1);
}
console.log("Logs will be written to " + logFilename);
log4jsConfig.appenders.push(
{ type: "file", absolute: true, filename: logFilename }
);
} else {
log4jsConfig.appenders.push(
{ type: "console", layout: { type:'basic' } }
);
}
global.log4js.configure(log4jsConfig);
2015-05-12 23:33:41 +08:00
global.logger = global.log4js.getLogger();
2014-03-13 18:52:40 +08:00
// kick off controller
2015-05-12 23:33:41 +08:00
if ( ! global.settings.base_url ) {
global.settings.base_url = '/api/*';
}
2014-03-13 20:50:53 +08:00
var version = require("./package").version;
2017-03-30 22:13:17 +08:00
var StatsClient = require('./app/stats/client');
if (global.settings.statsd) {
// Perform keyword substitution in statsd
if (global.settings.statsd.prefix) {
global.settings.statsd.prefix = global.settings.statsd.prefix.replace(/:host/, fqdn.reverse());
2017-03-30 22:13:17 +08:00
}
}
2017-03-30 23:32:22 +08:00
var statsClient = StatsClient.getInstance(global.settings.statsd);
2017-03-30 22:13:17 +08:00
2017-03-30 23:32:22 +08:00
var server = require('./app/server')(statsClient);
var listener = server.listen(global.settings.node_port, global.settings.node_host);
listener.on('listening', function() {
2017-02-10 17:03:36 +08:00
console.info("Using Node.js %s", process.version);
console.info('Using configuration file "%s"', configurationFile);
console.log(
"CartoDB SQL API %s listening on %s:%s PID=%d (%s)",
version, global.settings.node_host, global.settings.node_port, process.pid, ENVIRONMENT
);
});
process.on('uncaughtException', function(err) {
2015-05-12 23:33:41 +08:00
global.logger.error('Uncaught exception: ' + err.stack);
});
process.on('SIGHUP', function() {
global.log4js.clearAndShutdownAppenders(function() {
global.log4js.configure(log4jsConfig);
2015-05-12 23:33:41 +08:00
global.logger = global.log4js.getLogger();
console.log('Log files reloaded');
});
2016-09-30 23:10:52 +08:00
if (server.batch && server.batch.logger) {
server.batch.logger.reopenFileStreams();
}
if (server.dataIngestionLogger) {
server.dataIngestionLogger.reopenFileStreams();
2016-09-30 23:10:52 +08:00
}
});
process.on('SIGTERM', function () {
server.batch.stop();
server.batch.drain(function (err) {
if (err) {
console.log('Exit with error');
return process.exit(1);
}
console.log('Exit gracefully');
process.exit(0);
});
});
2017-03-30 22:27:34 +08:00
function isGteMinVersion(version, minVersion) {
var versionMatch = /[a-z]?([0-9]*)/.exec(version);
if (versionMatch) {
var majorVersion = parseInt(versionMatch[1], 10);
if (Number.isFinite(majorVersion)) {
return majorVersion >= minVersion;
}
}
return false;
}
if (global.gc && isGteMinVersion(process.version, 6)) {
var gcInterval = Number.isFinite(global.settings.gc_interval) ?
global.settings.gc_interval :
10000;
if (gcInterval > 0) {
setInterval(function gcForcedCycle() {
var start = Date.now();
global.gc();
2017-03-30 23:32:22 +08:00
statsClient.timing('sqlapi.gc', Date.now() - start);
2017-03-30 22:27:34 +08:00
}, gcInterval);
}
}