Merge branch 'master' into avoid-scan-to-discover-queues
This commit is contained in:
commit
da2a98cdb5
9
NEWS.md
9
NEWS.md
@ -1,9 +1,16 @@
|
|||||||
#Changelog
|
#Changelog
|
||||||
|
|
||||||
## 1.43.2
|
## 1.44.1
|
||||||
Released 2017-mm-dd
|
Released 2017-mm-dd
|
||||||
|
|
||||||
|
|
||||||
|
## 1.44.0
|
||||||
|
Released 2017-03-30
|
||||||
|
|
||||||
|
Announcements:
|
||||||
|
* Active GC interval for Node.js >=v6.
|
||||||
|
|
||||||
|
|
||||||
## 1.43.1
|
## 1.43.1
|
||||||
Released 2017-01-16
|
Released 2017-01-16
|
||||||
|
|
||||||
|
38
app.js
38
app.js
@ -11,6 +11,7 @@
|
|||||||
*/
|
*/
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
var os = require('os');
|
||||||
|
|
||||||
var argv = require('yargs')
|
var argv = require('yargs')
|
||||||
.usage('Usage: $0 <environment> [options]')
|
.usage('Usage: $0 <environment> [options]')
|
||||||
@ -80,7 +81,17 @@ if ( ! global.settings.base_url ) {
|
|||||||
|
|
||||||
var version = require("./package").version;
|
var version = require("./package").version;
|
||||||
|
|
||||||
var server = require('./app/server')();
|
var StatsClient = require('./app/stats/client');
|
||||||
|
if (global.settings.statsd) {
|
||||||
|
// Perform keyword substitution in statsd
|
||||||
|
if (global.settings.statsd.prefix) {
|
||||||
|
var hostToken = os.hostname().split('.').reverse().join('.');
|
||||||
|
global.settings.statsd.prefix = global.settings.statsd.prefix.replace(/:host/, hostToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var statsClient = StatsClient.getInstance(global.settings.statsd);
|
||||||
|
|
||||||
|
var server = require('./app/server')(statsClient);
|
||||||
var listener = server.listen(global.settings.node_port, global.settings.node_host);
|
var listener = server.listen(global.settings.node_port, global.settings.node_host);
|
||||||
listener.on('listening', function() {
|
listener.on('listening', function() {
|
||||||
console.info("Using Node.js %s", process.version);
|
console.info("Using Node.js %s", process.version);
|
||||||
@ -119,3 +130,28 @@ process.on('SIGTERM', function () {
|
|||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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();
|
||||||
|
statsClient.timing('sqlapi.gc', Date.now() - start);
|
||||||
|
}, gcInterval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -16,9 +16,7 @@
|
|||||||
|
|
||||||
var express = require('express');
|
var express = require('express');
|
||||||
var bodyParser = require('./middlewares/body-parser');
|
var bodyParser = require('./middlewares/body-parser');
|
||||||
var os = require('os');
|
|
||||||
var Profiler = require('./stats/profiler-proxy');
|
var Profiler = require('./stats/profiler-proxy');
|
||||||
var StatsD = require('node-statsd').StatsD;
|
|
||||||
var _ = require('underscore');
|
var _ = require('underscore');
|
||||||
var LRU = require('lru-cache');
|
var LRU = require('lru-cache');
|
||||||
|
|
||||||
@ -49,8 +47,8 @@ process.env.PGAPPNAME = process.env.PGAPPNAME || 'cartodb_sqlapi';
|
|||||||
// override Date.toJSON
|
// override Date.toJSON
|
||||||
require('./utils/date_to_json');
|
require('./utils/date_to_json');
|
||||||
|
|
||||||
// jshint maxcomplexity:12
|
// jshint maxcomplexity:9
|
||||||
function App() {
|
function App(statsClient) {
|
||||||
|
|
||||||
var app = express();
|
var app = express();
|
||||||
|
|
||||||
@ -107,45 +105,6 @@ function App() {
|
|||||||
app.use(global.log4js.connectLogger(global.log4js.getLogger(), _.defaults(loggerOpts, {level:'info'})));
|
app.use(global.log4js.connectLogger(global.log4js.getLogger(), _.defaults(loggerOpts, {level:'info'})));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize statsD client if requested
|
|
||||||
var statsd_client;
|
|
||||||
if ( global.settings.statsd ) {
|
|
||||||
|
|
||||||
// Perform keyword substitution in statsd
|
|
||||||
if ( global.settings.statsd.prefix ) {
|
|
||||||
var host_token = os.hostname().split('.').reverse().join('.');
|
|
||||||
global.settings.statsd.prefix = global.settings.statsd.prefix.replace(/:host/, host_token);
|
|
||||||
}
|
|
||||||
|
|
||||||
statsd_client = new StatsD(global.settings.statsd);
|
|
||||||
statsd_client.last_error = { msg:'', count:0 };
|
|
||||||
statsd_client.socket.on('error', function(err) {
|
|
||||||
var last_err = statsd_client.last_error;
|
|
||||||
var last_msg = last_err.msg;
|
|
||||||
var this_msg = ''+err;
|
|
||||||
if ( this_msg !== last_msg ) {
|
|
||||||
console.error("statsd client socket error: " + err);
|
|
||||||
statsd_client.last_error.count = 1;
|
|
||||||
statsd_client.last_error.msg = this_msg;
|
|
||||||
} else {
|
|
||||||
++last_err.count;
|
|
||||||
if ( ! last_err.interval ) {
|
|
||||||
//console.log("Installing interval");
|
|
||||||
statsd_client.last_error.interval = setInterval(function() {
|
|
||||||
var count = statsd_client.last_error.count;
|
|
||||||
if ( count > 1 ) {
|
|
||||||
console.error("last statsd client socket error repeated " + count + " times");
|
|
||||||
statsd_client.last_error.count = 1;
|
|
||||||
//console.log("Clearing interval");
|
|
||||||
clearInterval(statsd_client.last_error.interval);
|
|
||||||
statsd_client.last_error.interval = null;
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
app.use(cors());
|
app.use(cors());
|
||||||
|
|
||||||
// Use step-profiler
|
// Use step-profiler
|
||||||
@ -159,7 +118,7 @@ function App() {
|
|||||||
var profile = global.settings.useProfiler;
|
var profile = global.settings.useProfiler;
|
||||||
req.profiler = new Profiler({
|
req.profiler = new Profiler({
|
||||||
profile: profile,
|
profile: profile,
|
||||||
statsd_client: statsd_client
|
statsd_client: statsClient
|
||||||
});
|
});
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
@ -193,10 +152,10 @@ function App() {
|
|||||||
var genericController = new GenericController();
|
var genericController = new GenericController();
|
||||||
genericController.route(app);
|
genericController.route(app);
|
||||||
|
|
||||||
var queryController = new QueryController(userDatabaseService, tableCache, statsd_client);
|
var queryController = new QueryController(userDatabaseService, tableCache, statsClient);
|
||||||
queryController.route(app);
|
queryController.route(app);
|
||||||
|
|
||||||
var jobController = new JobController(userDatabaseService, jobService, statsd_client);
|
var jobController = new JobController(userDatabaseService, jobService, statsClient);
|
||||||
jobController.route(app);
|
jobController.route(app);
|
||||||
|
|
||||||
var cacheStatusController = new CacheStatusController(tableCache);
|
var cacheStatusController = new CacheStatusController(tableCache);
|
||||||
@ -213,7 +172,7 @@ function App() {
|
|||||||
if (global.settings.environment !== 'test' && isBatchProcess) {
|
if (global.settings.environment !== 'test' && isBatchProcess) {
|
||||||
var batchName = global.settings.api_hostname || 'batch';
|
var batchName = global.settings.api_hostname || 'batch';
|
||||||
app.batch = batchFactory(
|
app.batch = batchFactory(
|
||||||
metadataBackend, redisPool, batchName, statsd_client, global.settings.batch_log_filename
|
metadataBackend, redisPool, batchName, statsClient, global.settings.batch_log_filename
|
||||||
);
|
);
|
||||||
app.batch.start();
|
app.batch.start();
|
||||||
}
|
}
|
||||||
|
73
app/stats/client.js
Normal file
73
app/stats/client.js
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
var _ = require('underscore');
|
||||||
|
var debug = require('debug')('windshaft:stats_client');
|
||||||
|
var StatsD = require('node-statsd').StatsD;
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
/**
|
||||||
|
* Returns an StatsD instance or an stub object that replicates the StatsD public interface so there is no need to
|
||||||
|
* keep checking if the stats_client is instantiated or not.
|
||||||
|
*
|
||||||
|
* The first call to this method implies all future calls will use the config specified in the very first call.
|
||||||
|
*
|
||||||
|
* TODO: It's far from ideal to use make this a singleton, improvement desired.
|
||||||
|
* We proceed this way to be able to use StatsD from several places sharing one single StatsD instance.
|
||||||
|
*
|
||||||
|
* @param config Configuration for StatsD, if undefined it will return an stub
|
||||||
|
* @returns {StatsD|Object}
|
||||||
|
*/
|
||||||
|
getInstance: function(config) {
|
||||||
|
|
||||||
|
if (!this.instance) {
|
||||||
|
|
||||||
|
var instance;
|
||||||
|
|
||||||
|
if (config) {
|
||||||
|
instance = new StatsD(config);
|
||||||
|
instance.last_error = { msg: '', count: 0 };
|
||||||
|
instance.socket.on('error', function (err) {
|
||||||
|
var last_err = instance.last_error;
|
||||||
|
var last_msg = last_err.msg;
|
||||||
|
var this_msg = '' + err;
|
||||||
|
if (this_msg !== last_msg) {
|
||||||
|
debug("statsd client socket error: " + err);
|
||||||
|
instance.last_error.count = 1;
|
||||||
|
instance.last_error.msg = this_msg;
|
||||||
|
} else {
|
||||||
|
++last_err.count;
|
||||||
|
if (!last_err.interval) {
|
||||||
|
instance.last_error.interval = setInterval(function () {
|
||||||
|
var count = instance.last_error.count;
|
||||||
|
if (count > 1) {
|
||||||
|
debug("last statsd client socket error repeated " + count + " times");
|
||||||
|
instance.last_error.count = 1;
|
||||||
|
clearInterval(instance.last_error.interval);
|
||||||
|
instance.last_error.interval = null;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var stubFunc = function (stat, value, sampleRate, callback) {
|
||||||
|
if (_.isFunction(callback)) {
|
||||||
|
callback(null, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
instance = {
|
||||||
|
timing: stubFunc,
|
||||||
|
increment: stubFunc,
|
||||||
|
decrement: stubFunc,
|
||||||
|
gauge: stubFunc,
|
||||||
|
unique: stubFunc,
|
||||||
|
set: stubFunc,
|
||||||
|
sendAll: stubFunc,
|
||||||
|
send: stubFunc
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.instance = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.instance;
|
||||||
|
}
|
||||||
|
};
|
2
npm-shrinkwrap.json
generated
2
npm-shrinkwrap.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cartodb_sql_api",
|
"name": "cartodb_sql_api",
|
||||||
"version": "1.43.2",
|
"version": "1.44.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bintrees": {
|
"bintrees": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"cartodb"
|
"cartodb"
|
||||||
],
|
],
|
||||||
"version": "1.43.2",
|
"version": "1.44.1",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git://github.com/CartoDB/CartoDB-SQL-API.git"
|
"url": "git://github.com/CartoDB/CartoDB-SQL-API.git"
|
||||||
|
Loading…
Reference in New Issue
Block a user